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