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