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