xref: /aosp_15_r20/external/cronet/base/trace_event/etw_interceptor_win.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/trace_event/etw_interceptor_win.h"
6 
7 #include "base/containers/flat_map.h"
8 #include "base/time/time.h"
9 #include "base/trace_event/trace_event_etw_export_win.h"
10 #include "third_party/perfetto/protos/perfetto/common/interceptor_descriptor.gen.h"
11 #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
12 #include "third_party/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.h"
13 
14 namespace base::trace_event {
15 
16 class ETWInterceptor::Delegate
17     : public perfetto::TrackEventStateTracker::Delegate {
18  public:
Delegate(perfetto::LockedHandle<ETWInterceptor> locked_self)19   explicit Delegate(perfetto::LockedHandle<ETWInterceptor> locked_self)
20       : locked_self_(std::move(locked_self)) {
21     DCHECK(locked_self_);
22   }
23   ~Delegate() override;
24 
25   perfetto::TrackEventStateTracker::SessionState* GetSessionState() override;
26   void OnTrackUpdated(perfetto::TrackEventStateTracker::Track&) override;
27   void OnTrackEvent(
28       const perfetto::TrackEventStateTracker::Track&,
29       const perfetto::TrackEventStateTracker::ParsedTrackEvent&) override;
30 
31  private:
32   perfetto::LockedHandle<ETWInterceptor> locked_self_;
33 };
34 
35 ETWInterceptor::Delegate::~Delegate() = default;
36 
37 perfetto::TrackEventStateTracker::SessionState*
GetSessionState()38 ETWInterceptor::Delegate::GetSessionState() {
39   return &locked_self_->session_state_;
40 }
41 
OnTrackUpdated(perfetto::TrackEventStateTracker::Track & track)42 void ETWInterceptor::Delegate::OnTrackUpdated(
43     perfetto::TrackEventStateTracker::Track& track) {}
44 
OnTrackEvent(const perfetto::TrackEventStateTracker::Track & track,const perfetto::TrackEventStateTracker::ParsedTrackEvent & event)45 void ETWInterceptor::Delegate::OnTrackEvent(
46     const perfetto::TrackEventStateTracker::Track& track,
47     const perfetto::TrackEventStateTracker::ParsedTrackEvent& event) {
48   uint64_t keyword = base::trace_event::CategoryGroupToETWKeyword(
49       std::string_view(event.category.data, event.category.size));
50   const char* phase_string = nullptr;
51   switch (event.track_event.type()) {
52     case perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN:
53       phase_string = "Begin";
54       break;
55     case perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END:
56       phase_string = "End";
57       break;
58     case perfetto::protos::pbzero::TrackEvent::TYPE_INSTANT:
59       phase_string = "Instant";
60       break;
61   }
62   DCHECK_NE(nullptr, phase_string);
63   // TODO(crbug.com/1465855): Consider exporting thread time once
64   // TrackEventStateTracker supports it.
65   if (event.track_event.type() ==
66       perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END) {
67     locked_self_->provider_->WriteEvent(
68         std::string_view(event.name.data, event.name.size),
69         TlmEventDescriptor(0, keyword),
70         TlmMbcsStringField("Phase", phase_string),
71         TlmUInt64Field(
72             "Timestamp",
73             event.timestamp_ns / base::TimeTicks::kNanosecondsPerMicrosecond),
74         TlmUInt64Field(
75             "Duration",
76             event.duration_ns / base::TimeTicks::kNanosecondsPerMicrosecond));
77   } else {
78     locked_self_->provider_->WriteEvent(
79         std::string_view(event.name.data, event.name.size),
80         TlmEventDescriptor(0, keyword),
81         TlmMbcsStringField("Phase", phase_string),
82         TlmUInt64Field(
83             "Timestamp",
84             event.timestamp_ns / base::TimeTicks::kNanosecondsPerMicrosecond));
85   }
86 }
87 
ETWInterceptor(TlmProvider * provider)88 ETWInterceptor::ETWInterceptor(TlmProvider* provider) : provider_(provider) {}
89 ETWInterceptor::~ETWInterceptor() = default;
90 
Register(TlmProvider * provider)91 void ETWInterceptor::Register(TlmProvider* provider) {
92   perfetto::protos::gen::InterceptorDescriptor desc;
93   desc.set_name("etwexport");
94   perfetto::Interceptor<ETWInterceptor>::Register(desc, provider);
95 }
96 
OnTracePacket(InterceptorContext context)97 void ETWInterceptor::OnTracePacket(InterceptorContext context) {
98   auto& tls = context.GetThreadLocalState();
99   perfetto::LockedHandle<ETWInterceptor> locked_self =
100       context.GetInterceptorLocked();
101   if (!locked_self) {
102     return;
103   }
104   Delegate delegate(std::move(locked_self));
105   perfetto::protos::pbzero::TracePacket::Decoder packet(
106       context.packet_data.data, context.packet_data.size);
107   perfetto::TrackEventStateTracker::ProcessTracePacket(
108       delegate, tls.sequence_state, packet);
109 }
110 
ThreadLocalState(ThreadLocalStateArgs & args)111 ETWInterceptor::ThreadLocalState::ThreadLocalState(ThreadLocalStateArgs& args) {
112 }
113 ETWInterceptor::ThreadLocalState::~ThreadLocalState() = default;
114 
OnSetup(const SetupArgs &)115 void ETWInterceptor::OnSetup(const SetupArgs&) {}
OnStart(const StartArgs &)116 void ETWInterceptor::OnStart(const StartArgs&) {}
OnStop(const StopArgs &)117 void ETWInterceptor::OnStop(const StopArgs&) {}
118 
119 }  // namespace base::trace_event
120