• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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