blob: 056d3421fc068e85fe41bd3a27def77c5e97700c [file] [log] [blame]
Eric Seckler771960c2019-10-22 15:37:12 +01001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "src/trace_processor/importers/proto/track_event_tokenizer.h"
18
19#include "perfetto/base/logging.h"
Lalit Magantid5c45f42020-04-14 21:01:50 +010020#include "src/trace_processor/importers/common/clock_tracker.h"
Lalit Maganti617deae2020-04-14 21:00:49 +010021#include "src/trace_processor/importers/common/process_tracker.h"
22#include "src/trace_processor/importers/common/track_tracker.h"
Eric Seckler771960c2019-10-22 15:37:12 +010023#include "src/trace_processor/importers/proto/packet_sequence_state.h"
Lalit Magantieb63b082020-09-10 14:12:20 +010024#include "src/trace_processor/importers/proto/proto_trace_reader.h"
Lalit Maganti62b741f2020-12-10 18:24:00 +000025#include "src/trace_processor/importers/proto/track_event_tracker.h"
Lalit Maganti7010b332020-02-07 10:51:15 +000026#include "src/trace_processor/storage/stats.h"
27#include "src/trace_processor/storage/trace_storage.h"
Eric Seckler771960c2019-10-22 15:37:12 +010028#include "src/trace_processor/trace_sorter.h"
Alexander Timin97d87852021-05-17 18:01:33 +000029#include "src/trace_processor/util/trace_blob_view.h"
Eric Seckler771960c2019-10-22 15:37:12 +010030
Eric Secklerdc454522020-05-20 19:40:23 +010031#include "protos/perfetto/common/builtin_clock.pbzero.h"
Eric Secklerd2af9892019-11-01 10:10:53 +000032#include "protos/perfetto/trace/trace_packet.pbzero.h"
Sami Kyostilab0686c92020-01-07 12:56:55 +000033#include "protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h"
34#include "protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.h"
Eric Secklerfbd9aed2020-03-10 18:07:38 +000035#include "protos/perfetto/trace/track_event/counter_descriptor.pbzero.h"
Eric Seckler771960c2019-10-22 15:37:12 +010036#include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
37#include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
38#include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
39#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
40
41namespace perfetto {
42namespace trace_processor {
43
Eric Secklerf1497812020-04-30 10:43:23 +010044namespace {
45using protos::pbzero::CounterDescriptor;
46}
47
Lalit Maganti62b741f2020-12-10 18:24:00 +000048TrackEventTokenizer::TrackEventTokenizer(TraceProcessorContext* context,
49 TrackEventTracker* track_event_tracker)
Eric Secklerf1497812020-04-30 10:43:23 +010050 : context_(context),
Lalit Maganti62b741f2020-12-10 18:24:00 +000051 track_event_tracker_(track_event_tracker),
Eric Secklerf1497812020-04-30 10:43:23 +010052 counter_name_thread_time_id_(
53 context_->storage->InternString("thread_time")),
54 counter_name_thread_instruction_count_id_(
55 context_->storage->InternString("thread_instruction_count")) {}
Eric Seckler053ebaa2019-10-31 10:30:58 +000056
Eric Seckler3183c6d2020-01-14 15:45:20 +000057ModuleResult TrackEventTokenizer::TokenizeTrackDescriptorPacket(
Eric Seckler7d128472020-01-13 10:03:51 +000058 PacketSequenceState* state,
Eric Secklerfbd9aed2020-03-10 18:07:38 +000059 const protos::pbzero::TracePacket::Decoder& packet,
Eric Seckler3183c6d2020-01-14 15:45:20 +000060 int64_t packet_timestamp) {
Eric Secklerfbd9aed2020-03-10 18:07:38 +000061 auto track_descriptor_field = packet.track_descriptor();
62 protos::pbzero::TrackDescriptor::Decoder track(track_descriptor_field.data,
63 track_descriptor_field.size);
Eric Seckler771960c2019-10-22 15:37:12 +010064
Eric Secklerfbd9aed2020-03-10 18:07:38 +000065 if (!track.has_uuid()) {
Eric Seckler7d128472020-01-13 10:03:51 +000066 PERFETTO_ELOG("TrackDescriptor packet without uuid");
Eric Seckler771960c2019-10-22 15:37:12 +010067 context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
Eric Seckler3183c6d2020-01-14 15:45:20 +000068 return ModuleResult::Handled();
Eric Seckler771960c2019-10-22 15:37:12 +010069 }
70
Eric Secklerf1497812020-04-30 10:43:23 +010071 StringId name_id = kNullStringId;
72 if (track.has_name())
73 name_id = context_->storage->InternString(track.name());
74
Eric Secklerfbd9aed2020-03-10 18:07:38 +000075 if (track.has_thread()) {
76 protos::pbzero::ThreadDescriptor::Decoder thread(track.thread());
Eric Seckler771960c2019-10-22 15:37:12 +010077
Eric Secklerfbd9aed2020-03-10 18:07:38 +000078 if (!thread.has_pid() || !thread.has_tid()) {
Eric Seckler3183c6d2020-01-14 15:45:20 +000079 PERFETTO_ELOG(
80 "No pid or tid in ThreadDescriptor for track with uuid %" PRIu64,
Eric Secklerfbd9aed2020-03-10 18:07:38 +000081 track.uuid());
Eric Seckler3183c6d2020-01-14 15:45:20 +000082 context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
83 return ModuleResult::Handled();
Sami Kyostilab0686c92020-01-07 12:56:55 +000084 }
Eric Seckler3183c6d2020-01-14 15:45:20 +000085
86 if (state->IsIncrementalStateValid()) {
Eric Secklerfbd9aed2020-03-10 18:07:38 +000087 TokenizeThreadDescriptor(state, thread);
Eric Seckler3183c6d2020-01-14 15:45:20 +000088 }
89
Lalit Maganti62b741f2020-12-10 18:24:00 +000090 track_event_tracker_->ReserveDescriptorThreadTrack(
Eric Secklerf1497812020-04-30 10:43:23 +010091 track.uuid(), track.parent_uuid(), name_id,
92 static_cast<uint32_t>(thread.pid()),
Eric Secklerfbd9aed2020-03-10 18:07:38 +000093 static_cast<uint32_t>(thread.tid()), packet_timestamp);
94 } else if (track.has_process()) {
95 protos::pbzero::ProcessDescriptor::Decoder process(track.process());
Eric Seckler3183c6d2020-01-14 15:45:20 +000096
Eric Secklerfbd9aed2020-03-10 18:07:38 +000097 if (!process.has_pid()) {
Eric Seckler3183c6d2020-01-14 15:45:20 +000098 PERFETTO_ELOG("No pid in ProcessDescriptor for track with uuid %" PRIu64,
Eric Secklerfbd9aed2020-03-10 18:07:38 +000099 track.uuid());
Eric Seckler3183c6d2020-01-14 15:45:20 +0000100 context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
101 return ModuleResult::Handled();
102 }
103
Lalit Maganti62b741f2020-12-10 18:24:00 +0000104 track_event_tracker_->ReserveDescriptorProcessTrack(
Eric Secklerf1497812020-04-30 10:43:23 +0100105 track.uuid(), name_id, static_cast<uint32_t>(process.pid()),
106 packet_timestamp);
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000107 } else if (track.has_counter()) {
108 protos::pbzero::CounterDescriptor::Decoder counter(track.counter());
109
110 StringId category_id = kNullStringId;
111 if (counter.has_categories()) {
112 // TODO(eseckler): Support multi-category events in the table schema.
113 std::string categories;
114 for (auto it = counter.categories(); it; ++it) {
115 if (!categories.empty())
116 categories += ",";
117 categories.append((*it).data, (*it).size);
118 }
119 if (!categories.empty()) {
120 category_id =
121 context_->storage->InternString(base::StringView(categories));
122 }
123 }
124
Eric Secklerf1497812020-04-30 10:43:23 +0100125 // TODO(eseckler): Intern counter tracks for specific counter types like
126 // thread time, so that the same counter can be referred to from tracks with
127 // different uuids. (Chrome may emit thread time values on behalf of other
128 // threads, in which case it has to use absolute values on a different
129 // track_uuid. Right now these absolute values are imported onto a separate
130 // counter track than the other thread's regular thread time values.)
Lalit Maganti627f4a62020-12-09 16:10:35 +0000131 if (name_id.is_null()) {
Eric Secklerf1497812020-04-30 10:43:23 +0100132 switch (counter.type()) {
133 case CounterDescriptor::COUNTER_UNSPECIFIED:
134 break;
135 case CounterDescriptor::COUNTER_THREAD_TIME_NS:
136 name_id = counter_name_thread_time_id_;
137 break;
138 case CounterDescriptor::COUNTER_THREAD_INSTRUCTION_COUNT:
139 name_id = counter_name_thread_instruction_count_id_;
140 break;
141 }
142 }
143
Lalit Maganti62b741f2020-12-10 18:24:00 +0000144 track_event_tracker_->ReserveDescriptorCounterTrack(
Eric Secklerf1497812020-04-30 10:43:23 +0100145 track.uuid(), track.parent_uuid(), name_id, category_id,
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000146 counter.unit_multiplier(), counter.is_incremental(),
147 packet.trusted_packet_sequence_id());
Eric Seckler3183c6d2020-01-14 15:45:20 +0000148 } else {
Lalit Maganti62b741f2020-12-10 18:24:00 +0000149 track_event_tracker_->ReserveDescriptorChildTrack(
Eric Secklerf1497812020-04-30 10:43:23 +0100150 track.uuid(), track.parent_uuid(), name_id);
Eric Seckler771960c2019-10-22 15:37:12 +0100151 }
152
Lalit Magantieb63b082020-09-10 14:12:20 +0100153 // Let ProtoTraceReader forward the packet to the parser.
Eric Seckler3183c6d2020-01-14 15:45:20 +0000154 return ModuleResult::Ignored();
Eric Seckler771960c2019-10-22 15:37:12 +0100155}
156
Eric Seckler3183c6d2020-01-14 15:45:20 +0000157ModuleResult TrackEventTokenizer::TokenizeThreadDescriptorPacket(
Eric Seckler771960c2019-10-22 15:37:12 +0100158 PacketSequenceState* state,
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000159 const protos::pbzero::TracePacket::Decoder& packet) {
160 if (PERFETTO_UNLIKELY(!packet.has_trusted_packet_sequence_id())) {
Eric Seckler771960c2019-10-22 15:37:12 +0100161 PERFETTO_ELOG("ThreadDescriptor packet without trusted_packet_sequence_id");
162 context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000163 return ModuleResult::Handled();
Eric Seckler771960c2019-10-22 15:37:12 +0100164 }
165
166 // TrackEvents will be ignored while incremental state is invalid. As a
167 // consequence, we should also ignore any ThreadDescriptors received in this
168 // state. Otherwise, any delta-encoded timestamps would be calculated
169 // incorrectly once we move out of the packet loss state. Instead, wait until
170 // the first subsequent descriptor after incremental state is cleared.
171 if (!state->IsIncrementalStateValid()) {
172 context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000173 return ModuleResult::Handled();
Eric Seckler771960c2019-10-22 15:37:12 +0100174 }
175
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000176 protos::pbzero::ThreadDescriptor::Decoder thread(packet.thread_descriptor());
177 TokenizeThreadDescriptor(state, thread);
Eric Seckler3183c6d2020-01-14 15:45:20 +0000178
Lalit Magantieb63b082020-09-10 14:12:20 +0100179 // Let ProtoTraceReader forward the packet to the parser.
Eric Seckler3183c6d2020-01-14 15:45:20 +0000180 return ModuleResult::Ignored();
Eric Seckler771960c2019-10-22 15:37:12 +0100181}
182
Eric Seckler3183c6d2020-01-14 15:45:20 +0000183void TrackEventTokenizer::TokenizeThreadDescriptor(
Eric Seckler7d128472020-01-13 10:03:51 +0000184 PacketSequenceState* state,
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000185 const protos::pbzero::ThreadDescriptor::Decoder& thread) {
Eric Seckler7d128472020-01-13 10:03:51 +0000186 // TODO(eseckler): Remove support for legacy thread descriptor-based default
187 // tracks and delta timestamps.
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000188 state->SetThreadDescriptor(thread.pid(), thread.tid(),
189 thread.reference_timestamp_us() * 1000,
190 thread.reference_thread_time_us() * 1000,
191 thread.reference_thread_instruction_count());
Sami Kyostilab0686c92020-01-07 12:56:55 +0000192}
193
Eric Seckler771960c2019-10-22 15:37:12 +0100194void TrackEventTokenizer::TokenizeTrackEventPacket(
195 PacketSequenceState* state,
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000196 const protos::pbzero::TracePacket::Decoder& packet,
197 TraceBlobView* packet_blob,
Eric Seckler771960c2019-10-22 15:37:12 +0100198 int64_t packet_timestamp) {
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000199 if (PERFETTO_UNLIKELY(!packet.has_trusted_packet_sequence_id())) {
Eric Seckler771960c2019-10-22 15:37:12 +0100200 PERFETTO_ELOG("TrackEvent packet without trusted_packet_sequence_id");
201 context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
202 return;
203 }
204
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000205 auto field = packet.track_event();
206 protos::pbzero::TrackEvent::Decoder event(field.data, field.size);
207
208 protos::pbzero::TrackEventDefaults::Decoder* defaults =
209 state->current_generation()->GetTrackEventDefaults();
Eric Seckler771960c2019-10-22 15:37:12 +0100210
211 int64_t timestamp;
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000212 std::unique_ptr<TrackEventData> data(
213 new TrackEventData(std::move(*packet_blob), state->current_generation()));
Eric Seckler771960c2019-10-22 15:37:12 +0100214
215 // TODO(eseckler): Remove handling of timestamps relative to ThreadDescriptors
216 // once all producers have switched to clock-domain timestamps (e.g.
217 // TracePacket's timestamp).
218
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000219 if (event.has_timestamp_delta_us()) {
Eric Seckler771960c2019-10-22 15:37:12 +0100220 // Delta timestamps require a valid ThreadDescriptor packet since the last
221 // packet loss.
222 if (!state->track_event_timestamps_valid()) {
223 context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
224 return;
225 }
226 timestamp = state->IncrementAndGetTrackEventTimeNs(
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000227 event.timestamp_delta_us() * 1000);
Eric Seckler771960c2019-10-22 15:37:12 +0100228
229 // Legacy TrackEvent timestamp fields are in MONOTONIC domain. Adjust to
230 // trace time if we have a clock snapshot.
231 auto trace_ts = context_->clock_tracker->ToTraceTime(
Eric Secklerdc454522020-05-20 19:40:23 +0100232 protos::pbzero::BUILTIN_CLOCK_MONOTONIC, timestamp);
Eric Seckler771960c2019-10-22 15:37:12 +0100233 if (trace_ts.has_value())
234 timestamp = trace_ts.value();
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000235 } else if (int64_t ts_absolute_us = event.timestamp_absolute_us()) {
Eric Seckler771960c2019-10-22 15:37:12 +0100236 // One-off absolute timestamps don't affect delta computation.
Eric Seckler866054c2019-11-13 19:08:22 +0000237 timestamp = ts_absolute_us * 1000;
Eric Seckler771960c2019-10-22 15:37:12 +0100238
239 // Legacy TrackEvent timestamp fields are in MONOTONIC domain. Adjust to
240 // trace time if we have a clock snapshot.
241 auto trace_ts = context_->clock_tracker->ToTraceTime(
Eric Secklerdc454522020-05-20 19:40:23 +0100242 protos::pbzero::BUILTIN_CLOCK_MONOTONIC, timestamp);
Eric Seckler771960c2019-10-22 15:37:12 +0100243 if (trace_ts.has_value())
244 timestamp = trace_ts.value();
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000245 } else if (packet.has_timestamp()) {
Eric Seckler771960c2019-10-22 15:37:12 +0100246 timestamp = packet_timestamp;
247 } else {
Eric Seckler866054c2019-11-13 19:08:22 +0000248 PERFETTO_ELOG("TrackEvent without valid timestamp");
Eric Seckler771960c2019-10-22 15:37:12 +0100249 context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
250 return;
251 }
252
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000253 if (event.has_thread_time_delta_us()) {
Eric Seckler771960c2019-10-22 15:37:12 +0100254 // Delta timestamps require a valid ThreadDescriptor packet since the last
255 // packet loss.
256 if (!state->track_event_timestamps_valid()) {
257 context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
258 return;
259 }
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000260 data->thread_timestamp = state->IncrementAndGetTrackEventThreadTimeNs(
261 event.thread_time_delta_us() * 1000);
262 } else if (event.has_thread_time_absolute_us()) {
Eric Seckler771960c2019-10-22 15:37:12 +0100263 // One-off absolute timestamps don't affect delta computation.
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000264 data->thread_timestamp = event.thread_time_absolute_us() * 1000;
Eric Seckler771960c2019-10-22 15:37:12 +0100265 }
266
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000267 if (event.has_thread_instruction_count_delta()) {
Eric Seckler771960c2019-10-22 15:37:12 +0100268 // Delta timestamps require a valid ThreadDescriptor packet since the last
269 // packet loss.
270 if (!state->track_event_timestamps_valid()) {
271 context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
272 return;
273 }
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000274 data->thread_instruction_count =
Eric Seckler771960c2019-10-22 15:37:12 +0100275 state->IncrementAndGetTrackEventThreadInstructionCount(
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000276 event.thread_instruction_count_delta());
277 } else if (event.has_thread_instruction_count_absolute()) {
Eric Seckler771960c2019-10-22 15:37:12 +0100278 // One-off absolute timestamps don't affect delta computation.
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000279 data->thread_instruction_count = event.thread_instruction_count_absolute();
Eric Seckler771960c2019-10-22 15:37:12 +0100280 }
281
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000282 if (event.type() == protos::pbzero::TrackEvent::TYPE_COUNTER) {
283 // Consider track_uuid from the packet and TrackEventDefaults.
284 uint64_t track_uuid;
285 if (event.has_track_uuid()) {
286 track_uuid = event.track_uuid();
Eric Seckler9ccafbc2020-04-23 14:32:54 +0100287 } else if (defaults && defaults->has_track_uuid()) {
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000288 track_uuid = defaults->track_uuid();
289 } else {
290 PERFETTO_DLOG(
291 "Ignoring TrackEvent with counter_value but without track_uuid");
292 context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
293 return;
294 }
295
Sami Kyostilab51e3802021-02-03 16:56:35 +0000296 if (!event.has_counter_value() && !event.has_double_counter_value()) {
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000297 PERFETTO_DLOG(
Sami Kyostilab51e3802021-02-03 16:56:35 +0000298 "Ignoring TrackEvent with TYPE_COUNTER but without counter_value or "
299 "double_counter_value for "
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000300 "track_uuid %" PRIu64,
301 track_uuid);
302 context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
303 return;
304 }
305
Sami Kyostilab51e3802021-02-03 16:56:35 +0000306 base::Optional<double> value;
307 if (event.has_counter_value()) {
308 value = track_event_tracker_->ConvertToAbsoluteCounterValue(
309 track_uuid, packet.trusted_packet_sequence_id(),
310 static_cast<double>(event.counter_value()));
311 } else {
312 value = track_event_tracker_->ConvertToAbsoluteCounterValue(
313 track_uuid, packet.trusted_packet_sequence_id(),
314 event.double_counter_value());
315 }
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000316
317 if (!value) {
318 PERFETTO_DLOG("Ignoring TrackEvent with invalid track_uuid %" PRIu64,
319 track_uuid);
320 context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
321 return;
322 }
323
324 data->counter_value = *value;
325 }
326
Sami Kyostilab51e3802021-02-03 16:56:35 +0000327 size_t index = 0;
328 const protozero::RepeatedFieldIterator<uint64_t> kEmptyIterator;
329 auto result = AddExtraCounterValues(
330 *data, index, packet.trusted_packet_sequence_id(),
331 event.extra_counter_values(), event.extra_counter_track_uuids(),
332 defaults ? defaults->extra_counter_track_uuids() : kEmptyIterator);
333 if (!result.ok()) {
334 PERFETTO_DLOG("%s", result.c_message());
335 context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
336 return;
337 }
338 result = AddExtraCounterValues(
339 *data, index, packet.trusted_packet_sequence_id(),
340 event.extra_double_counter_values(),
341 event.extra_double_counter_track_uuids(),
342 defaults ? defaults->extra_double_counter_track_uuids() : kEmptyIterator);
343 if (!result.ok()) {
344 PERFETTO_DLOG("%s", result.c_message());
345 context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
346 return;
Eric Secklerfbd9aed2020-03-10 18:07:38 +0000347 }
348
349 context_->sorter->PushTrackEventPacket(timestamp, std::move(data));
Eric Seckler771960c2019-10-22 15:37:12 +0100350}
351
Sami Kyostilab51e3802021-02-03 16:56:35 +0000352template <typename T>
353base::Status TrackEventTokenizer::AddExtraCounterValues(
354 TrackEventData& data,
355 size_t& index,
356 uint32_t trusted_packet_sequence_id,
357 protozero::RepeatedFieldIterator<T> value_it,
358 protozero::RepeatedFieldIterator<uint64_t> packet_track_uuid_it,
359 protozero::RepeatedFieldIterator<uint64_t> default_track_uuid_it) {
360 if (!value_it)
361 return base::OkStatus();
362
363 // Consider extra_{double_,}counter_track_uuids from the packet and
364 // TrackEventDefaults.
365 protozero::RepeatedFieldIterator<uint64_t> track_uuid_it;
366 if (packet_track_uuid_it) {
367 track_uuid_it = packet_track_uuid_it;
368 } else if (default_track_uuid_it) {
369 track_uuid_it = default_track_uuid_it;
370 } else {
371 return base::Status(
372 "Ignoring TrackEvent with extra_{double_,}counter_values but without "
373 "extra_{double_,}counter_track_uuids");
374 }
375
376 for (; value_it; ++value_it, ++track_uuid_it, ++index) {
377 if (!*track_uuid_it) {
378 return base::Status(
379 "Ignoring TrackEvent with more extra_{double_,}counter_values than "
380 "extra_{double_,}counter_track_uuids");
381 }
382 if (index >= TrackEventData::kMaxNumExtraCounters) {
383 return base::Status(
384 "Ignoring TrackEvent with more extra_{double_,}counter_values than "
385 "TrackEventData::kMaxNumExtraCounters");
386 }
387 base::Optional<double> abs_value =
388 track_event_tracker_->ConvertToAbsoluteCounterValue(
389 *track_uuid_it, trusted_packet_sequence_id,
390 static_cast<double>(*value_it));
391 if (!abs_value) {
392 return base::Status(
393 "Ignoring TrackEvent with invalid extra counter track");
394 }
395 data.extra_counter_values[index] = *abs_value;
396 }
397 return base::OkStatus();
398}
399
Eric Seckler771960c2019-10-22 15:37:12 +0100400} // namespace trace_processor
401} // namespace perfetto