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