• 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/clock_snapshots.h"
28 #include "perfetto/ext/base/scoped_file.h"
29 #include "perfetto/ext/base/sys_types.h"
30 #include "perfetto/ext/tracing/core/basic_types.h"
31 #include "perfetto/ext/tracing/core/shared_memory.h"
32 #include "perfetto/ext/tracing/core/trace_packet.h"
33 #include "perfetto/tracing/buffer_exhausted_policy.h"
34 #include "perfetto/tracing/core/flush_flags.h"
35 #include "perfetto/tracing/core/forward_decls.h"
36 
37 namespace perfetto {
38 
39 namespace base {
40 class TaskRunner;
41 }  // namespace base
42 
43 class Consumer;
44 class Producer;
45 class SharedMemoryArbiter;
46 class TraceWriter;
47 class ClientIdentity;
48 
49 // TODO: for the moment this assumes that all the calls happen on the same
50 // thread/sequence. Not sure this will be the case long term in Chrome.
51 
52 // The API for the Producer port of the Service.
53 // Subclassed by:
54 // 1. The tracing_service_impl.cc business logic when returning it in response
55 //    to the ConnectProducer() method.
56 // 2. The transport layer (e.g., src/ipc) when the producer and
57 //    the service don't talk locally but via some IPC mechanism.
58 class PERFETTO_EXPORT_COMPONENT ProducerEndpoint {
59  public:
60   virtual ~ProducerEndpoint();
61 
62   // Disconnects the endpoint from the service, while keeping the shared memory
63   // valid. After calling this, the endpoint will no longer call any methods
64   // on the Producer.
65   virtual void Disconnect() = 0;
66 
67   // Called by the Producer to (un)register data sources. Data sources are
68   // identified by their name (i.e. DataSourceDescriptor.name)
69   virtual void RegisterDataSource(const DataSourceDescriptor&) = 0;
70   virtual void UpdateDataSource(const DataSourceDescriptor&) = 0;
71   virtual void UnregisterDataSource(const std::string& name) = 0;
72 
73   // Associate the trace writer with the given |writer_id| with
74   // |target_buffer|. The service may use this information to retrieve and
75   // copy uncommitted chunks written by the trace writer into its associated
76   // buffer, e.g. when a producer process crashes or when a flush is
77   // necessary.
78   virtual void RegisterTraceWriter(uint32_t writer_id,
79                                    uint32_t target_buffer) = 0;
80 
81   // Remove the association of the trace writer previously created via
82   // RegisterTraceWriter.
83   virtual void UnregisterTraceWriter(uint32_t writer_id) = 0;
84 
85   // Called by the Producer to signal that some pages in the shared memory
86   // buffer (shared between Service and Producer) have changed.
87   // When the Producer and the Service are hosted in the same process and
88   // hence potentially live on the same task runner, This method must call
89   // TracingServiceImpl's CommitData synchronously, without any PostTask()s,
90   // if on the same thread. This is to avoid a deadlock where the Producer
91   // exhausts its SMB and stalls waiting for the service to catch up with
92   // reads, but the Service never gets to that because it lives on the same
93   // thread.
94   using CommitDataCallback = std::function<void()>;
95   virtual void CommitData(const CommitDataRequest&,
96                           CommitDataCallback callback = {}) = 0;
97 
98   virtual SharedMemory* shared_memory() const = 0;
99 
100   // Size of shared memory buffer pages. It's always a multiple of 4K.
101   // See shared_memory_abi.h
102   virtual size_t shared_buffer_page_size_kb() const = 0;
103 
104   // Creates a trace writer, which allows to create events, handling the
105   // underying shared memory buffer and signalling to the Service. This method
106   // is thread-safe but the returned object is not. A TraceWriter should be
107   // used only from a single thread, or the caller has to handle sequencing
108   // via a mutex or equivalent. This method can only be called if
109   // TracingService::ConnectProducer was called with |in_process=true|.
110   // Args:
111   // |target_buffer| is the target buffer ID where the data produced by the
112   // writer should be stored by the tracing service. This value is passed
113   // upon creation of the data source (StartDataSource()) in the
114   // DataSourceConfig.target_buffer().
115   virtual std::unique_ptr<TraceWriter> CreateTraceWriter(
116       BufferID target_buffer,
117       BufferExhaustedPolicy buffer_exhausted_policy =
118           BufferExhaustedPolicy::kDefault) = 0;
119 
120   // TODO(eseckler): Also expose CreateStartupTraceWriter() ?
121 
122   // In some cases you can access the producer's SharedMemoryArbiter (for
123   // example if TracingService::ConnectProducer is called with
124   // |in_process=true|). The SharedMemoryArbiter can be used to create
125   // TraceWriters which is able to directly commit chunks. For the
126   // |in_process=true| case this can be done without going through an IPC layer.
127   virtual SharedMemoryArbiter* MaybeSharedMemoryArbiter() = 0;
128 
129   // Whether the service accepted a shared memory buffer provided by the
130   // producer.
131   virtual bool IsShmemProvidedByProducer() const = 0;
132 
133   // Called in response to a Producer::Flush(request_id) call after all data
134   // for the flush request has been committed.
135   virtual void NotifyFlushComplete(FlushRequestID) = 0;
136 
137   // Called in response to one or more Producer::StartDataSource(),
138   // if the data source registered setting the flag
139   // DataSourceDescriptor.will_notify_on_start.
140   virtual void NotifyDataSourceStarted(DataSourceInstanceID) = 0;
141 
142   // Called in response to one or more Producer::StopDataSource(),
143   // if the data source registered setting the flag
144   // DataSourceDescriptor.will_notify_on_stop.
145   virtual void NotifyDataSourceStopped(DataSourceInstanceID) = 0;
146 
147   // This informs the service to activate any of these triggers if any tracing
148   // session was waiting for them.
149   virtual void ActivateTriggers(const std::vector<std::string>&) = 0;
150 
151   // Emits a synchronization barrier to linearize with the service. When
152   // |callback| is invoked, the caller has the guarantee that the service has
153   // seen and processed all the requests sent by this producer prior to the
154   // Sync() call. Used mainly in tests.
155   virtual void Sync(std::function<void()> callback) = 0;
156 };  // class ProducerEndpoint.
157 
158 // The API for the Consumer port of the Service.
159 // Subclassed by:
160 // 1. The tracing_service_impl.cc business logic when returning it in response
161 // to
162 //    the ConnectConsumer() method.
163 // 2. The transport layer (e.g., src/ipc) when the consumer and
164 //    the service don't talk locally but via some IPC mechanism.
165 class PERFETTO_EXPORT_COMPONENT ConsumerEndpoint {
166  public:
167   virtual ~ConsumerEndpoint();
168 
169   // Enables tracing with the given TraceConfig. The ScopedFile argument is
170   // used only when TraceConfig.write_into_file == true.
171   // If TraceConfig.deferred_start == true data sources are configured via
172   // SetupDataSource() but are not started until StartTracing() is called.
173   // This is to support pre-initialization and fast triggering of traces.
174   // The ScopedFile argument is used only when TraceConfig.write_into_file
175   // == true.
176   virtual void EnableTracing(const TraceConfig&,
177                              base::ScopedFile = base::ScopedFile()) = 0;
178 
179   // Update the trace config of an existing tracing session; only a subset
180   // of options can be changed mid-session. Currently the only
181   // supported functionality is expanding the list of producer_name_filters()
182   // (or removing the filter entirely) for existing data sources.
183   virtual void ChangeTraceConfig(const TraceConfig&) = 0;
184 
185   // Starts all data sources configured in the trace config. This is used only
186   // after calling EnableTracing() with TraceConfig.deferred_start=true.
187   // It's a no-op if called after a regular EnableTracing(), without setting
188   // deferred_start.
189   virtual void StartTracing() = 0;
190 
191   virtual void DisableTracing() = 0;
192 
193   // Clones an existing tracing session and attaches to it. The session is
194   // cloned in read-only mode and can only be used to read a snapshot of an
195   // existing tracing session. Will invoke Consumer::OnSessionCloned().
196   struct CloneSessionArgs {
197     // Exactly one between tsid and unique_session_name should be set.
198 
199     // The id of the tracing session that should be cloned. If
200     // kBugreportSessionId (0xff...ff) the session with the highest bugreport
201     // score is cloned (if any exists).
202     TracingSessionID tsid = 0;
203 
204     // The unique_session_name of the session that should be cloned.
205     std::string unique_session_name;
206 
207     // If set, the trace filter will not have effect on the cloned session.
208     // Used for bugreports.
209     bool skip_trace_filter = false;
210 
211     // If set, affects the generation of the FlushFlags::CloneTarget to be set
212     // to kBugreport when requesting the flush to the producers.
213     bool for_bugreport = false;
214 
215     // If not empty, this is stored in the trace as name of the trigger that
216     // caused the clone.
217     std::string clone_trigger_name;
218     // If not empty, this is stored in the trace as name of the producer that
219     // triggered the clone.
220     std::string clone_trigger_producer_name;
221     // If not zero, this is stored in the trace as uid of the producer that
222     // triggered the clone.
223     uid_t clone_trigger_trusted_producer_uid = 0;
224     // If not zero, this is stored in the trace as timestamp of the trigger that
225     // caused the clone.
226     uint64_t clone_trigger_boot_time_ns = 0;
227   };
228   virtual void CloneSession(CloneSessionArgs) = 0;
229 
230   // Requests all data sources to flush their data immediately and invokes the
231   // passed callback once all of them have acked the flush (in which case
232   // the callback argument |success| will be true) or |timeout_ms| are elapsed
233   // (in which case |success| will be false).
234   // If |timeout_ms| is 0 the TraceConfig's flush_timeout_ms is used, or,
235   // if that one is not set (or is set to 0), kDefaultFlushTimeoutMs (5s) is
236   // used.
237   using FlushCallback = std::function<void(bool /*success*/)>;
238   virtual void Flush(uint32_t timeout_ms,
239                      FlushCallback callback,
240                      FlushFlags) = 0;
241 
242   // This is required for legacy out-of-repo clients like arctraceservice which
243   // use the 2-version parameter.
Flush(uint32_t timeout_ms,FlushCallback callback)244   inline void Flush(uint32_t timeout_ms, FlushCallback callback) {
245     Flush(timeout_ms, std::move(callback), FlushFlags());
246   }
247 
248   // Tracing data will be delivered invoking Consumer::OnTraceData().
249   virtual void ReadBuffers() = 0;
250 
251   virtual void FreeBuffers() = 0;
252 
253   // Will call OnDetach().
254   virtual void Detach(const std::string& key) = 0;
255 
256   // Will call OnAttach().
257   virtual void Attach(const std::string& key) = 0;
258 
259   // Will call OnTraceStats().
260   virtual void GetTraceStats() = 0;
261 
262   // Start or stop observing events of selected types. |events_mask| specifies
263   // the types of events to observe in a bitmask of ObservableEvents::Type.
264   // To disable observing, pass 0.
265   // Will call OnObservableEvents() repeatedly whenever an event of an enabled
266   // ObservableEventType occurs.
267   // TODO(eseckler): Extend this to support producers & data sources.
268   virtual void ObserveEvents(uint32_t events_mask) = 0;
269 
270   // Used to obtain the list of connected data sources and other info about
271   // the tracing service.
272   struct QueryServiceStateArgs {
273     // If set, only the TracingServiceState.tracing_sessions is filled.
274     bool sessions_only = false;
275   };
276   using QueryServiceStateCallback =
277       std::function<void(bool success, const TracingServiceState&)>;
278   virtual void QueryServiceState(QueryServiceStateArgs,
279                                  QueryServiceStateCallback) = 0;
280 
281   // Used for feature detection. Makes sense only when the consumer and the
282   // service talk over IPC and can be from different versions.
283   using QueryCapabilitiesCallback =
284       std::function<void(const TracingServiceCapabilities&)>;
285   virtual void QueryCapabilities(QueryCapabilitiesCallback) = 0;
286 
287   // If any tracing session with TraceConfig.bugreport_score > 0 is running,
288   // this will pick the highest-score one, stop it and save it into a fixed
289   // path (See kBugreportTracePath).
290   // The callback is invoked when the file has been saved, in case of success,
291   // or whenever an error occurs.
292   // Args:
293   // - success: if true, an eligible trace was found and saved into file.
294   //            If false, either there was no eligible trace running or
295   //            something else failed (See |msg|).
296   // - msg: human readable diagnostic messages to debug failures.
297   using SaveTraceForBugreportCallback =
298       std::function<void(bool /*success*/, const std::string& /*msg*/)>;
299   virtual void SaveTraceForBugreport(SaveTraceForBugreportCallback) = 0;
300 };  // class ConsumerEndpoint.
301 
302 struct PERFETTO_EXPORT_COMPONENT TracingServiceInitOpts {
303   // Function used by tracing service to compress packets. Takes a pointer to
304   // a vector of TracePackets and replaces the packets in the vector with
305   // compressed ones.
306   using CompressorFn = void (*)(std::vector<TracePacket>*);
307   CompressorFn compressor_fn = nullptr;
308 
309   // Whether the relay endpoint is enabled on producer transport(s).
310   bool enable_relay_endpoint = false;
311 };
312 
313 // The API for the Relay port of the Service. Subclassed by the
314 // tracing_service_impl.cc business logic when returning it in response to the
315 // ConnectRelayClient() method.
316 class PERFETTO_EXPORT_COMPONENT RelayEndpoint {
317  public:
318   virtual ~RelayEndpoint();
319 
320   // A snapshot of client and host clocks.
321   struct SyncClockSnapshot {
322     base::ClockSnapshotVector client_clock_snapshots;
323     base::ClockSnapshotVector host_clock_snapshots;
324   };
325 
326   enum class SyncMode : uint32_t { PING = 1, UPDATE = 2 };
327   virtual void SyncClocks(SyncMode sync_mode,
328                           base::ClockSnapshotVector client_clocks,
329                           base::ClockSnapshotVector host_clocks) = 0;
330   virtual void Disconnect() = 0;
331 };
332 
333 // The public API of the tracing Service business logic.
334 //
335 // Exposed to:
336 // 1. The transport layer (e.g., src/unix_rpc/unix_service_host.cc),
337 //    which forwards commands received from a remote producer or consumer to
338 //    the actual service implementation.
339 // 2. Tests.
340 //
341 // Subclassed by:
342 //   The service business logic in src/core/tracing_service_impl.cc.
343 class PERFETTO_EXPORT_COMPONENT TracingService {
344  public:
345   using ProducerEndpoint = perfetto::ProducerEndpoint;
346   using ConsumerEndpoint = perfetto::ConsumerEndpoint;
347   using RelayEndpoint = perfetto::RelayEndpoint;
348   using InitOpts = TracingServiceInitOpts;
349 
350   // Default sizes used by the service implementation and client library.
351   static constexpr size_t kDefaultShmPageSize = 4096ul;
352   static constexpr size_t kDefaultShmSize = 256 * 1024ul;
353 
354   enum class ProducerSMBScrapingMode {
355     // Use service's default setting for SMB scraping. Currently, the default
356     // mode is to disable SMB scraping, but this may change in the future.
357     kDefault,
358 
359     // Enable scraping of uncommitted chunks in producers' shared memory
360     // buffers.
361     kEnabled,
362 
363     // Disable scraping of uncommitted chunks in producers' shared memory
364     // buffers.
365     kDisabled
366   };
367 
368   // Implemented in src/core/tracing_service_impl.cc . CompressorFn can be
369   // nullptr, in which case TracingService will not support compression.
370   static std::unique_ptr<TracingService> CreateInstance(
371       std::unique_ptr<SharedMemory::Factory>,
372       base::TaskRunner*,
373       InitOpts init_opts = {});
374 
375   virtual ~TracingService();
376 
377   // Connects a Producer instance and obtains a ProducerEndpoint, which is
378   // essentially a 1:1 channel between one Producer and the Service.
379   //
380   // The caller has to guarantee that the passed Producer will be alive as long
381   // as the returned ProducerEndpoint is alive. Both the passed Producer and the
382   // returned ProducerEndpoint must live on the same task runner of the service,
383   // specifically:
384   // 1) The Service will call Producer::* methods on the Service's task runner.
385   // 2) The Producer should call ProducerEndpoint::* methods only on the
386   //    service's task runner, except for ProducerEndpoint::CreateTraceWriter(),
387   //    which can be called on any thread. To disconnect just destroy the
388   //    returned ProducerEndpoint object. It is safe to destroy the Producer
389   //    once the Producer::OnDisconnect() has been invoked.
390   //
391   // |uid| is the trusted user id of the producer process, used by the consumers
392   // for validating the origin of trace data. |shared_memory_size_hint_bytes|
393   // and |shared_memory_page_size_hint_bytes| are optional hints on the size of
394   // the shared memory buffer and its pages. The service can ignore the hints
395   // (e.g., if the hints are unreasonably large or other sizes were configured
396   // in a tracing session's config). |in_process| enables the ProducerEndpoint
397   // to manage its own shared memory and enables use of
398   // |ProducerEndpoint::CreateTraceWriter|.
399   //
400   // The producer can optionally provide a non-null |shm|, which the service
401   // will adopt for the connection to the producer, provided it is correctly
402   // sized. In this case, |shared_memory_page_size_hint_bytes| indicates the
403   // page size used in this SMB. The producer can use this mechanism to record
404   // tracing data to an SMB even before the tracing session is started by the
405   // service. This is used in Chrome to implement startup tracing. If the buffer
406   // is incorrectly sized, the service will discard the SMB and allocate a new
407   // one, provided to the producer via ProducerEndpoint::shared_memory() after
408   // OnTracingSetup(). To verify that the service accepted the SMB, the producer
409   // may check via ProducerEndpoint::IsShmemProvidedByProducer(). If the service
410   // accepted the SMB, the producer can then commit any data that is already in
411   // the SMB after the tracing session was started by the service via
412   // Producer::StartDataSource(). The |shm| will also be rejected when
413   // connecting to a service that is too old (pre Android-11).
414   //
415   // Can return null in the unlikely event that service has too many producers
416   // connected.
417   virtual std::unique_ptr<ProducerEndpoint> ConnectProducer(
418       Producer*,
419       const ClientIdentity& client_identity,
420       const std::string& name,
421       size_t shared_memory_size_hint_bytes = 0,
422       bool in_process = false,
423       ProducerSMBScrapingMode smb_scraping_mode =
424           ProducerSMBScrapingMode::kDefault,
425       size_t shared_memory_page_size_hint_bytes = 0,
426       std::unique_ptr<SharedMemory> shm = nullptr,
427       const std::string& sdk_version = {}) = 0;
428 
429   // Connects a Consumer instance and obtains a ConsumerEndpoint, which is
430   // essentially a 1:1 channel between one Consumer and the Service.
431   // The caller has to guarantee that the passed Consumer will be alive as long
432   // as the returned ConsumerEndpoint is alive.
433   // To disconnect just destroy the returned ConsumerEndpoint object. It is safe
434   // to destroy the Consumer once the Consumer::OnDisconnect() has been invoked.
435   virtual std::unique_ptr<ConsumerEndpoint> ConnectConsumer(Consumer*,
436                                                             uid_t) = 0;
437 
438   // Enable/disable scraping of chunks in the shared memory buffer. If enabled,
439   // the service will copy uncommitted but non-empty chunks from the SMB when
440   // flushing (e.g. to handle unresponsive producers or producers unable to
441   // flush their active chunks), on producer disconnect (e.g. to recover data
442   // from crashed producers), and after disabling a tracing session (e.g. to
443   // gather data from producers that didn't stop their data sources in time).
444   //
445   // This feature is currently used by Chrome.
446   virtual void SetSMBScrapingEnabled(bool enabled) = 0;
447 
448   using RelayClientID = std::pair<base::MachineID, /*client ID*/ uint64_t>;
449   // Connects a remote RelayClient instance and obtains a RelayEndpoint, which
450   // is a 1:1 channel between one RelayClient and the Service. To disconnect
451   // just call Disconnect() of the RelayEndpoint instance. The relay client is
452   // connected using an identifier of MachineID and client ID. The service
453   // doesn't hold an object that represents the client because the relay port
454   // only has a client-to-host SyncClock() method.
455   //
456   // TODO(chinglinyu): connect the relay client using a RelayClient* object when
457   // we need host-to-client RPC method.
458   virtual std::unique_ptr<RelayEndpoint> ConnectRelayClient(RelayClientID) = 0;
459 };
460 
461 }  // namespace perfetto
462 
463 #endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACING_SERVICE_H_
464