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