xref: /aosp_15_r20/external/webrtc/logging/rtc_event_log/events/rtc_event_field_encoding.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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_FIELD_ENCODING_H_
12 #define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_H_
13 
14 #include <string>
15 #include <vector>
16 
17 #include "absl/types/optional.h"
18 #include "api/array_view.h"
19 #include "api/rtc_event_log/rtc_event.h"
20 #include "logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h"
21 #include "logging/rtc_event_log/events/fixed_length_encoding_parameters_v3.h"
22 #include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
23 #include "rtc_base/logging.h"
24 
25 namespace webrtc {
26 
27 // To maintain backwards compatibility with past (or future) logs,
28 // the constants in this enum must not be changed.
29 // New field types with numerical IDs 5-7 can be added, but old
30 // parsers will fail to parse events containing the new fields.
31 enum class FieldType : uint8_t {
32   kFixed8 = 0,
33   kFixed32 = 1,
34   kFixed64 = 2,
35   kVarInt = 3,
36   kString = 4,
37 };
38 
39 // EventParameters map an event name to a numerical ID.
40 struct EventParameters {
41   // The name is primarily used for debugging purposes.
42   const char* const name;
43   //
44   const RtcEvent::Type id;
45 };
46 
47 // FieldParameters define the encoding for a field.
48 struct FieldParameters {
49   // The name is primarily used for debugging purposes.
50   const char* const name;
51   // Numerical ID for the field. Must be strictly greater than 0,
52   // and unique within each event type.
53   const uint64_t field_id;
54   // Encoding type for the base (i.e. non-delta) field in a batch.
55   const FieldType field_type;
56   // Number of bits after which wrap-around occurs. In most cases,
57   // this should be the number of bits in the field data type, i.e.
58   // 8 for an uint8_t, 32 for a int32_t and so on. However, `value_width`
59   // can be used to achieve a more efficient encoding if it is known
60   // that the field uses a smaller number of bits. For example, a
61   // 15-bit counter could set `value_width` to 15 even if the data is
62   // actually stored in a uint32_t.
63   const uint64_t value_width;
64   // Field ID 0 is reserved for timestamps.
65   static constexpr uint64_t kTimestampField = 0;
66 };
67 
68 // The EventEncoder is used to encode a batch of events.
69 class EventEncoder {
70  public:
71   EventEncoder(EventParameters params, rtc::ArrayView<const RtcEvent*> batch);
72 
73   void EncodeField(const FieldParameters& params,
74                    const std::vector<uint64_t>& values,
75                    const std::vector<bool>* positions = nullptr);
76 
77   void EncodeField(const FieldParameters& params,
78                    const ValuesWithPositions& values);
79 
80   void EncodeField(const FieldParameters& params,
81                    const std::vector<absl::string_view>& values);
82 
83   std::string AsString();
84 
85  private:
86   size_t batch_size_;
87   uint32_t event_tag_;
88   std::vector<std::string> encoded_fields_;
89 };
90 
91 std::string EncodeSingleValue(uint64_t value, FieldType field_type);
92 std::string EncodeDeltasV3(FixedLengthEncodingParametersV3 params,
93                            uint64_t base,
94                            rtc::ArrayView<const uint64_t> values);
95 
96 // Given a batch of RtcEvents and a member pointer, extract that
97 // member from each event in the batch. Signed integer members are
98 // encoded as unsigned, and the bitsize increased so the result can
99 // represented as a std::vector<uint64_t>.
100 // This is intended to be used in conjuction with
101 // EventEncoder::EncodeField to encode a batch of events as follows:
102 // auto values = ExtractRtcEventMember(batch, RtcEventFoo::timestamp_ms);
103 // encoder.EncodeField(timestamp_params, values)
104 template <typename T,
105           typename E,
106           std::enable_if_t<std::is_integral<T>::value, bool> = true>
ExtractRtcEventMember(rtc::ArrayView<const RtcEvent * > batch,const T E::* member)107 std::vector<uint64_t> ExtractRtcEventMember(
108     rtc::ArrayView<const RtcEvent*> batch,
109     const T E::*member) {
110   std::vector<uint64_t> values;
111   values.reserve(batch.size());
112   for (const RtcEvent* event : batch) {
113     RTC_CHECK_EQ(event->GetType(), E::kType);
114     T value = static_cast<const E*>(event)->*member;
115     values.push_back(EncodeAsUnsigned(value));
116   }
117   return values;
118 }
119 
120 // Extract an optional field from a batch of RtcEvents.
121 // The function returns a vector of positions in addition to the vector of
122 // values. The vector `positions` has the same length as the batch where
123 // `positions[i] == true` iff the batch[i]->member has a value.
124 // The values vector only contains the values that exists, so it
125 // may be shorter than the batch.
126 template <typename T,
127           typename E,
128           std::enable_if_t<std::is_integral<T>::value, bool> = true>
ExtractRtcEventMember(rtc::ArrayView<const RtcEvent * > batch,const absl::optional<T> E::* member)129 ValuesWithPositions ExtractRtcEventMember(rtc::ArrayView<const RtcEvent*> batch,
130                                           const absl::optional<T> E::*member) {
131   ValuesWithPositions result;
132   result.position_mask.reserve(batch.size());
133   result.values.reserve(batch.size());
134   for (const RtcEvent* event : batch) {
135     RTC_CHECK_EQ(event->GetType(), E::kType);
136     absl::optional<T> field = static_cast<const E*>(event)->*member;
137     result.position_mask.push_back(field.has_value());
138     if (field.has_value()) {
139       result.values.push_back(EncodeAsUnsigned(field.value()));
140     }
141   }
142   return result;
143 }
144 
145 // Extract an enum field from a batch of RtcEvents.
146 // Requires specializing RtcEventLogEnum<T> for the enum type T.
147 template <typename T,
148           typename E,
149           std::enable_if_t<std::is_enum<T>::value, bool> = true>
ExtractRtcEventMember(rtc::ArrayView<const RtcEvent * > batch,const T E::* member)150 std::vector<uint64_t> ExtractRtcEventMember(
151     rtc::ArrayView<const RtcEvent*> batch,
152     const T E::*member) {
153   std::vector<uint64_t> values;
154   values.reserve(batch.size());
155   for (const RtcEvent* event : batch) {
156     RTC_CHECK_EQ(event->GetType(), E::kType);
157     T value = static_cast<const E*>(event)->*member;
158     values.push_back(RtcEventLogEnum<T>::Encode(value));
159   }
160   return values;
161 }
162 
163 // Extract a string field from a batch of RtcEvents.
164 template <typename E>
ExtractRtcEventMember(rtc::ArrayView<const RtcEvent * > batch,const std::string E::* member)165 std::vector<absl::string_view> ExtractRtcEventMember(
166     rtc::ArrayView<const RtcEvent*> batch,
167     const std::string E::*member) {
168   std::vector<absl::string_view> values;
169   values.reserve(batch.size());
170   for (const RtcEvent* event : batch) {
171     RTC_CHECK_EQ(event->GetType(), E::kType);
172     absl::string_view str = static_cast<const E*>(event)->*member;
173     values.push_back(str);
174   }
175   return values;
176 }
177 
178 }  // namespace webrtc
179 #endif  // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_H_
180