• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(InterceptorContext & context)19   explicit Delegate(InterceptorContext& context)
20       : context_(&context), locked_self_(context_->GetInterceptorLocked()) {}
21   ~Delegate() override;
22 
23   perfetto::TrackEventStateTracker::SessionState* GetSessionState() override;
24   void OnTrackUpdated(perfetto::TrackEventStateTracker::Track&) override;
25   void OnTrackEvent(
26       const perfetto::TrackEventStateTracker::Track&,
27       const perfetto::TrackEventStateTracker::ParsedTrackEvent&) override;
28 
29  private:
30   raw_ptr<InterceptorContext> context_;
31   perfetto::LockedHandle<ETWInterceptor> locked_self_;
32 };
33 
34 ETWInterceptor::Delegate::~Delegate() = default;
35 
36 perfetto::TrackEventStateTracker::SessionState*
GetSessionState()37 ETWInterceptor::Delegate::GetSessionState() {
38   return &locked_self_->session_state_;
39 }
40 
OnTrackUpdated(perfetto::TrackEventStateTracker::Track & track)41 void ETWInterceptor::Delegate::OnTrackUpdated(
42     perfetto::TrackEventStateTracker::Track& track) {}
43 
OnTrackEvent(const perfetto::TrackEventStateTracker::Track & track,const perfetto::TrackEventStateTracker::ParsedTrackEvent & event)44 void ETWInterceptor::Delegate::OnTrackEvent(
45     const perfetto::TrackEventStateTracker::Track& track,
46     const perfetto::TrackEventStateTracker::ParsedTrackEvent& event) {
47   uint64_t keyword = base::trace_event::CategoryGroupToETWKeyword(
48       std::string_view(event.category.data, event.category.size));
49   const char* phase_string = nullptr;
50   switch (event.track_event.type()) {
51     case perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN:
52       phase_string = "Begin";
53       break;
54     case perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END:
55       phase_string = "End";
56       break;
57     case perfetto::protos::pbzero::TrackEvent::TYPE_INSTANT:
58       phase_string = "Instant";
59       break;
60   }
61   DCHECK_NE(nullptr, phase_string);
62   // TODO(crbug.com/1465855): Consider exporting thread time once
63   // TrackEventStateTracker supports it.
64   if (event.track_event.type() ==
65       perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END) {
66     locked_self_->provider_->WriteEvent(
67         std::string_view(event.name.data, event.name.size),
68         TlmEventDescriptor(0, keyword),
69         TlmMbcsStringField("Phase", phase_string),
70         TlmUInt64Field(
71             "Timestamp",
72             event.timestamp_ns / base::TimeTicks::kNanosecondsPerMicrosecond),
73         TlmUInt64Field(
74             "Duration",
75             event.duration_ns / base::TimeTicks::kNanosecondsPerMicrosecond));
76   } else {
77     locked_self_->provider_->WriteEvent(
78         std::string_view(event.name.data, event.name.size),
79         TlmEventDescriptor(0, keyword),
80         TlmMbcsStringField("Phase", phase_string),
81         TlmUInt64Field(
82             "Timestamp",
83             event.timestamp_ns / base::TimeTicks::kNanosecondsPerMicrosecond));
84   }
85 }
86 
ETWInterceptor(TlmProvider * provider)87 ETWInterceptor::ETWInterceptor(TlmProvider* provider) : provider_(provider) {}
88 ETWInterceptor::~ETWInterceptor() = default;
89 
Register(TlmProvider * provider)90 void ETWInterceptor::Register(TlmProvider* provider) {
91   perfetto::protos::gen::InterceptorDescriptor desc;
92   desc.set_name("etwexport");
93   perfetto::Interceptor<ETWInterceptor>::Register(desc, provider);
94 }
95 
OnTracePacket(InterceptorContext context)96 void ETWInterceptor::OnTracePacket(InterceptorContext context) {
97   auto& tls = context.GetThreadLocalState();
98   Delegate delegate(context);
99   perfetto::protos::pbzero::TracePacket::Decoder packet(
100       context.packet_data.data, context.packet_data.size);
101   perfetto::TrackEventStateTracker::ProcessTracePacket(
102       delegate, tls.sequence_state, packet);
103 }
104 
ThreadLocalState(ThreadLocalStateArgs & args)105 ETWInterceptor::ThreadLocalState::ThreadLocalState(ThreadLocalStateArgs& args) {
106 }
107 ETWInterceptor::ThreadLocalState::~ThreadLocalState() = default;
108 
OnSetup(const SetupArgs &)109 void ETWInterceptor::OnSetup(const SetupArgs&) {}
OnStart(const StartArgs &)110 void ETWInterceptor::OnStart(const StartArgs&) {}
OnStop(const StopArgs &)111 void ETWInterceptor::OnStop(const StopArgs&) {}
112 
113 }  // namespace base::trace_event
114