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/clock_snapshots.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 // If TracingSessionID == kBugreportSessionId (0xff...ff) the session with the 197 // highest bugreport score is cloned (if any exists). 198 struct CloneSessionArgs { 199 // If set, the trace filter will not have effect on the cloned session. 200 // Used for bugreports. 201 bool skip_trace_filter = false; 202 203 // If set, affects the generation of the FlushFlags::CloneTarget to be set 204 // to kBugreport when requesting the flush to the producers. 205 bool for_bugreport = false; 206 }; 207 virtual void CloneSession(TracingSessionID, CloneSessionArgs) = 0; 208 209 // Requests all data sources to flush their data immediately and invokes the 210 // passed callback once all of them have acked the flush (in which case 211 // the callback argument |success| will be true) or |timeout_ms| are elapsed 212 // (in which case |success| will be false). 213 // If |timeout_ms| is 0 the TraceConfig's flush_timeout_ms is used, or, 214 // if that one is not set (or is set to 0), kDefaultFlushTimeoutMs (5s) is 215 // used. 216 using FlushCallback = std::function<void(bool /*success*/)>; 217 virtual void Flush(uint32_t timeout_ms, 218 FlushCallback callback, 219 FlushFlags) = 0; 220 221 // This is required for legacy out-of-repo clients like arctraceservice which 222 // use the 2-version parameter. Flush(uint32_t timeout_ms,FlushCallback callback)223 inline void Flush(uint32_t timeout_ms, FlushCallback callback) { 224 Flush(timeout_ms, std::move(callback), FlushFlags()); 225 } 226 227 // Tracing data will be delivered invoking Consumer::OnTraceData(). 228 virtual void ReadBuffers() = 0; 229 230 virtual void FreeBuffers() = 0; 231 232 // Will call OnDetach(). 233 virtual void Detach(const std::string& key) = 0; 234 235 // Will call OnAttach(). 236 virtual void Attach(const std::string& key) = 0; 237 238 // Will call OnTraceStats(). 239 virtual void GetTraceStats() = 0; 240 241 // Start or stop observing events of selected types. |events_mask| specifies 242 // the types of events to observe in a bitmask of ObservableEvents::Type. 243 // To disable observing, pass 0. 244 // Will call OnObservableEvents() repeatedly whenever an event of an enabled 245 // ObservableEventType occurs. 246 // TODO(eseckler): Extend this to support producers & data sources. 247 virtual void ObserveEvents(uint32_t events_mask) = 0; 248 249 // Used to obtain the list of connected data sources and other info about 250 // the tracing service. 251 struct QueryServiceStateArgs { 252 // If set, only the TracingServiceState.tracing_sessions is filled. 253 bool sessions_only = false; 254 }; 255 using QueryServiceStateCallback = 256 std::function<void(bool success, const TracingServiceState&)>; 257 virtual void QueryServiceState(QueryServiceStateArgs, 258 QueryServiceStateCallback) = 0; 259 260 // Used for feature detection. Makes sense only when the consumer and the 261 // service talk over IPC and can be from different versions. 262 using QueryCapabilitiesCallback = 263 std::function<void(const TracingServiceCapabilities&)>; 264 virtual void QueryCapabilities(QueryCapabilitiesCallback) = 0; 265 266 // If any tracing session with TraceConfig.bugreport_score > 0 is running, 267 // this will pick the highest-score one, stop it and save it into a fixed 268 // path (See kBugreportTracePath). 269 // The callback is invoked when the file has been saved, in case of success, 270 // or whenever an error occurs. 271 // Args: 272 // - success: if true, an eligible trace was found and saved into file. 273 // If false, either there was no eligible trace running or 274 // something else failed (See |msg|). 275 // - msg: human readable diagnostic messages to debug failures. 276 using SaveTraceForBugreportCallback = 277 std::function<void(bool /*success*/, const std::string& /*msg*/)>; 278 virtual void SaveTraceForBugreport(SaveTraceForBugreportCallback) = 0; 279 }; // class ConsumerEndpoint. 280 281 struct PERFETTO_EXPORT_COMPONENT TracingServiceInitOpts { 282 // Function used by tracing service to compress packets. Takes a pointer to 283 // a vector of TracePackets and replaces the packets in the vector with 284 // compressed ones. 285 using CompressorFn = void (*)(std::vector<TracePacket>*); 286 CompressorFn compressor_fn = nullptr; 287 288 // Whether the relay endpoint is enabled on producer transport(s). 289 bool enable_relay_endpoint = false; 290 }; 291 292 // The API for the Relay port of the Service. Subclassed by the 293 // tracing_service_impl.cc business logic when returning it in response to the 294 // ConnectRelayClient() method. 295 class PERFETTO_EXPORT_COMPONENT RelayEndpoint { 296 public: 297 virtual ~RelayEndpoint(); 298 299 // A snapshot of client and host clocks. 300 struct SyncClockSnapshot { 301 ClockSnapshotVector client_clock_snapshots; 302 ClockSnapshotVector host_clock_snapshots; 303 }; 304 305 enum class SyncMode : uint32_t { PING = 1, UPDATE = 2 }; 306 virtual void SyncClocks(SyncMode sync_mode, 307 ClockSnapshotVector client_clocks, 308 ClockSnapshotVector host_clocks) = 0; 309 virtual void Disconnect() = 0; 310 }; 311 312 // The public API of the tracing Service business logic. 313 // 314 // Exposed to: 315 // 1. The transport layer (e.g., src/unix_rpc/unix_service_host.cc), 316 // which forwards commands received from a remote producer or consumer to 317 // the actual service implementation. 318 // 2. Tests. 319 // 320 // Subclassed by: 321 // The service business logic in src/core/tracing_service_impl.cc. 322 class PERFETTO_EXPORT_COMPONENT TracingService { 323 public: 324 using ProducerEndpoint = perfetto::ProducerEndpoint; 325 using ConsumerEndpoint = perfetto::ConsumerEndpoint; 326 using RelayEndpoint = perfetto::RelayEndpoint; 327 using InitOpts = TracingServiceInitOpts; 328 329 // Default sizes used by the service implementation and client library. 330 static constexpr size_t kDefaultShmPageSize = 4096ul; 331 static constexpr size_t kDefaultShmSize = 256 * 1024ul; 332 333 enum class ProducerSMBScrapingMode { 334 // Use service's default setting for SMB scraping. Currently, the default 335 // mode is to disable SMB scraping, but this may change in the future. 336 kDefault, 337 338 // Enable scraping of uncommitted chunks in producers' shared memory 339 // buffers. 340 kEnabled, 341 342 // Disable scraping of uncommitted chunks in producers' shared memory 343 // buffers. 344 kDisabled 345 }; 346 347 // Implemented in src/core/tracing_service_impl.cc . CompressorFn can be 348 // nullptr, in which case TracingService will not support compression. 349 static std::unique_ptr<TracingService> CreateInstance( 350 std::unique_ptr<SharedMemory::Factory>, 351 base::TaskRunner*, 352 InitOpts init_opts = {}); 353 354 virtual ~TracingService(); 355 356 // Connects a Producer instance and obtains a ProducerEndpoint, which is 357 // essentially a 1:1 channel between one Producer and the Service. 358 // 359 // The caller has to guarantee that the passed Producer will be alive as long 360 // as the returned ProducerEndpoint is alive. Both the passed Producer and the 361 // returned ProducerEndpoint must live on the same task runner of the service, 362 // specifically: 363 // 1) The Service will call Producer::* methods on the Service's task runner. 364 // 2) The Producer should call ProducerEndpoint::* methods only on the 365 // service's task runner, except for ProducerEndpoint::CreateTraceWriter(), 366 // which can be called on any thread. To disconnect just destroy the 367 // returned ProducerEndpoint object. It is safe to destroy the Producer 368 // once the Producer::OnDisconnect() has been invoked. 369 // 370 // |uid| is the trusted user id of the producer process, used by the consumers 371 // for validating the origin of trace data. |shared_memory_size_hint_bytes| 372 // and |shared_memory_page_size_hint_bytes| are optional hints on the size of 373 // the shared memory buffer and its pages. The service can ignore the hints 374 // (e.g., if the hints are unreasonably large or other sizes were configured 375 // in a tracing session's config). |in_process| enables the ProducerEndpoint 376 // to manage its own shared memory and enables use of 377 // |ProducerEndpoint::CreateTraceWriter|. 378 // 379 // The producer can optionally provide a non-null |shm|, which the service 380 // will adopt for the connection to the producer, provided it is correctly 381 // sized. In this case, |shared_memory_page_size_hint_bytes| indicates the 382 // page size used in this SMB. The producer can use this mechanism to record 383 // tracing data to an SMB even before the tracing session is started by the 384 // service. This is used in Chrome to implement startup tracing. If the buffer 385 // is incorrectly sized, the service will discard the SMB and allocate a new 386 // one, provided to the producer via ProducerEndpoint::shared_memory() after 387 // OnTracingSetup(). To verify that the service accepted the SMB, the producer 388 // may check via ProducerEndpoint::IsShmemProvidedByProducer(). If the service 389 // accepted the SMB, the producer can then commit any data that is already in 390 // the SMB after the tracing session was started by the service via 391 // Producer::StartDataSource(). The |shm| will also be rejected when 392 // connecting to a service that is too old (pre Android-11). 393 // 394 // Can return null in the unlikely event that service has too many producers 395 // connected. 396 virtual std::unique_ptr<ProducerEndpoint> ConnectProducer( 397 Producer*, 398 const ClientIdentity& client_identity, 399 const std::string& name, 400 size_t shared_memory_size_hint_bytes = 0, 401 bool in_process = false, 402 ProducerSMBScrapingMode smb_scraping_mode = 403 ProducerSMBScrapingMode::kDefault, 404 size_t shared_memory_page_size_hint_bytes = 0, 405 std::unique_ptr<SharedMemory> shm = nullptr, 406 const std::string& sdk_version = {}) = 0; 407 408 // Connects a Consumer instance and obtains a ConsumerEndpoint, which is 409 // essentially a 1:1 channel between one Consumer and the Service. 410 // The caller has to guarantee that the passed Consumer will be alive as long 411 // as the returned ConsumerEndpoint is alive. 412 // To disconnect just destroy the returned ConsumerEndpoint object. It is safe 413 // to destroy the Consumer once the Consumer::OnDisconnect() has been invoked. 414 virtual std::unique_ptr<ConsumerEndpoint> ConnectConsumer(Consumer*, 415 uid_t) = 0; 416 417 // Enable/disable scraping of chunks in the shared memory buffer. If enabled, 418 // the service will copy uncommitted but non-empty chunks from the SMB when 419 // flushing (e.g. to handle unresponsive producers or producers unable to 420 // flush their active chunks), on producer disconnect (e.g. to recover data 421 // from crashed producers), and after disabling a tracing session (e.g. to 422 // gather data from producers that didn't stop their data sources in time). 423 // 424 // This feature is currently used by Chrome. 425 virtual void SetSMBScrapingEnabled(bool enabled) = 0; 426 427 using RelayClientID = std::pair<base::MachineID, /*client ID*/ uint64_t>; 428 // Connects a remote RelayClient instance and obtains a RelayEndpoint, which 429 // is a 1:1 channel between one RelayClient and the Service. To disconnect 430 // just call Disconnect() of the RelayEndpoint instance. The relay client is 431 // connected using an identifier of MachineID and client ID. The service 432 // doesn't hold an object that represents the client because the relay port 433 // only has a client-to-host SyncClock() method. 434 // 435 // TODO(chinglinyu): connect the relay client using a RelayClient* object when 436 // we need host-to-client RPC method. 437 virtual std::unique_ptr<RelayEndpoint> ConnectRelayClient(RelayClientID) = 0; 438 }; 439 440 } // namespace perfetto 441 442 #endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACING_SERVICE_H_ 443