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