1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACE_EVENT_DATA_SOURCE_H_
6 #define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACE_EVENT_DATA_SOURCE_H_
7
8 #include <atomic>
9 #include <memory>
10 #include <string>
11 #include <vector>
12
13 #include "base/component_export.h"
14 #include "base/macros.h"
15 #include "base/memory/ref_counted_memory.h"
16 #include "base/metrics/histogram_base.h"
17 #include "base/metrics/user_metrics.h"
18 #include "base/sequence_checker.h"
19 #include "base/threading/thread_local.h"
20 #include "base/time/time.h"
21 #include "base/timer/timer.h"
22 #include "base/trace_event/trace_config.h"
23 #include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
24 #include "services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h"
25 #include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pbzero.h"
26 #include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h"
27
28 namespace base {
29 namespace trace_event {
30 class ThreadInstructionCount;
31 class TraceEvent;
32 struct TraceEventHandle;
33 } // namespace trace_event
34 } // namespace base
35
36 namespace perfetto {
37 class TraceWriter;
38 class EventContext;
39 }
40
41 namespace tracing {
42
43 class ThreadLocalEventSink;
44
45 class AutoThreadLocalBoolean {
46 public:
AutoThreadLocalBoolean(base::ThreadLocalBoolean * thread_local_boolean)47 explicit AutoThreadLocalBoolean(
48 base::ThreadLocalBoolean* thread_local_boolean)
49 : thread_local_boolean_(thread_local_boolean) {
50 DCHECK(!thread_local_boolean_->Get());
51 thread_local_boolean_->Set(true);
52 }
~AutoThreadLocalBoolean()53 ~AutoThreadLocalBoolean() { thread_local_boolean_->Set(false); }
54
55 private:
56 base::ThreadLocalBoolean* thread_local_boolean_;
57 DISALLOW_COPY_AND_ASSIGN(AutoThreadLocalBoolean);
58 };
59
60 // This class is a data source that clients can use to provide
61 // global metadata in dictionary form, by registering callbacks.
COMPONENT_EXPORT(TRACING_CPP)62 class COMPONENT_EXPORT(TRACING_CPP) TraceEventMetadataSource
63 : public PerfettoTracedProcess::DataSourceBase {
64 public:
65 static TraceEventMetadataSource* GetInstance();
66
67 using JsonMetadataGeneratorFunction =
68 base::RepeatingCallback<std::unique_ptr<base::DictionaryValue>()>;
69
70 using MetadataGeneratorFunction = base::RepeatingCallback<void(
71 perfetto::protos::pbzero::ChromeMetadataPacket*,
72 bool /* privacy_filtering_enabled */)>;
73
74 // Any callbacks passed here will be called when tracing. Note that if tracing
75 // is enabled while calling this method, the callback may be invoked
76 // directly.
77 void AddGeneratorFunction(JsonMetadataGeneratorFunction generator);
78 // Same as above, but for filling in proto format.
79 void AddGeneratorFunction(MetadataGeneratorFunction generator);
80 // For background tracing, the legacy crash uploader needs
81 // metadata fields to be uploaded as POST args in addition to being
82 // embedded in the trace. TODO(oysteine): Remove when only the
83 // UMA uploader path is used.
84 std::unique_ptr<base::DictionaryValue> GenerateLegacyMetadataDict();
85
86 // PerfettoTracedProcess::DataSourceBase implementation, called by
87 // ProducerClent.
88 void StartTracing(
89 PerfettoProducer* producer,
90 const perfetto::DataSourceConfig& data_source_config) override;
91 void StopTracing(base::OnceClosure stop_complete_callback) override;
92 void Flush(base::RepeatingClosure flush_complete_callback) override;
93
94 void ResetForTesting();
95
96 private:
97 friend class base::NoDestructor<TraceEventMetadataSource>;
98
99 TraceEventMetadataSource();
100 ~TraceEventMetadataSource() override;
101
102 void GenerateMetadata(
103 std::unique_ptr<std::vector<JsonMetadataGeneratorFunction>>
104 json_generators,
105 std::unique_ptr<std::vector<MetadataGeneratorFunction>> proto_generators);
106 void GenerateMetadataFromGenerator(
107 const MetadataGeneratorFunction& generator);
108 void GenerateJsonMetadataFromGenerator(
109 const JsonMetadataGeneratorFunction& generator,
110 perfetto::protos::pbzero::ChromeEventBundle* event_bundle);
111 std::unique_ptr<base::DictionaryValue> GenerateTraceConfigMetadataDict();
112
113 // All members are protected by |lock_|.
114 base::Lock lock_;
115 std::vector<JsonMetadataGeneratorFunction> json_generator_functions_;
116 std::vector<MetadataGeneratorFunction> generator_functions_;
117
118 const scoped_refptr<base::SequencedTaskRunner> origin_task_runner_;
119
120 std::unique_ptr<perfetto::TraceWriter> trace_writer_;
121 bool privacy_filtering_enabled_ = false;
122 std::string chrome_config_;
123 std::unique_ptr<base::trace_event::TraceConfig> parsed_chrome_config_;
124 bool emit_metadata_at_start_ = false;
125
126 DISALLOW_COPY_AND_ASSIGN(TraceEventMetadataSource);
127 };
128
129 // This class acts as a bridge between the TraceLog and
130 // the PerfettoProducer. It converts incoming
131 // trace events to ChromeTraceEvent protos and writes
132 // them into the Perfetto shared memory.
COMPONENT_EXPORT(TRACING_CPP)133 class COMPONENT_EXPORT(TRACING_CPP) TraceEventDataSource
134 : public PerfettoTracedProcess::DataSourceBase {
135 public:
136 struct SessionFlags {
137 // True if startup tracing is enabled for the current tracing session.
138 uint32_t is_startup_tracing : 1;
139
140 // This ID is incremented whenever a new tracing session is started (either
141 // when startup tracing is enabled or when the service tells us to start the
142 // session otherwise).
143 uint32_t session_id : 31;
144 };
145
146 static TraceEventDataSource* GetInstance();
147
148 // Destroys and recreates the global instance for testing.
149 static void ResetForTesting();
150
151 // Flushes and deletes the TraceWriter for the current thread, if any.
152 static void FlushCurrentThread();
153
154 static base::ThreadLocalBoolean* GetThreadIsInTraceEventTLS();
155
156 // Installs TraceLog overrides for tracing during Chrome startup.
157 void RegisterStartupHooks();
158
159 // The PerfettoProducer is responsible for calling StopTracing
160 // which will clear the stored pointer to it, before it
161 // gets destroyed. PerfettoProducer::CreateTraceWriter can be
162 // called by the TraceEventDataSource on any thread.
163 void StartTracing(
164 PerfettoProducer* producer,
165 const perfetto::DataSourceConfig& data_source_config) override;
166
167 // Called from the PerfettoProducer.
168 void StopTracing(base::OnceClosure stop_complete_callback) override;
169 void Flush(base::RepeatingClosure flush_complete_callback) override;
170 void ClearIncrementalState() override;
171 void SetupStartupTracing(PerfettoProducer* producer,
172 const base::trace_event::TraceConfig& trace_config,
173 bool privacy_filtering_enabled) override;
174 void AbortStartupTracing() override;
175
176 // Deletes TraceWriter safely on behalf of a ThreadLocalEventSink.
177 void ReturnTraceWriter(std::unique_ptr<perfetto::TraceWriter> trace_writer);
178
179 bool privacy_filtering_enabled() const { return privacy_filtering_enabled_; }
180
181 bool IsEnabled();
182
183 static TrackEventThreadLocalEventSink* GetOrPrepareEventSink(
184 bool thread_will_flush);
185
186 template <
187 typename TrackEventArgumentFunction = void (*)(perfetto::EventContext)>
188 static void OnAddTraceEvent(base::trace_event::TraceEvent* trace_event,
189 bool thread_will_flush,
190 base::trace_event::TraceEventHandle* handle,
191 TrackEventArgumentFunction func) {
192 auto* thread_local_event_sink = GetOrPrepareEventSink(thread_will_flush);
193 if (thread_local_event_sink) {
194 AutoThreadLocalBoolean thread_is_in_trace_event(
195 GetThreadIsInTraceEventTLS());
196 thread_local_event_sink->AddTraceEvent(trace_event, handle, func);
197 }
198 }
199
200 // Registered with base::StatisticsRecorder to receive a callback on every
201 // histogram sample which gets added.
202 static void OnMetricsSampleCallback(const char* histogram_name,
203 uint64_t name_hash,
204 base::HistogramBase::Sample sample);
205
206 // Registered as a callback to receive every action recorded using
207 // base::RecordAction(), when tracing is enabled with a histogram category.
208 static void OnUserActionSampleCallback(const std::string& action,
209 base::TimeTicks action_time);
210
211 private:
212 friend class base::NoDestructor<TraceEventDataSource>;
213
214 TraceEventDataSource();
215 ~TraceEventDataSource() override;
216
217 void OnFlushFinished(const scoped_refptr<base::RefCountedString>&,
218 bool has_more_events);
219
220 void StartTracingInternal(
221 PerfettoProducer* producer_client,
222 const perfetto::DataSourceConfig& data_source_config);
223
224 void RegisterWithTraceLog();
225 void OnStopTracingDone();
226
227 std::unique_ptr<perfetto::TraceWriter> CreateTraceWriterLocked();
228 TrackEventThreadLocalEventSink* CreateThreadLocalEventSink(
229 bool thread_will_flush);
230
231 // Callback from TraceLog, can be called from any thread.
232 static void OnAddTraceEvent(base::trace_event::TraceEvent* trace_event,
233 bool thread_will_flush,
234 base::trace_event::TraceEventHandle* handle);
235 static void OnUpdateDuration(
236 const unsigned char* category_group_enabled,
237 const char* name,
238 base::trace_event::TraceEventHandle handle,
239 int thread_id,
240 bool explicit_timestamps,
241 const base::TimeTicks& now,
242 const base::ThreadTicks& thread_now,
243 base::trace_event::ThreadInstructionCount thread_instruction_now);
244
245 // Extracts UMA histogram names that should be logged in traces and logs their
246 // starting values.
247 void ResetHistograms(const base::trace_event::TraceConfig& trace_config);
248 // Logs selected UMA histogram.
249 void LogHistograms();
250 // Logs a given histogram in traces.
251 void LogHistogram(base::HistogramBase* histogram);
252 void EmitTrackDescriptor();
253
254 uint32_t IncrementSessionIdOrClearStartupFlagWhileLocked();
255 void SetStartupTracingFlagsWhileLocked();
256 bool IsStartupTracingActive() const;
257 bool IsPrivacyFilteringEnabled(); // Takes the |lock_|.
258
259 bool disable_interning_ = false;
260 base::OnceClosure stop_complete_callback_;
261
262 // Incremented and accessed atomically but without memory order guarantees.
263 static constexpr uint32_t kInvalidSessionID = 0;
264 std::atomic<SessionFlags> session_flags_{
265 SessionFlags{false, kInvalidSessionID}};
266
267 // To avoid lock-order inversion, this lock should not be held while making
268 // calls to mojo interfaces or posting tasks, or calling any other code path
269 // that may acquire another lock that may also be held while emitting a trace
270 // event (crbug.com/986248). Use AutoLockWithDeferredTaskPosting rather than
271 // base::AutoLock to protect code paths which may post tasks.
272 base::Lock lock_; // Protects subsequent members.
273 uint32_t target_buffer_ = 0;
274 std::unique_ptr<perfetto::TraceWriter> trace_writer_;
275 bool is_enabled_ = false;
276 bool flushing_trace_log_ = false;
277 base::OnceClosure flush_complete_task_;
278 std::vector<std::string> histograms_;
279 bool privacy_filtering_enabled_ = false;
280 std::string process_name_;
281 int process_id_ = base::kNullProcessId;
282 base::ActionCallback user_action_callback_ =
283 base::BindRepeating(&TraceEventDataSource::OnUserActionSampleCallback);
284 SEQUENCE_CHECKER(perfetto_sequence_checker_);
285
286 DISALLOW_COPY_AND_ASSIGN(TraceEventDataSource);
287 };
288
289 } // namespace tracing
290
291 #endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACE_EVENT_DATA_SOURCE_H_
292