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