rtc_event_definition.h (5618B)
1 /* 2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_DEFINITION_H_ 12 #define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_DEFINITION_H_ 13 14 #include <cstdint> 15 #include <string> 16 #include <vector> 17 18 #include "absl/strings/string_view.h" 19 #include "api/array_view.h" 20 #include "api/rtc_event_log/rtc_event.h" 21 #include "logging/rtc_event_log/events/rtc_event_field_encoding.h" 22 #include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h" 23 #include "logging/rtc_event_log/events/rtc_event_log_parse_status.h" 24 25 namespace webrtc { 26 27 template <typename EventType, typename LoggedType, typename T> 28 struct RtcEventFieldDefinition { 29 const T EventType::*event_member; 30 T LoggedType::*logged_member; 31 FieldParameters params; 32 }; 33 34 // Base case 35 template <typename EventType, typename LoggedType, typename... Ts> 36 class RtcEventDefinitionImpl { 37 public: 38 void EncodeImpl(EventEncoder&, ArrayView<const RtcEvent*>) const {} 39 RtcEventLogParseStatus ParseImpl(EventParser&, ArrayView<LoggedType>) const { 40 return RtcEventLogParseStatus::Success(); 41 } 42 }; 43 44 // Recursive case 45 template <typename EventType, typename LoggedType, typename T, typename... Ts> 46 class RtcEventDefinitionImpl<EventType, LoggedType, T, Ts...> { 47 public: 48 constexpr RtcEventDefinitionImpl( 49 RtcEventFieldDefinition<EventType, LoggedType, T> field, 50 RtcEventFieldDefinition<EventType, LoggedType, Ts>... rest) 51 : field_(field), rest_(rest...) {} 52 53 void EncodeImpl(EventEncoder& encoder, 54 ArrayView<const RtcEvent*> batch) const { 55 auto values = ExtractRtcEventMember(batch, field_.event_member); 56 encoder.EncodeField(field_.params, values); 57 rest_.EncodeImpl(encoder, batch); 58 } 59 60 RtcEventLogParseStatus ParseImpl(EventParser& parser, 61 ArrayView<LoggedType> output_batch) const { 62 RtcEventLogParseStatusOr<ArrayView<uint64_t>> result = 63 parser.ParseNumericField(field_.params); 64 if (!result.ok()) 65 return result.status(); 66 auto status = PopulateRtcEventMember(result.value(), field_.logged_member, 67 output_batch); 68 if (!status.ok()) 69 return status; 70 71 return rest_.ParseImpl(parser, output_batch); 72 } 73 74 private: 75 RtcEventFieldDefinition<EventType, LoggedType, T> field_; 76 RtcEventDefinitionImpl<EventType, LoggedType, Ts...> rest_; 77 }; 78 79 // The RtcEventDefinition sets up a mapping between the fields 80 // in an RtcEvent and the corresponding fields in the parsed struct. 81 // For example, an RtcFoo class containing two fields; `uint32_t bar` 82 // and `bool baz` (a log timestamp is always implicitly added) 83 // might have a definition 84 // RtcEventDefinition<RtcFoo, LoggedFoo, uint32_t, bool>( 85 // {"foo", RtcFoo::Type}, 86 // {&RtcFoo::bar_, &LoggedFoo::bar, {"bar", 1, FieldType::kVarInt, 32}}, 87 // {&RtcFoo::baz_, &LoggedFoo::baz, {"baz", 2, FieldType::kFixed8, 1}}, 88 // ); 89 // In addition to defining string names to aid debugging, 90 // this specifies that 91 // * RtcFoo::Type uniquely identifies an RtcFoo in the encoded stream 92 // * The `bar` field has ID 1, is encoded as a VarInt 93 // (when not delta compressed), and wraps around after 32 bits. 94 // * The `baz` field has ID 2, is encoded as an 8-bit field 95 // (when not delta compressed), and wraps around after 1 bit. 96 // Note that the numerical field and event IDs can't be changed since 97 // that would break compatibility with old logs. 98 // In most cases (including all cases where wrap around isn't 99 // expected), the wrap around should be equal to the bitwidth of 100 // the field. 101 template <typename EventType, typename LoggedType, typename... Ts> 102 class RtcEventDefinition { 103 public: 104 constexpr RtcEventDefinition( 105 EventParameters params, 106 RtcEventFieldDefinition<EventType, LoggedType, Ts>... fields) 107 : params_(params), fields_(fields...) {} 108 109 std::string EncodeBatch(ArrayView<const RtcEvent*> batch) const { 110 EventEncoder encoder(params_, batch); 111 fields_.EncodeImpl(encoder, batch); 112 return encoder.AsString(); 113 } 114 115 RtcEventLogParseStatus ParseBatch(absl::string_view s, 116 bool batched, 117 std::vector<LoggedType>& output) const { 118 EventParser parser; 119 auto status = parser.Initialize(s, batched); 120 if (!status.ok()) 121 return status; 122 123 ArrayView<LoggedType> output_batch = 124 ExtendLoggedBatch(output, parser.NumEventsInBatch()); 125 126 constexpr FieldParameters timestamp_params{"timestamp_ms", 127 FieldParameters::kTimestampField, 128 FieldType::kVarInt, 64}; 129 RtcEventLogParseStatusOr<ArrayView<uint64_t>> result = 130 parser.ParseNumericField(timestamp_params); 131 if (!result.ok()) 132 return result.status(); 133 status = PopulateRtcEventTimestamp(result.value(), &LoggedType::timestamp, 134 output_batch); 135 if (!status.ok()) 136 return status; 137 138 return fields_.ParseImpl(parser, output_batch); 139 } 140 141 private: 142 EventParameters params_; 143 RtcEventDefinitionImpl<EventType, LoggedType, Ts...> fields_; 144 }; 145 146 } // namespace webrtc 147 148 #endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_DEFINITION_H_