xref: /aosp_15_r20/external/perfetto/src/tracing/internal/track_event_internal.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
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 "perfetto/tracing/internal/track_event_internal.h"
18 
19 #include "perfetto/base/proc_utils.h"
20 #include "perfetto/base/time.h"
21 #include "perfetto/tracing/core/data_source_config.h"
22 #include "perfetto/tracing/internal/track_event_interned_fields.h"
23 #include "perfetto/tracing/track_event.h"
24 #include "perfetto/tracing/track_event_category_registry.h"
25 #include "perfetto/tracing/track_event_interned_data_index.h"
26 #include "protos/perfetto/common/data_source_descriptor.gen.h"
27 #include "protos/perfetto/common/track_event_descriptor.pbzero.h"
28 #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
29 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
30 #include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
31 #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
32 #include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
33 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MAC)
34 #include <os/signpost.h>
35 #endif
36 
37 using perfetto::protos::pbzero::ClockSnapshot;
38 
39 namespace perfetto {
40 
41 TrackEventSessionObserver::~TrackEventSessionObserver() = default;
OnSetup(const DataSourceBase::SetupArgs &)42 void TrackEventSessionObserver::OnSetup(const DataSourceBase::SetupArgs&) {}
OnStart(const DataSourceBase::StartArgs &)43 void TrackEventSessionObserver::OnStart(const DataSourceBase::StartArgs&) {}
OnStop(const DataSourceBase::StopArgs &)44 void TrackEventSessionObserver::OnStop(const DataSourceBase::StopArgs&) {}
WillClearIncrementalState(const DataSourceBase::ClearIncrementalStateArgs &)45 void TrackEventSessionObserver::WillClearIncrementalState(
46     const DataSourceBase::ClearIncrementalStateArgs&) {}
47 
48 TrackEventTlsStateUserData::~TrackEventTlsStateUserData() = default;
49 
50 namespace internal {
51 
52 BaseTrackEventInternedDataIndex::~BaseTrackEventInternedDataIndex() = default;
53 
54 namespace {
55 
56 static constexpr const char kLegacySlowPrefix[] = "disabled-by-default-";
57 static constexpr const char kSlowTag[] = "slow";
58 static constexpr const char kDebugTag[] = "debug";
59 static constexpr const char kFilteredEventName[] = "FILTERED";
60 
61 constexpr auto kClockIdIncremental =
62     TrackEventIncrementalState::kClockIdIncremental;
63 
64 constexpr auto kClockIdAbsolute = TrackEventIncrementalState::kClockIdAbsolute;
65 
66 class TrackEventSessionObserverRegistry {
67  public:
GetInstance()68   static TrackEventSessionObserverRegistry* GetInstance() {
69     static TrackEventSessionObserverRegistry* instance =
70         new TrackEventSessionObserverRegistry();  // leaked
71     return instance;
72   }
73 
AddObserverForRegistry(const TrackEventCategoryRegistry & registry,TrackEventSessionObserver * observer)74   void AddObserverForRegistry(const TrackEventCategoryRegistry& registry,
75                               TrackEventSessionObserver* observer) {
76     std::unique_lock<std::recursive_mutex> lock(mutex_);
77     observers_.emplace_back(&registry, observer);
78   }
79 
RemoveObserverForRegistry(const TrackEventCategoryRegistry & registry,TrackEventSessionObserver * observer)80   void RemoveObserverForRegistry(const TrackEventCategoryRegistry& registry,
81                                  TrackEventSessionObserver* observer) {
82     std::unique_lock<std::recursive_mutex> lock(mutex_);
83     observers_.erase(std::remove(observers_.begin(), observers_.end(),
84                                  RegisteredObserver(&registry, observer)),
85                      observers_.end());
86   }
87 
ForEachObserverForRegistry(const TrackEventCategoryRegistry & registry,std::function<void (TrackEventSessionObserver *)> callback)88   void ForEachObserverForRegistry(
89       const TrackEventCategoryRegistry& registry,
90       std::function<void(TrackEventSessionObserver*)> callback) {
91     std::unique_lock<std::recursive_mutex> lock(mutex_);
92     for (auto& registered_observer : observers_) {
93       if (&registry == registered_observer.registry) {
94         callback(registered_observer.observer);
95       }
96     }
97   }
98 
99  private:
100   struct RegisteredObserver {
RegisteredObserverperfetto::internal::__anon172934bf0111::TrackEventSessionObserverRegistry::RegisteredObserver101     RegisteredObserver(const TrackEventCategoryRegistry* r,
102                        TrackEventSessionObserver* o)
103         : registry(r), observer(o) {}
operator ==perfetto::internal::__anon172934bf0111::TrackEventSessionObserverRegistry::RegisteredObserver104     bool operator==(const RegisteredObserver& other) {
105       return registry == other.registry && observer == other.observer;
106     }
107     const TrackEventCategoryRegistry* registry;
108     TrackEventSessionObserver* observer;
109   };
110 
111   std::recursive_mutex mutex_;
112   std::vector<RegisteredObserver> observers_;
113 };
114 
115 enum class MatchType { kExact, kPattern };
116 
NameMatchesPattern(const std::string & pattern,const std::string & name,MatchType match_type)117 bool NameMatchesPattern(const std::string& pattern,
118                         const std::string& name,
119                         MatchType match_type) {
120   // To avoid pulling in all of std::regex, for now we only support a single "*"
121   // wildcard at the end of the pattern.
122   size_t i = pattern.find('*');
123   if (i != std::string::npos) {
124     PERFETTO_DCHECK(i == pattern.size() - 1);
125     if (match_type != MatchType::kPattern)
126       return false;
127     return name.substr(0, i) == pattern.substr(0, i);
128   }
129   return name == pattern;
130 }
131 
NameMatchesPatternList(const std::vector<std::string> & patterns,const std::string & name,MatchType match_type)132 bool NameMatchesPatternList(const std::vector<std::string>& patterns,
133                             const std::string& name,
134                             MatchType match_type) {
135   for (const auto& pattern : patterns) {
136     if (NameMatchesPattern(pattern, name, match_type))
137       return true;
138   }
139   return false;
140 }
141 
142 }  // namespace
143 
144 // static
145 const Track TrackEventInternal::kDefaultTrack{};
146 
147 // static
148 std::atomic<int> TrackEventInternal::session_count_{};
149 
150 // static
Initialize(const TrackEventCategoryRegistry & registry,bool (* register_data_source)(const DataSourceDescriptor &))151 bool TrackEventInternal::Initialize(
152     const TrackEventCategoryRegistry& registry,
153     bool (*register_data_source)(const DataSourceDescriptor&)) {
154   DataSourceDescriptor dsd;
155   dsd.set_name("track_event");
156 
157   protozero::HeapBuffered<protos::pbzero::TrackEventDescriptor> ted;
158   for (size_t i = 0; i < registry.category_count(); i++) {
159     auto category = registry.GetCategory(i);
160     // Don't register group categories.
161     if (category->IsGroup())
162       continue;
163     auto cat = ted->add_available_categories();
164     cat->set_name(category->name);
165     if (category->description)
166       cat->set_description(category->description);
167     for (const auto& tag : category->tags) {
168       if (tag)
169         cat->add_tags(tag);
170     }
171     // Disabled-by-default categories get a "slow" tag.
172     if (!strncmp(category->name, kLegacySlowPrefix, strlen(kLegacySlowPrefix)))
173       cat->add_tags(kSlowTag);
174   }
175   dsd.set_track_event_descriptor_raw(ted.SerializeAsString());
176 
177   return register_data_source(dsd);
178 }
179 
180 // static
AddSessionObserver(const TrackEventCategoryRegistry & registry,TrackEventSessionObserver * observer)181 bool TrackEventInternal::AddSessionObserver(
182     const TrackEventCategoryRegistry& registry,
183     TrackEventSessionObserver* observer) {
184   TrackEventSessionObserverRegistry::GetInstance()->AddObserverForRegistry(
185       registry, observer);
186   return true;
187 }
188 
189 // static
RemoveSessionObserver(const TrackEventCategoryRegistry & registry,TrackEventSessionObserver * observer)190 void TrackEventInternal::RemoveSessionObserver(
191     const TrackEventCategoryRegistry& registry,
192     TrackEventSessionObserver* observer) {
193   TrackEventSessionObserverRegistry::GetInstance()->RemoveObserverForRegistry(
194       registry, observer);
195 }
196 
197 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
198     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
199 static constexpr protos::pbzero::BuiltinClock kDefaultTraceClock =
200     protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
201 #else
202 static constexpr protos::pbzero::BuiltinClock kDefaultTraceClock =
203     protos::pbzero::BUILTIN_CLOCK_MONOTONIC;
204 #endif
205 
206 // static
207 protos::pbzero::BuiltinClock TrackEventInternal::clock_ = kDefaultTraceClock;
208 
209 // static
210 bool TrackEventInternal::disallow_merging_with_system_tracks_ = false;
211 
212 // static
EnableTracing(const TrackEventCategoryRegistry & registry,const protos::gen::TrackEventConfig & config,const DataSourceBase::SetupArgs & args)213 void TrackEventInternal::EnableTracing(
214     const TrackEventCategoryRegistry& registry,
215     const protos::gen::TrackEventConfig& config,
216     const DataSourceBase::SetupArgs& args) {
217   for (size_t i = 0; i < registry.category_count(); i++) {
218     if (IsCategoryEnabled(registry, config, *registry.GetCategory(i)))
219       registry.EnableCategoryForInstance(i, args.internal_instance_index);
220   }
221   TrackEventSessionObserverRegistry::GetInstance()->ForEachObserverForRegistry(
222       registry, [&](TrackEventSessionObserver* o) { o->OnSetup(args); });
223 }
224 
225 // static
OnStart(const TrackEventCategoryRegistry & registry,const DataSourceBase::StartArgs & args)226 void TrackEventInternal::OnStart(const TrackEventCategoryRegistry& registry,
227                                  const DataSourceBase::StartArgs& args) {
228   session_count_.fetch_add(1);
229   TrackEventSessionObserverRegistry::GetInstance()->ForEachObserverForRegistry(
230       registry, [&](TrackEventSessionObserver* o) { o->OnStart(args); });
231 }
232 
233 // static
OnStop(const TrackEventCategoryRegistry & registry,const DataSourceBase::StopArgs & args)234 void TrackEventInternal::OnStop(const TrackEventCategoryRegistry& registry,
235                                 const DataSourceBase::StopArgs& args) {
236   TrackEventSessionObserverRegistry::GetInstance()->ForEachObserverForRegistry(
237       registry, [&](TrackEventSessionObserver* o) { o->OnStop(args); });
238 }
239 
240 // static
DisableTracing(const TrackEventCategoryRegistry & registry,uint32_t internal_instance_index)241 void TrackEventInternal::DisableTracing(
242     const TrackEventCategoryRegistry& registry,
243     uint32_t internal_instance_index) {
244   for (size_t i = 0; i < registry.category_count(); i++)
245     registry.DisableCategoryForInstance(i, internal_instance_index);
246 }
247 
248 // static
WillClearIncrementalState(const TrackEventCategoryRegistry & registry,const DataSourceBase::ClearIncrementalStateArgs & args)249 void TrackEventInternal::WillClearIncrementalState(
250     const TrackEventCategoryRegistry& registry,
251     const DataSourceBase::ClearIncrementalStateArgs& args) {
252   TrackEventSessionObserverRegistry::GetInstance()->ForEachObserverForRegistry(
253       registry, [&](TrackEventSessionObserver* o) {
254         o->WillClearIncrementalState(args);
255       });
256 }
257 
258 // static
IsCategoryEnabled(const TrackEventCategoryRegistry & registry,const protos::gen::TrackEventConfig & config,const Category & category)259 bool TrackEventInternal::IsCategoryEnabled(
260     const TrackEventCategoryRegistry& registry,
261     const protos::gen::TrackEventConfig& config,
262     const Category& category) {
263   // If this is a group category, check if any of its constituent categories are
264   // enabled. If so, then this one is enabled too.
265   if (category.IsGroup()) {
266     bool result = false;
267     category.ForEachGroupMember([&](const char* member_name, size_t name_size) {
268       for (size_t i = 0; i < registry.category_count(); i++) {
269         const auto ref_category = registry.GetCategory(i);
270         // Groups can't refer to other groups.
271         if (ref_category->IsGroup())
272           continue;
273         // Require an exact match.
274         if (ref_category->name_size() != name_size ||
275             strncmp(ref_category->name, member_name, name_size)) {
276           continue;
277         }
278         if (IsCategoryEnabled(registry, config, *ref_category)) {
279           result = true;
280           // Break ForEachGroupMember() loop.
281           return false;
282         }
283         break;
284       }
285       // No match? Must be a dynamic category.
286       DynamicCategory dyn_category(std::string(member_name, name_size));
287       Category ref_category{Category::FromDynamicCategory(dyn_category)};
288       if (IsCategoryEnabled(registry, config, ref_category)) {
289         result = true;
290         // Break ForEachGroupMember() loop.
291         return false;
292       }
293       // No match found => keep iterating.
294       return true;
295     });
296     return result;
297   }
298 
299   auto has_matching_tag = [&](std::function<bool(const char*)> matcher) {
300     for (const auto& tag : category.tags) {
301       if (!tag)
302         break;
303       if (matcher(tag))
304         return true;
305     }
306     // Legacy "disabled-by-default" categories automatically get the "slow" tag.
307     if (!strncmp(category.name, kLegacySlowPrefix, strlen(kLegacySlowPrefix)) &&
308         matcher(kSlowTag)) {
309       return true;
310     }
311     return false;
312   };
313 
314   // First try exact matches, then pattern matches.
315   const std::array<MatchType, 2> match_types = {
316       {MatchType::kExact, MatchType::kPattern}};
317   for (auto match_type : match_types) {
318     // 1. Enabled categories.
319     if (NameMatchesPatternList(config.enabled_categories(), category.name,
320                                match_type)) {
321       return true;
322     }
323 
324     // 2. Enabled tags.
325     if (has_matching_tag([&](const char* tag) {
326           return NameMatchesPatternList(config.enabled_tags(), tag, match_type);
327         })) {
328       return true;
329     }
330 
331     // 2.5. A special case for Chrome's legacy disabled-by-default categories.
332     // We treat them as having a "slow" tag with one exception: they can be
333     // enabled by a pattern if the pattern starts with "disabled-by-default-"
334     // itself.
335     if (match_type == MatchType::kExact &&
336         !strncmp(category.name, kLegacySlowPrefix, strlen(kLegacySlowPrefix))) {
337       for (const auto& pattern : config.enabled_categories()) {
338         if (!strncmp(pattern.c_str(), kLegacySlowPrefix,
339                      strlen(kLegacySlowPrefix)) &&
340             NameMatchesPattern(pattern, category.name, MatchType::kPattern)) {
341           return true;
342         }
343       }
344     }
345 
346     // 3. Disabled categories.
347     if (NameMatchesPatternList(config.disabled_categories(), category.name,
348                                match_type)) {
349       return false;
350     }
351 
352     // 4. Disabled tags.
353     if (has_matching_tag([&](const char* tag) {
354           if (config.disabled_tags_size()) {
355             return NameMatchesPatternList(config.disabled_tags(), tag,
356                                           match_type);
357           } else {
358             // The "slow" and "debug" tags are disabled by default.
359             return NameMatchesPattern(kSlowTag, tag, match_type) ||
360                    NameMatchesPattern(kDebugTag, tag, match_type);
361           }
362         })) {
363       return false;
364     }
365   }
366 
367   // If nothing matched, enable the category by default.
368   return true;
369 }
370 
371 // static
GetTimeNs()372 uint64_t TrackEventInternal::GetTimeNs() {
373   if (GetClockId() == protos::pbzero::BUILTIN_CLOCK_BOOTTIME)
374     return static_cast<uint64_t>(perfetto::base::GetBootTimeNs().count());
375   else if (GetClockId() == protos::pbzero::BUILTIN_CLOCK_MONOTONIC)
376     return static_cast<uint64_t>(perfetto::base::GetWallTimeNs().count());
377   PERFETTO_DCHECK(GetClockId() == protos::pbzero::BUILTIN_CLOCK_MONOTONIC_RAW);
378   return static_cast<uint64_t>(perfetto::base::GetWallTimeRawNs().count());
379 }
380 
381 // static
GetTraceTime()382 TraceTimestamp TrackEventInternal::GetTraceTime() {
383   return {kClockIdIncremental, GetTimeNs()};
384 }
385 
386 // static
GetSessionCount()387 int TrackEventInternal::GetSessionCount() {
388   return session_count_.load();
389 }
390 
391 // static
ResetIncrementalState(TraceWriterBase * trace_writer,TrackEventIncrementalState * incr_state,const TrackEventTlsState & tls_state,const TraceTimestamp & timestamp)392 void TrackEventInternal::ResetIncrementalState(
393     TraceWriterBase* trace_writer,
394     TrackEventIncrementalState* incr_state,
395     const TrackEventTlsState& tls_state,
396     const TraceTimestamp& timestamp) {
397   auto sequence_timestamp = timestamp;
398   if (timestamp.clock_id != kClockIdIncremental) {
399     sequence_timestamp = TrackEventInternal::GetTraceTime();
400   }
401 
402   incr_state->last_timestamp_ns = sequence_timestamp.value;
403   auto default_track = ThreadTrack::Current();
404   auto ts_unit_multiplier = tls_state.timestamp_unit_multiplier;
405   auto thread_time_counter_track =
406       CounterTrack("thread_time", default_track)
407           .set_is_incremental(true)
408           .set_unit_multiplier(static_cast<int64_t>(ts_unit_multiplier))
409           .set_type(protos::gen::CounterDescriptor::COUNTER_THREAD_TIME_NS);
410   {
411     // Mark any incremental state before this point invalid. Also set up
412     // defaults so that we don't need to repeat constant data for each packet.
413     auto packet = NewTracePacket(
414         trace_writer, incr_state, tls_state, timestamp,
415         protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
416     auto defaults = packet->set_trace_packet_defaults();
417     defaults->set_timestamp_clock_id(tls_state.default_clock);
418     // Establish the default track for this event sequence.
419     auto track_defaults = defaults->set_track_event_defaults();
420     track_defaults->set_track_uuid(default_track.uuid);
421     if (tls_state.enable_thread_time_sampling) {
422       track_defaults->add_extra_counter_track_uuids(
423           thread_time_counter_track.uuid);
424     }
425 
426 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MAC)
427     // Emit a MacOS point-of-interest signpost to synchonize Mac profiler time
428     // with boot time.
429     // TODO(leszeks): Consider allowing synchronization against other clocks
430     // than boot time.
431     static os_log_t log_handle = os_log_create(
432         "dev.perfetto.clock_sync", OS_LOG_CATEGORY_POINTS_OF_INTEREST);
433     os_signpost_event_emit(
434         log_handle, OS_SIGNPOST_ID_EXCLUSIVE, "boottime", "%" PRId64,
435         static_cast<uint64_t>(perfetto::base::GetBootTimeNs().count()));
436 #endif
437 
438     if (tls_state.default_clock != static_cast<uint32_t>(GetClockId())) {
439       ClockSnapshot* clocks = packet->set_clock_snapshot();
440       // Trace clock.
441       ClockSnapshot::Clock* trace_clock = clocks->add_clocks();
442       trace_clock->set_clock_id(static_cast<uint32_t>(GetClockId()));
443       trace_clock->set_timestamp(sequence_timestamp.value);
444 
445       if (PERFETTO_LIKELY(tls_state.default_clock == kClockIdIncremental)) {
446         // Delta-encoded incremental clock in nanoseconds by default but
447         // configurable by |tls_state.timestamp_unit_multiplier|.
448         ClockSnapshot::Clock* clock_incremental = clocks->add_clocks();
449         clock_incremental->set_clock_id(kClockIdIncremental);
450         clock_incremental->set_timestamp(sequence_timestamp.value /
451                                          ts_unit_multiplier);
452         clock_incremental->set_is_incremental(true);
453         clock_incremental->set_unit_multiplier_ns(ts_unit_multiplier);
454       }
455       if (ts_unit_multiplier > 1) {
456         // absolute clock with custom timestamp_unit_multiplier.
457         ClockSnapshot::Clock* absolute_clock = clocks->add_clocks();
458         absolute_clock->set_clock_id(kClockIdAbsolute);
459         absolute_clock->set_timestamp(sequence_timestamp.value /
460                                       ts_unit_multiplier);
461         absolute_clock->set_is_incremental(false);
462         absolute_clock->set_unit_multiplier_ns(ts_unit_multiplier);
463       }
464     }
465   }
466 
467   // Every thread should write a descriptor for its default track, because most
468   // trace points won't explicitly reference it. We also write the process
469   // descriptor from every thread that writes trace events to ensure it gets
470   // emitted at least once.
471   incr_state->seen_tracks.insert(default_track.uuid);
472   WriteTrackDescriptor(default_track, trace_writer, incr_state, tls_state,
473                        sequence_timestamp);
474 
475   incr_state->seen_tracks.insert(ProcessTrack::Current().uuid);
476   WriteTrackDescriptor(ProcessTrack::Current(), trace_writer, incr_state,
477                        tls_state, sequence_timestamp);
478 
479   if (tls_state.enable_thread_time_sampling) {
480     WriteTrackDescriptor(thread_time_counter_track, trace_writer, incr_state,
481                          tls_state, sequence_timestamp);
482   }
483 }
484 
485 // static
486 protozero::MessageHandle<protos::pbzero::TracePacket>
NewTracePacket(TraceWriterBase * trace_writer,TrackEventIncrementalState * incr_state,const TrackEventTlsState & tls_state,TraceTimestamp timestamp,uint32_t seq_flags)487 TrackEventInternal::NewTracePacket(TraceWriterBase* trace_writer,
488                                    TrackEventIncrementalState* incr_state,
489                                    const TrackEventTlsState& tls_state,
490                                    TraceTimestamp timestamp,
491                                    uint32_t seq_flags) {
492   if (PERFETTO_UNLIKELY(tls_state.default_clock != kClockIdIncremental &&
493                         timestamp.clock_id == kClockIdIncremental)) {
494     timestamp.clock_id = tls_state.default_clock;
495   }
496   auto packet = trace_writer->NewTracePacket();
497   auto ts_unit_multiplier = tls_state.timestamp_unit_multiplier;
498   if (PERFETTO_LIKELY(timestamp.clock_id == kClockIdIncremental)) {
499     if (PERFETTO_LIKELY(incr_state->last_timestamp_ns <= timestamp.value)) {
500       // No need to set the clock id here, since kClockIdIncremental is the
501       // clock id assumed by default.
502       auto time_diff_ns = timestamp.value - incr_state->last_timestamp_ns;
503       auto time_diff_units = time_diff_ns / ts_unit_multiplier;
504       packet->set_timestamp(time_diff_units);
505       incr_state->last_timestamp_ns += time_diff_units * ts_unit_multiplier;
506     } else {
507       packet->set_timestamp(timestamp.value / ts_unit_multiplier);
508       packet->set_timestamp_clock_id(ts_unit_multiplier == 1
509                                          ? static_cast<uint32_t>(GetClockId())
510                                          : kClockIdAbsolute);
511     }
512   } else if (PERFETTO_LIKELY(timestamp.clock_id == tls_state.default_clock)) {
513     packet->set_timestamp(timestamp.value / ts_unit_multiplier);
514   } else {
515     packet->set_timestamp(timestamp.value);
516     packet->set_timestamp_clock_id(timestamp.clock_id);
517   }
518   packet->set_sequence_flags(seq_flags);
519   return packet;
520 }
521 
522 // static
WriteEventName(StaticString event_name,perfetto::EventContext & event_ctx,const TrackEventTlsState &)523 void TrackEventInternal::WriteEventName(StaticString event_name,
524                                         perfetto::EventContext& event_ctx,
525                                         const TrackEventTlsState&) {
526   if (PERFETTO_LIKELY(event_name.value != nullptr)) {
527     size_t name_iid = InternedEventName::Get(&event_ctx, event_name.value);
528     event_ctx.event()->set_name_iid(name_iid);
529   }
530 }
531 
532 // static
WriteEventName(perfetto::DynamicString event_name,perfetto::EventContext & event_ctx,const TrackEventTlsState & tls_state)533 void TrackEventInternal::WriteEventName(perfetto::DynamicString event_name,
534                                         perfetto::EventContext& event_ctx,
535                                         const TrackEventTlsState& tls_state) {
536   if (PERFETTO_UNLIKELY(tls_state.filter_dynamic_event_names)) {
537     event_ctx.event()->set_name(kFilteredEventName,
538                                 sizeof(kFilteredEventName) - 1);
539   } else {
540     event_ctx.event()->set_name(event_name.value, event_name.length);
541   }
542 }
543 
544 // static
WriteEvent(TraceWriterBase * trace_writer,TrackEventIncrementalState * incr_state,TrackEventTlsState & tls_state,const Category * category,perfetto::protos::pbzero::TrackEvent::Type type,const TraceTimestamp & timestamp,bool on_current_thread_track)545 EventContext TrackEventInternal::WriteEvent(
546     TraceWriterBase* trace_writer,
547     TrackEventIncrementalState* incr_state,
548     TrackEventTlsState& tls_state,
549     const Category* category,
550     perfetto::protos::pbzero::TrackEvent::Type type,
551     const TraceTimestamp& timestamp,
552     bool on_current_thread_track) {
553   PERFETTO_DCHECK(!incr_state->was_cleared);
554   auto packet = NewTracePacket(trace_writer, incr_state, tls_state, timestamp);
555   EventContext ctx(trace_writer, std::move(packet), incr_state, &tls_state);
556 
557   auto track_event = ctx.event();
558   if (type != protos::pbzero::TrackEvent::TYPE_UNSPECIFIED)
559     track_event->set_type(type);
560 
561   if (tls_state.enable_thread_time_sampling && on_current_thread_track) {
562     int64_t thread_time_ns = base::GetThreadCPUTimeNs().count();
563     auto thread_time_delta_ns =
564         thread_time_ns - incr_state->last_thread_time_ns;
565     incr_state->last_thread_time_ns = thread_time_ns;
566     track_event->add_extra_counter_values(
567         thread_time_delta_ns /
568         static_cast<int64_t>(tls_state.timestamp_unit_multiplier));
569   }
570 
571   // We assume that |category| points to the string with static lifetime.
572   // This means we can use their addresses as interning keys.
573   // TODO(skyostil): Intern categories at compile time.
574   if (category && type != protos::pbzero::TrackEvent::TYPE_SLICE_END &&
575       type != protos::pbzero::TrackEvent::TYPE_COUNTER) {
576     category->ForEachGroupMember(
577         [&](const char* member_name, size_t name_size) {
578           size_t category_iid =
579               InternedEventCategory::Get(&ctx, member_name, name_size);
580           track_event->add_category_iids(category_iid);
581           return true;
582         });
583   }
584   return ctx;
585 }
586 
587 // static
AddDebugAnnotation(perfetto::EventContext * event_ctx,const char * name)588 protos::pbzero::DebugAnnotation* TrackEventInternal::AddDebugAnnotation(
589     perfetto::EventContext* event_ctx,
590     const char* name) {
591   auto annotation = event_ctx->event()->add_debug_annotations();
592   annotation->set_name_iid(InternedDebugAnnotationName::Get(event_ctx, name));
593   return annotation;
594 }
595 
596 // static
AddDebugAnnotation(perfetto::EventContext * event_ctx,perfetto::DynamicString name)597 protos::pbzero::DebugAnnotation* TrackEventInternal::AddDebugAnnotation(
598     perfetto::EventContext* event_ctx,
599     perfetto::DynamicString name) {
600   auto annotation = event_ctx->event()->add_debug_annotations();
601   annotation->set_name(name.value);
602   return annotation;
603 }
604 
605 }  // namespace internal
606 }  // namespace perfetto
607