• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 #ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACING_SERVICE_H_
18 #define INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACING_SERVICE_H_
19 
20 #include <stdint.h>
21 
22 #include <functional>
23 #include <memory>
24 #include <vector>
25 
26 #include "perfetto/base/export.h"
27 #include "perfetto/ext/base/scoped_file.h"
28 #include "perfetto/ext/base/sys_types.h"
29 #include "perfetto/ext/tracing/core/basic_types.h"
30 #include "perfetto/ext/tracing/core/shared_memory.h"
31 #include "perfetto/tracing/buffer_exhausted_policy.h"
32 #include "perfetto/tracing/core/forward_decls.h"
33 
34 namespace perfetto {
35 
36 namespace base {
37 class TaskRunner;
38 }  // namespace base
39 
40 class Consumer;
41 class Producer;
42 class SharedMemoryArbiter;
43 class TraceWriter;
44 
45 // Exposed for testing.
46 std::string GetBugreportPath();
47 
48 // TODO: for the moment this assumes that all the calls happen on the same
49 // thread/sequence. Not sure this will be the case long term in Chrome.
50 
51 // The API for the Producer port of the Service.
52 // Subclassed by:
53 // 1. The tracing_service_impl.cc business logic when returning it in response
54 //    to the ConnectProducer() method.
55 // 2. The transport layer (e.g., src/ipc) when the producer and
56 //    the service don't talk locally but via some IPC mechanism.
57 class PERFETTO_EXPORT ProducerEndpoint {
58  public:
59   virtual ~ProducerEndpoint();
60 
61   // Called by the Producer to (un)register data sources. Data sources are
62   // identified by their name (i.e. DataSourceDescriptor.name)
63   virtual void RegisterDataSource(const DataSourceDescriptor&) = 0;
64   virtual void UpdateDataSource(const DataSourceDescriptor&) = 0;
65   virtual void UnregisterDataSource(const std::string& name) = 0;
66 
67   // Associate the trace writer with the given |writer_id| with
68   // |target_buffer|. The service may use this information to retrieve and
69   // copy uncommitted chunks written by the trace writer into its associated
70   // buffer, e.g. when a producer process crashes or when a flush is
71   // necessary.
72   virtual void RegisterTraceWriter(uint32_t writer_id,
73                                    uint32_t target_buffer) = 0;
74 
75   // Remove the association of the trace writer previously created via
76   // RegisterTraceWriter.
77   virtual void UnregisterTraceWriter(uint32_t writer_id) = 0;
78 
79   // Called by the Producer to signal that some pages in the shared memory
80   // buffer (shared between Service and Producer) have changed.
81   // When the Producer and the Service are hosted in the same process and
82   // hence potentially live on the same task runner, This method must call
83   // TracingServiceImpl's CommitData synchronously, without any PostTask()s,
84   // if on the same thread. This is to avoid a deadlock where the Producer
85   // exhausts its SMB and stalls waiting for the service to catch up with
86   // reads, but the Service never gets to that because it lives on the same
87   // thread.
88   using CommitDataCallback = std::function<void()>;
89   virtual void CommitData(const CommitDataRequest&,
90                           CommitDataCallback callback = {}) = 0;
91 
92   virtual SharedMemory* shared_memory() const = 0;
93 
94   // Size of shared memory buffer pages. It's always a multiple of 4K.
95   // See shared_memory_abi.h
96   virtual size_t shared_buffer_page_size_kb() const = 0;
97 
98   // Creates a trace writer, which allows to create events, handling the
99   // underying shared memory buffer and signalling to the Service. This method
100   // is thread-safe but the returned object is not. A TraceWriter should be
101   // used only from a single thread, or the caller has to handle sequencing
102   // via a mutex or equivalent. This method can only be called if
103   // TracingService::ConnectProducer was called with |in_process=true|.
104   // Args:
105   // |target_buffer| is the target buffer ID where the data produced by the
106   // writer should be stored by the tracing service. This value is passed
107   // upon creation of the data source (StartDataSource()) in the
108   // DataSourceConfig.target_buffer().
109   virtual std::unique_ptr<TraceWriter> CreateTraceWriter(
110       BufferID target_buffer,
111       BufferExhaustedPolicy buffer_exhausted_policy =
112           BufferExhaustedPolicy::kDefault) = 0;
113 
114   // TODO(eseckler): Also expose CreateStartupTraceWriter() ?
115 
116   // In some cases you can access the producer's SharedMemoryArbiter (for
117   // example if TracingService::ConnectProducer is called with
118   // |in_process=true|). The SharedMemoryArbiter can be used to create
119   // TraceWriters which is able to directly commit chunks. For the
120   // |in_process=true| case this can be done without going through an IPC layer.
121   virtual SharedMemoryArbiter* MaybeSharedMemoryArbiter() = 0;
122 
123   // Whether the service accepted a shared memory buffer provided by the
124   // producer.
125   virtual bool IsShmemProvidedByProducer() const = 0;
126 
127   // Called in response to a Producer::Flush(request_id) call after all data
128   // for the flush request has been committed.
129   virtual void NotifyFlushComplete(FlushRequestID) = 0;
130 
131   // Called in response to one or more Producer::StartDataSource(),
132   // if the data source registered setting the flag
133   // DataSourceDescriptor.will_notify_on_start.
134   virtual void NotifyDataSourceStarted(DataSourceInstanceID) = 0;
135 
136   // Called in response to one or more Producer::StopDataSource(),
137   // if the data source registered setting the flag
138   // DataSourceDescriptor.will_notify_on_stop.
139   virtual void NotifyDataSourceStopped(DataSourceInstanceID) = 0;
140 
141   // This informs the service to activate any of these triggers if any tracing
142   // session was waiting for them.
143   virtual void ActivateTriggers(const std::vector<std::string>&) = 0;
144 
145   // Emits a synchronization barrier to linearize with the service. When
146   // |callback| is invoked, the caller has the guarantee that the service has
147   // seen and processed all the requests sent by this producer prior to the
148   // Sync() call. Used mainly in tests.
149   virtual void Sync(std::function<void()> callback) = 0;
150 };  // class ProducerEndpoint.
151 
152 // The API for the Consumer port of the Service.
153 // Subclassed by:
154 // 1. The tracing_service_impl.cc business logic when returning it in response
155 // to
156 //    the ConnectConsumer() method.
157 // 2. The transport layer (e.g., src/ipc) when the consumer and
158 //    the service don't talk locally but via some IPC mechanism.
159 class PERFETTO_EXPORT ConsumerEndpoint {
160  public:
161   virtual ~ConsumerEndpoint();
162 
163   // Enables tracing with the given TraceConfig. The ScopedFile argument is
164   // used only when TraceConfig.write_into_file == true.
165   // If TraceConfig.deferred_start == true data sources are configured via
166   // SetupDataSource() but are not started until StartTracing() is called.
167   // This is to support pre-initialization and fast triggering of traces.
168   // The ScopedFile argument is used only when TraceConfig.write_into_file
169   // == true.
170   virtual void EnableTracing(const TraceConfig&,
171                              base::ScopedFile = base::ScopedFile()) = 0;
172 
173   // Update the trace config of an existing tracing session; only a subset
174   // of options can be changed mid-session. Currently the only
175   // supported functionality is expanding the list of producer_name_filters()
176   // (or removing the filter entirely) for existing data sources.
177   virtual void ChangeTraceConfig(const TraceConfig&) = 0;
178 
179   // Starts all data sources configured in the trace config. This is used only
180   // after calling EnableTracing() with TraceConfig.deferred_start=true.
181   // It's a no-op if called after a regular EnableTracing(), without setting
182   // deferred_start.
183   virtual void StartTracing() = 0;
184 
185   virtual void DisableTracing() = 0;
186 
187   // Requests all data sources to flush their data immediately and invokes the
188   // passed callback once all of them have acked the flush (in which case
189   // the callback argument |success| will be true) or |timeout_ms| are elapsed
190   // (in which case |success| will be false).
191   // If |timeout_ms| is 0 the TraceConfig's flush_timeout_ms is used, or,
192   // if that one is not set (or is set to 0), kDefaultFlushTimeoutMs (5s) is
193   // used.
194   using FlushCallback = std::function<void(bool /*success*/)>;
195   virtual void Flush(uint32_t timeout_ms, FlushCallback) = 0;
196 
197   // Tracing data will be delivered invoking Consumer::OnTraceData().
198   virtual void ReadBuffers() = 0;
199 
200   virtual void FreeBuffers() = 0;
201 
202   // Will call OnDetach().
203   virtual void Detach(const std::string& key) = 0;
204 
205   // Will call OnAttach().
206   virtual void Attach(const std::string& key) = 0;
207 
208   // Will call OnTraceStats().
209   virtual void GetTraceStats() = 0;
210 
211   // Start or stop observing events of selected types. |events_mask| specifies
212   // the types of events to observe in a bitmask of ObservableEvents::Type.
213   // To disable observing, pass 0.
214   // Will call OnObservableEvents() repeatedly whenever an event of an enabled
215   // ObservableEventType occurs.
216   // TODO(eseckler): Extend this to support producers & data sources.
217   virtual void ObserveEvents(uint32_t events_mask) = 0;
218 
219   // Used to obtain the list of connected data sources and other info about
220   // the tracing service.
221   using QueryServiceStateCallback =
222       std::function<void(bool success, const TracingServiceState&)>;
223   virtual void QueryServiceState(QueryServiceStateCallback) = 0;
224 
225   // Used for feature detection. Makes sense only when the consumer and the
226   // service talk over IPC and can be from different versions.
227   using QueryCapabilitiesCallback =
228       std::function<void(const TracingServiceCapabilities&)>;
229   virtual void QueryCapabilities(QueryCapabilitiesCallback) = 0;
230 
231   // If any tracing session with TraceConfig.bugreport_score > 0 is running,
232   // this will pick the highest-score one, stop it and save it into a fixed
233   // path (See kBugreportTracePath).
234   // The callback is invoked when the file has been saved, in case of success,
235   // or whenever an error occurs.
236   // Args:
237   // - success: if true, an eligible trace was found and saved into file.
238   //            If false, either there was no eligible trace running or
239   //            something else failed (See |msg|).
240   // - msg: human readable diagnostic messages to debug failures.
241   using SaveTraceForBugreportCallback =
242       std::function<void(bool /*success*/, const std::string& /*msg*/)>;
243   virtual void SaveTraceForBugreport(SaveTraceForBugreportCallback) = 0;
244 };  // class ConsumerEndpoint.
245 
246 // The public API of the tracing Service business logic.
247 //
248 // Exposed to:
249 // 1. The transport layer (e.g., src/unix_rpc/unix_service_host.cc),
250 //    which forwards commands received from a remote producer or consumer to
251 //    the actual service implementation.
252 // 2. Tests.
253 //
254 // Subclassed by:
255 //   The service business logic in src/core/tracing_service_impl.cc.
256 class PERFETTO_EXPORT TracingService {
257  public:
258   using ProducerEndpoint = perfetto::ProducerEndpoint;
259   using ConsumerEndpoint = perfetto::ConsumerEndpoint;
260 
261   enum class ProducerSMBScrapingMode {
262     // Use service's default setting for SMB scraping. Currently, the default
263     // mode is to disable SMB scraping, but this may change in the future.
264     kDefault,
265 
266     // Enable scraping of uncommitted chunks in producers' shared memory
267     // buffers.
268     kEnabled,
269 
270     // Disable scraping of uncommitted chunks in producers' shared memory
271     // buffers.
272     kDisabled
273   };
274 
275   // Implemented in src/core/tracing_service_impl.cc .
276   static std::unique_ptr<TracingService> CreateInstance(
277       std::unique_ptr<SharedMemory::Factory>,
278       base::TaskRunner*);
279 
280   virtual ~TracingService();
281 
282   // Connects a Producer instance and obtains a ProducerEndpoint, which is
283   // essentially a 1:1 channel between one Producer and the Service.
284   //
285   // The caller has to guarantee that the passed Producer will be alive as long
286   // as the returned ProducerEndpoint is alive. Both the passed Producer and the
287   // returned ProducerEndpoint must live on the same task runner of the service,
288   // specifically:
289   // 1) The Service will call Producer::* methods on the Service's task runner.
290   // 2) The Producer should call ProducerEndpoint::* methods only on the
291   //    service's task runner, except for ProducerEndpoint::CreateTraceWriter(),
292   //    which can be called on any thread. To disconnect just destroy the
293   //    returned ProducerEndpoint object. It is safe to destroy the Producer
294   //    once the Producer::OnDisconnect() has been invoked.
295   //
296   // |uid| is the trusted user id of the producer process, used by the consumers
297   // for validating the origin of trace data. |shared_memory_size_hint_bytes|
298   // and |shared_memory_page_size_hint_bytes| are optional hints on the size of
299   // the shared memory buffer and its pages. The service can ignore the hints
300   // (e.g., if the hints are unreasonably large or other sizes were configured
301   // in a tracing session's config). |in_process| enables the ProducerEndpoint
302   // to manage its own shared memory and enables use of
303   // |ProducerEndpoint::CreateTraceWriter|.
304   //
305   // The producer can optionally provide a non-null |shm|, which the service
306   // will adopt for the connection to the producer, provided it is correctly
307   // sized. In this case, |shared_memory_page_size_hint_bytes| indicates the
308   // page size used in this SMB. The producer can use this mechanism to record
309   // tracing data to an SMB even before the tracing session is started by the
310   // service. This is used in Chrome to implement startup tracing. If the buffer
311   // is incorrectly sized, the service will discard the SMB and allocate a new
312   // one, provided to the producer via ProducerEndpoint::shared_memory() after
313   // OnTracingSetup(). To verify that the service accepted the SMB, the producer
314   // may check via ProducerEndpoint::IsShmemProvidedByProducer(). If the service
315   // accepted the SMB, the producer can then commit any data that is already in
316   // the SMB after the tracing session was started by the service via
317   // Producer::StartDataSource(). The |shm| will also be rejected when
318   // connecting to a service that is too old (pre Android-11).
319   //
320   // Can return null in the unlikely event that service has too many producers
321   // connected.
322   virtual std::unique_ptr<ProducerEndpoint> ConnectProducer(
323       Producer*,
324       uid_t uid,
325       pid_t pid,
326       const std::string& name,
327       size_t shared_memory_size_hint_bytes = 0,
328       bool in_process = false,
329       ProducerSMBScrapingMode smb_scraping_mode =
330           ProducerSMBScrapingMode::kDefault,
331       size_t shared_memory_page_size_hint_bytes = 0,
332       std::unique_ptr<SharedMemory> shm = nullptr,
333       const std::string& sdk_version = {}) = 0;
334 
335   // Connects a Consumer instance and obtains a ConsumerEndpoint, which is
336   // essentially a 1:1 channel between one Consumer and the Service.
337   // The caller has to guarantee that the passed Consumer will be alive as long
338   // as the returned ConsumerEndpoint is alive.
339   // To disconnect just destroy the returned ConsumerEndpoint object. It is safe
340   // to destroy the Consumer once the Consumer::OnDisconnect() has been invoked.
341   virtual std::unique_ptr<ConsumerEndpoint> ConnectConsumer(Consumer*,
342                                                             uid_t) = 0;
343 
344   // Enable/disable scraping of chunks in the shared memory buffer. If enabled,
345   // the service will copy uncommitted but non-empty chunks from the SMB when
346   // flushing (e.g. to handle unresponsive producers or producers unable to
347   // flush their active chunks), on producer disconnect (e.g. to recover data
348   // from crashed producers), and after disabling a tracing session (e.g. to
349   // gather data from producers that didn't stop their data sources in time).
350   //
351   // This feature is currently used by Chrome.
352   virtual void SetSMBScrapingEnabled(bool enabled) = 0;
353 };
354 
355 }  // namespace perfetto
356 
357 #endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACING_SERVICE_H_
358