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