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