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