consumer_host.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "services/tracing/perfetto/consumer_host.h"
  5. #include <algorithm>
  6. #include <cstring>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/containers/contains.h"
  11. #include "base/containers/cxx20_erase.h"
  12. #include "base/logging.h"
  13. #include "base/strings/strcat.h"
  14. #include "base/strings/string_number_conversions.h"
  15. #include "base/strings/string_util.h"
  16. #include "base/task/thread_pool.h"
  17. #include "base/trace_event/trace_log.h"
  18. #include "base/values.h"
  19. #include "build/build_config.h"
  20. #include "mojo/public/cpp/bindings/self_owned_receiver.h"
  21. #include "mojo/public/cpp/system/wait.h"
  22. #include "services/tracing/perfetto/perfetto_service.h"
  23. #include "services/tracing/perfetto/privacy_filtering_check.h"
  24. #include "services/tracing/public/cpp/perfetto/perfetto_session.h"
  25. #include "services/tracing/public/cpp/trace_event_args_allowlist.h"
  26. #include "third_party/perfetto/include/perfetto/ext/trace_processor/export_json.h"
  27. #include "third_party/perfetto/include/perfetto/ext/tracing/core/observable_events.h"
  28. #include "third_party/perfetto/include/perfetto/ext/tracing/core/slice.h"
  29. #include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h"
  30. #include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_stats.h"
  31. #include "third_party/perfetto/include/perfetto/trace_processor/basic_types.h"
  32. #include "third_party/perfetto/include/perfetto/trace_processor/trace_processor_storage.h"
  33. #include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h"
  34. #include "third_party/perfetto/protos/perfetto/config/trace_config.pb.h"
  35. namespace tracing {
  36. namespace {
  37. const int32_t kEnableTracingTimeoutSeconds = 10;
  38. class JsonStringOutputWriter
  39. : public perfetto::trace_processor::json::OutputWriter {
  40. public:
  41. using FlushCallback =
  42. base::RepeatingCallback<void(std::string json, bool has_more)>;
  43. JsonStringOutputWriter(FlushCallback flush_callback)
  44. : flush_callback_(std::move(flush_callback)) {
  45. buffer_.reserve(kBufferReserveCapacity);
  46. }
  47. ~JsonStringOutputWriter() override {
  48. flush_callback_.Run(std::move(buffer_), false);
  49. }
  50. perfetto::trace_processor::util::Status AppendString(
  51. const std::string& string) override {
  52. buffer_ += string;
  53. if (buffer_.size() > kBufferLimitInBytes) {
  54. flush_callback_.Run(std::move(buffer_), true);
  55. // Reset the buffer_ after moving it above.
  56. buffer_.clear();
  57. buffer_.reserve(kBufferReserveCapacity);
  58. }
  59. return perfetto::trace_processor::util::OkStatus();
  60. }
  61. private:
  62. static constexpr size_t kBufferLimitInBytes = 100 * 1024;
  63. // Since we write each string before checking the limit, we'll always go
  64. // slightly over and hence we reserve some extra space to avoid most
  65. // reallocs.
  66. static constexpr size_t kBufferReserveCapacity = kBufferLimitInBytes * 5 / 4;
  67. FlushCallback flush_callback_;
  68. std::string buffer_;
  69. };
  70. } // namespace
  71. class ConsumerHost::StreamWriter {
  72. public:
  73. using Slice = std::string;
  74. static scoped_refptr<base::SequencedTaskRunner> CreateTaskRunner() {
  75. return base::ThreadPool::CreateSequencedTaskRunner(
  76. {base::WithBaseSyncPrimitives(), base::TaskPriority::BEST_EFFORT});
  77. }
  78. StreamWriter(mojo::ScopedDataPipeProducerHandle stream,
  79. TracingSession::ReadBuffersCallback callback,
  80. base::OnceClosure disconnect_callback,
  81. scoped_refptr<base::SequencedTaskRunner> callback_task_runner)
  82. : stream_(std::move(stream)),
  83. read_buffers_callback_(std::move(callback)),
  84. disconnect_callback_(std::move(disconnect_callback)),
  85. callback_task_runner_(callback_task_runner) {}
  86. void WriteToStream(std::unique_ptr<Slice> slice, bool has_more) {
  87. DCHECK(stream_.is_valid());
  88. uint32_t write_position = 0;
  89. while (write_position < slice->size()) {
  90. uint32_t write_bytes = slice->size() - write_position;
  91. MojoResult result =
  92. stream_->WriteData(slice->data() + write_position, &write_bytes,
  93. MOJO_WRITE_DATA_FLAG_NONE);
  94. if (result == MOJO_RESULT_OK) {
  95. write_position += write_bytes;
  96. continue;
  97. }
  98. if (result == MOJO_RESULT_SHOULD_WAIT) {
  99. result = mojo::Wait(stream_.get(), MOJO_HANDLE_SIGNAL_WRITABLE);
  100. }
  101. if (result != MOJO_RESULT_OK) {
  102. if (!disconnect_callback_.is_null()) {
  103. callback_task_runner_->PostTask(FROM_HERE,
  104. std::move(disconnect_callback_));
  105. }
  106. return;
  107. }
  108. }
  109. if (!has_more && !read_buffers_callback_.is_null()) {
  110. callback_task_runner_->PostTask(FROM_HERE,
  111. std::move(read_buffers_callback_));
  112. }
  113. }
  114. StreamWriter(const StreamWriter&) = delete;
  115. StreamWriter& operator=(const StreamWriter&) = delete;
  116. private:
  117. mojo::ScopedDataPipeProducerHandle stream_;
  118. TracingSession::ReadBuffersCallback read_buffers_callback_;
  119. base::OnceClosure disconnect_callback_;
  120. scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
  121. };
  122. ConsumerHost::TracingSession::TracingSession(
  123. ConsumerHost* host,
  124. mojo::PendingReceiver<mojom::TracingSessionHost> tracing_session_host,
  125. mojo::PendingRemote<mojom::TracingSessionClient> tracing_session_client,
  126. const perfetto::TraceConfig& trace_config,
  127. perfetto::base::ScopedFile output_file,
  128. mojom::TracingClientPriority priority)
  129. : host_(host),
  130. tracing_session_client_(std::move(tracing_session_client)),
  131. receiver_(this, std::move(tracing_session_host)),
  132. tracing_priority_(priority) {
  133. host_->service()->RegisterTracingSession(this);
  134. tracing_session_client_.set_disconnect_handler(base::BindOnce(
  135. &ConsumerHost::DestructTracingSession, base::Unretained(host)));
  136. receiver_.set_disconnect_handler(base::BindOnce(
  137. &ConsumerHost::DestructTracingSession, base::Unretained(host)));
  138. privacy_filtering_enabled_ = false;
  139. for (const auto& data_source : trace_config.data_sources()) {
  140. if (data_source.config().chrome_config().privacy_filtering_enabled()) {
  141. privacy_filtering_enabled_ = true;
  142. }
  143. if (data_source.config().chrome_config().convert_to_legacy_json()) {
  144. convert_to_legacy_json_ = true;
  145. }
  146. }
  147. #if DCHECK_IS_ON()
  148. if (privacy_filtering_enabled_) {
  149. // If enabled, filtering must be enabled for all data sources.
  150. for (const auto& data_source : trace_config.data_sources()) {
  151. DCHECK(data_source.config().chrome_config().privacy_filtering_enabled());
  152. }
  153. }
  154. #endif
  155. filtered_pids_.clear();
  156. for (const auto& ds_config : trace_config.data_sources()) {
  157. if (ds_config.config().name() == mojom::kTraceEventDataSourceName) {
  158. for (const auto& filter : ds_config.producer_name_filter()) {
  159. base::ProcessId pid;
  160. if (PerfettoService::ParsePidFromProducerName(filter, &pid)) {
  161. filtered_pids_.insert(pid);
  162. }
  163. }
  164. break;
  165. }
  166. }
  167. pending_enable_tracing_ack_pids_ = host_->service()->active_service_pids();
  168. base::EraseIf(*pending_enable_tracing_ack_pids_,
  169. [this](base::ProcessId pid) { return !IsExpectedPid(pid); });
  170. perfetto::TraceConfig effective_config(trace_config);
  171. // If we're going to convert the data to JSON, don't enable privacy filtering
  172. // at the data source level since it will be performed at conversion time
  173. // (otherwise there's nothing to pass through the allowlist).
  174. if (convert_to_legacy_json_ && privacy_filtering_enabled_) {
  175. for (auto& data_source : *effective_config.mutable_data_sources()) {
  176. auto* chrome_config =
  177. data_source.mutable_config()->mutable_chrome_config();
  178. chrome_config->set_privacy_filtering_enabled(false);
  179. // Argument filtering should still be enabled together with privacy
  180. // filtering to ensure, for example, that only the expected metadata gets
  181. // written.
  182. base::trace_event::TraceConfig base_config(chrome_config->trace_config());
  183. base_config.EnableArgumentFilter();
  184. chrome_config->set_trace_config(base_config.ToString());
  185. }
  186. }
  187. host_->consumer_endpoint()->EnableTracing(effective_config,
  188. std::move(output_file));
  189. MaybeSendEnableTracingAck();
  190. if (pending_enable_tracing_ack_pids_) {
  191. // We can't know for sure whether all processes we request to connect to the
  192. // tracing service will connect back, or if all the connected services will
  193. // ACK our EnableTracing request eventually, so we'll add a timeout for that
  194. // case.
  195. enable_tracing_ack_timer_.Start(
  196. FROM_HERE, base::Seconds(kEnableTracingTimeoutSeconds), this,
  197. &ConsumerHost::TracingSession::OnEnableTracingTimeout);
  198. }
  199. }
  200. ConsumerHost::TracingSession::~TracingSession() {
  201. host_->service()->UnregisterTracingSession(this);
  202. if (host_->consumer_endpoint()) {
  203. host_->consumer_endpoint()->FreeBuffers();
  204. }
  205. }
  206. void ConsumerHost::TracingSession::OnPerfettoEvents(
  207. const perfetto::ObservableEvents& events) {
  208. if (!pending_enable_tracing_ack_pids_ ||
  209. !events.instance_state_changes_size()) {
  210. return;
  211. }
  212. for (const auto& state_change : events.instance_state_changes()) {
  213. DataSourceHandle handle(state_change.producer_name(),
  214. state_change.data_source_name());
  215. data_source_states_[handle] =
  216. state_change.state() ==
  217. perfetto::ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED;
  218. }
  219. // Data sources are first reported as being stopped before starting, so once
  220. // all the data sources we know about have started we can declare tracing
  221. // begun.
  222. bool all_data_sources_started = std::all_of(
  223. data_source_states_.cbegin(), data_source_states_.cend(),
  224. [](std::pair<DataSourceHandle, bool> state) { return state.second; });
  225. if (!all_data_sources_started)
  226. return;
  227. for (const auto& it : data_source_states_) {
  228. // Attempt to parse the PID out of the producer name.
  229. base::ProcessId pid;
  230. if (!PerfettoService::ParsePidFromProducerName(it.first.producer_name(),
  231. &pid)) {
  232. continue;
  233. }
  234. pending_enable_tracing_ack_pids_->erase(pid);
  235. }
  236. MaybeSendEnableTracingAck();
  237. }
  238. void ConsumerHost::TracingSession::OnActiveServicePidAdded(
  239. base::ProcessId pid) {
  240. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  241. if (pending_enable_tracing_ack_pids_ && IsExpectedPid(pid)) {
  242. pending_enable_tracing_ack_pids_->insert(pid);
  243. }
  244. }
  245. void ConsumerHost::TracingSession::OnActiveServicePidRemoved(
  246. base::ProcessId pid) {
  247. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  248. if (pending_enable_tracing_ack_pids_) {
  249. pending_enable_tracing_ack_pids_->erase(pid);
  250. MaybeSendEnableTracingAck();
  251. }
  252. }
  253. void ConsumerHost::TracingSession::OnActiveServicePidsInitialized() {
  254. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  255. MaybeSendEnableTracingAck();
  256. }
  257. void ConsumerHost::TracingSession::RequestDisableTracing(
  258. base::OnceClosure on_disabled_callback) {
  259. DCHECK(!on_disabled_callback_);
  260. on_disabled_callback_ = std::move(on_disabled_callback);
  261. DisableTracing();
  262. }
  263. void ConsumerHost::TracingSession::OnEnableTracingTimeout() {
  264. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  265. if (!pending_enable_tracing_ack_pids_) {
  266. return;
  267. }
  268. std::stringstream error;
  269. error << "Timed out waiting for processes to ack BeginTracing: ";
  270. for (auto pid : *pending_enable_tracing_ack_pids_) {
  271. error << pid << " ";
  272. }
  273. LOG(ERROR) << error.rdbuf();
  274. DCHECK(tracing_session_client_);
  275. tracing_session_client_->OnTracingEnabled();
  276. pending_enable_tracing_ack_pids_.reset();
  277. }
  278. void ConsumerHost::TracingSession::MaybeSendEnableTracingAck() {
  279. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  280. if (!pending_enable_tracing_ack_pids_ ||
  281. !pending_enable_tracing_ack_pids_->empty() ||
  282. !host_->service()->active_service_pids_initialized()) {
  283. return;
  284. }
  285. DCHECK(tracing_session_client_);
  286. tracing_session_client_->OnTracingEnabled();
  287. pending_enable_tracing_ack_pids_.reset();
  288. enable_tracing_ack_timer_.Stop();
  289. }
  290. bool ConsumerHost::TracingSession::IsExpectedPid(base::ProcessId pid) const {
  291. return filtered_pids_.empty() || base::Contains(filtered_pids_, pid);
  292. }
  293. void ConsumerHost::TracingSession::ChangeTraceConfig(
  294. const perfetto::TraceConfig& trace_config) {
  295. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  296. host_->consumer_endpoint()->ChangeTraceConfig(trace_config);
  297. }
  298. void ConsumerHost::TracingSession::DisableTracing() {
  299. host_->consumer_endpoint()->DisableTracing();
  300. }
  301. void ConsumerHost::TracingSession::OnTracingDisabled(const std::string& error) {
  302. DCHECK(tracing_session_client_);
  303. if (enable_tracing_ack_timer_.IsRunning()) {
  304. enable_tracing_ack_timer_.FireNow();
  305. }
  306. DCHECK(!pending_enable_tracing_ack_pids_);
  307. tracing_session_client_->OnTracingDisabled(
  308. /*tracing_succeeded=*/error.empty());
  309. if (trace_processor_) {
  310. host_->consumer_endpoint()->ReadBuffers();
  311. }
  312. tracing_enabled_ = false;
  313. if (on_disabled_callback_) {
  314. std::move(on_disabled_callback_).Run();
  315. }
  316. }
  317. void ConsumerHost::TracingSession::OnConsumerClientDisconnected() {
  318. // The TracingSession will be deleted after this point.
  319. host_->DestructTracingSession();
  320. }
  321. void ConsumerHost::TracingSession::ReadBuffers(
  322. mojo::ScopedDataPipeProducerHandle stream,
  323. ReadBuffersCallback callback) {
  324. DCHECK(!convert_to_legacy_json_);
  325. read_buffers_stream_writer_ = base::SequenceBound<StreamWriter>(
  326. StreamWriter::CreateTaskRunner(), std::move(stream), std::move(callback),
  327. base::BindOnce(&TracingSession::OnConsumerClientDisconnected,
  328. weak_factory_.GetWeakPtr()),
  329. base::SequencedTaskRunnerHandle::Get());
  330. host_->consumer_endpoint()->ReadBuffers();
  331. }
  332. void ConsumerHost::TracingSession::RequestBufferUsage(
  333. RequestBufferUsageCallback callback) {
  334. if (!request_buffer_usage_callback_.is_null()) {
  335. std::move(callback).Run(false, 0, false);
  336. return;
  337. }
  338. request_buffer_usage_callback_ = std::move(callback);
  339. host_->consumer_endpoint()->GetTraceStats();
  340. }
  341. void ConsumerHost::TracingSession::DisableTracingAndEmitJson(
  342. const std::string& agent_label_filter,
  343. mojo::ScopedDataPipeProducerHandle stream,
  344. bool privacy_filtering_enabled,
  345. DisableTracingAndEmitJsonCallback callback) {
  346. DCHECK(!read_buffers_stream_writer_);
  347. read_buffers_stream_writer_ = base::SequenceBound<StreamWriter>(
  348. StreamWriter::CreateTaskRunner(), std::move(stream), std::move(callback),
  349. base::BindOnce(&TracingSession::OnConsumerClientDisconnected,
  350. weak_factory_.GetWeakPtr()),
  351. base::SequencedTaskRunnerHandle::Get());
  352. if (privacy_filtering_enabled) {
  353. // For filtering/allowlisting to be possible at JSON export time,
  354. // filtering must not have been enabled during proto emission time
  355. // (or there's nothing to pass through the allowlist).
  356. DCHECK(!privacy_filtering_enabled_ || convert_to_legacy_json_);
  357. privacy_filtering_enabled_ = true;
  358. }
  359. json_agent_label_filter_ = agent_label_filter;
  360. perfetto::trace_processor::Config processor_config;
  361. trace_processor_ =
  362. perfetto::trace_processor::TraceProcessorStorage::CreateInstance(
  363. processor_config);
  364. if (tracing_enabled_) {
  365. DisableTracing();
  366. } else {
  367. host_->consumer_endpoint()->ReadBuffers();
  368. }
  369. }
  370. void ConsumerHost::TracingSession::ExportJson() {
  371. // In legacy backend, the trace event agent sets the predicate used by
  372. // TraceLog. For perfetto backend, ensure that predicate is always set
  373. // before creating the exporter. The agent can be created later than this
  374. // point.
  375. if (base::trace_event::TraceLog::GetInstance()
  376. ->GetArgumentFilterPredicate()
  377. .is_null()) {
  378. base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate(
  379. base::BindRepeating(&IsTraceEventArgsAllowlisted));
  380. base::trace_event::TraceLog::GetInstance()->SetMetadataFilterPredicate(
  381. base::BindRepeating(&IsMetadataAllowlisted));
  382. }
  383. perfetto::trace_processor::json::ArgumentFilterPredicate argument_filter;
  384. perfetto::trace_processor::json::MetadataFilterPredicate metadata_filter;
  385. perfetto::trace_processor::json::LabelFilterPredicate label_filter;
  386. if (privacy_filtering_enabled_) {
  387. auto* trace_log = base::trace_event::TraceLog::GetInstance();
  388. base::trace_event::ArgumentFilterPredicate argument_filter_predicate =
  389. trace_log->GetArgumentFilterPredicate();
  390. argument_filter =
  391. [argument_filter_predicate](
  392. const char* category_group_name, const char* event_name,
  393. perfetto::trace_processor::json::ArgumentNameFilterPredicate*
  394. name_filter) {
  395. base::trace_event::ArgumentNameFilterPredicate name_filter_predicate;
  396. bool result = argument_filter_predicate.Run(
  397. category_group_name, event_name, &name_filter_predicate);
  398. if (name_filter_predicate) {
  399. *name_filter = [name_filter_predicate](const char* arg_name) {
  400. return name_filter_predicate.Run(arg_name);
  401. };
  402. }
  403. return result;
  404. };
  405. base::trace_event::MetadataFilterPredicate metadata_filter_predicate =
  406. trace_log->GetMetadataFilterPredicate();
  407. metadata_filter = [metadata_filter_predicate](const char* metadata_name) {
  408. return metadata_filter_predicate.Run(metadata_name);
  409. };
  410. }
  411. if (!json_agent_label_filter_.empty()) {
  412. label_filter = [this](const char* label) {
  413. return strcmp(label, json_agent_label_filter_.c_str()) == 0;
  414. };
  415. }
  416. JsonStringOutputWriter output_writer(base::BindRepeating(
  417. &ConsumerHost::TracingSession::OnJSONTraceData, base::Unretained(this)));
  418. auto status = perfetto::trace_processor::json::ExportJson(
  419. trace_processor_.get(), &output_writer, argument_filter, metadata_filter,
  420. label_filter);
  421. DCHECK(status.ok()) << status.message();
  422. }
  423. void ConsumerHost::TracingSession::OnJSONTraceData(std::string json,
  424. bool has_more) {
  425. auto slice = std::make_unique<StreamWriter::Slice>();
  426. slice->swap(json);
  427. read_buffers_stream_writer_.AsyncCall(&StreamWriter::WriteToStream)
  428. .WithArgs(std::move(slice), has_more);
  429. if (!has_more) {
  430. read_buffers_stream_writer_.Reset();
  431. }
  432. }
  433. void ConsumerHost::TracingSession::OnTraceData(
  434. std::vector<perfetto::TracePacket> packets,
  435. bool has_more) {
  436. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  437. // Calculate space needed for trace chunk. Each packet has a preamble and
  438. // payload size.
  439. size_t max_size = packets.size() * perfetto::TracePacket::kMaxPreambleBytes;
  440. for (const auto& packet : packets) {
  441. max_size += packet.size();
  442. }
  443. // If |trace_processor_| was initialized, then export trace as JSON.
  444. if (trace_processor_) {
  445. // Copy packets into a trace file chunk.
  446. size_t position = 0;
  447. std::unique_ptr<uint8_t[]> data(new uint8_t[max_size]);
  448. for (perfetto::TracePacket& packet : packets) {
  449. auto [preamble, preamble_size] = packet.GetProtoPreamble();
  450. DCHECK_LT(position + preamble_size, max_size);
  451. memcpy(&data[position], preamble, preamble_size);
  452. position += preamble_size;
  453. for (const perfetto::Slice& slice : packet.slices()) {
  454. DCHECK_LT(position + slice.size, max_size);
  455. memcpy(&data[position], slice.start, slice.size);
  456. position += slice.size;
  457. }
  458. }
  459. auto status = trace_processor_->Parse(std::move(data), position);
  460. // TODO(eseckler): There's no way to propagate this error at the moment - If
  461. // one occurs on production builds, we silently ignore it and will end up
  462. // producing an empty JSON result.
  463. DCHECK(status.ok()) << status.message();
  464. if (!has_more) {
  465. trace_processor_->NotifyEndOfFile();
  466. ExportJson();
  467. trace_processor_.reset();
  468. }
  469. return;
  470. }
  471. // Copy packets into a trace slice.
  472. auto chunk = std::make_unique<StreamWriter::Slice>();
  473. chunk->reserve(max_size);
  474. for (auto& packet : packets) {
  475. auto [data, size] = packet.GetProtoPreamble();
  476. chunk->append(data, size);
  477. auto& slices = packet.slices();
  478. for (auto& slice : slices) {
  479. chunk->append(static_cast<const char*>(slice.start), slice.size);
  480. }
  481. }
  482. if (privacy_filtering_enabled_) {
  483. tracing::PrivacyFilteringCheck::RemoveBlockedFields(*chunk);
  484. }
  485. read_buffers_stream_writer_.AsyncCall(&StreamWriter::WriteToStream)
  486. .WithArgs(std::move(chunk), has_more);
  487. if (!has_more) {
  488. read_buffers_stream_writer_.Reset();
  489. }
  490. }
  491. void ConsumerHost::TracingSession::OnTraceStats(
  492. bool success,
  493. const perfetto::TraceStats& stats) {
  494. if (!request_buffer_usage_callback_) {
  495. return;
  496. }
  497. if (!(success && stats.buffer_stats_size())) {
  498. std::move(request_buffer_usage_callback_).Run(false, 0.0f, false);
  499. return;
  500. }
  501. double percent_full = GetTraceBufferUsage(stats);
  502. bool data_loss = HasLostData(stats);
  503. std::move(request_buffer_usage_callback_).Run(true, percent_full, data_loss);
  504. }
  505. void ConsumerHost::TracingSession::Flush(
  506. uint32_t timeout,
  507. base::OnceCallback<void(bool)> callback) {
  508. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  509. flush_callback_ = std::move(callback);
  510. base::WeakPtr<TracingSession> weak_this = weak_factory_.GetWeakPtr();
  511. host_->consumer_endpoint()->Flush(timeout, [weak_this](bool success) {
  512. if (!weak_this) {
  513. return;
  514. }
  515. if (weak_this->flush_callback_) {
  516. std::move(weak_this->flush_callback_).Run(success);
  517. }
  518. });
  519. }
  520. // static
  521. void ConsumerHost::BindConsumerReceiver(
  522. PerfettoService* service,
  523. mojo::PendingReceiver<mojom::ConsumerHost> receiver) {
  524. mojo::MakeSelfOwnedReceiver(std::make_unique<ConsumerHost>(service),
  525. std::move(receiver));
  526. }
  527. ConsumerHost::ConsumerHost(PerfettoService* service) : service_(service) {
  528. DETACH_FROM_SEQUENCE(sequence_checker_);
  529. consumer_endpoint_ =
  530. service_->GetService()->ConnectConsumer(this, 0 /*uid_t*/);
  531. consumer_endpoint_->ObserveEvents(
  532. perfetto::ObservableEvents::TYPE_DATA_SOURCES_INSTANCES);
  533. }
  534. ConsumerHost::~ConsumerHost() {
  535. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  536. // Make sure the tracing_session is destroyed first, as it keeps a pointer to
  537. // the ConsumerHost parent and accesses it on destruction.
  538. tracing_session_.reset();
  539. }
  540. void ConsumerHost::EnableTracing(
  541. mojo::PendingReceiver<mojom::TracingSessionHost> tracing_session_host,
  542. mojo::PendingRemote<mojom::TracingSessionClient> tracing_session_client,
  543. const perfetto::TraceConfig& trace_config,
  544. base::File output_file) {
  545. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  546. DCHECK(!tracing_session_);
  547. auto priority = mojom::TracingClientPriority::kUnknown;
  548. for (const auto& data_source : trace_config.data_sources()) {
  549. if (!data_source.has_config() ||
  550. !data_source.config().has_chrome_config()) {
  551. continue;
  552. }
  553. switch (data_source.config().chrome_config().client_priority()) {
  554. case perfetto::protos::gen::ChromeConfig::BACKGROUND:
  555. priority =
  556. std::max(priority, mojom::TracingClientPriority::kBackground);
  557. break;
  558. case perfetto::protos::gen::ChromeConfig::USER_INITIATED:
  559. priority =
  560. std::max(priority, mojom::TracingClientPriority::kUserInitiated);
  561. break;
  562. default:
  563. case perfetto::protos::gen::ChromeConfig::UNKNOWN:
  564. break;
  565. }
  566. }
  567. #if BUILDFLAG(IS_WIN)
  568. // TODO(crbug.com/1158482): Support writing to a file directly on Windows.
  569. DCHECK(!output_file.IsValid())
  570. << "Tracing directly to a file isn't supported yet on Windows";
  571. perfetto::base::ScopedFile file;
  572. #else
  573. perfetto::base::ScopedFile file(output_file.TakePlatformFile());
  574. #endif
  575. // We create our new TracingSession async, if the PerfettoService allows
  576. // us to, after it's stopped any currently running lower or equal priority
  577. // tracing sessions.
  578. service_->RequestTracingSession(
  579. priority, base::BindOnce(
  580. [](base::WeakPtr<ConsumerHost> weak_this,
  581. mojo::PendingReceiver<mojom::TracingSessionHost>
  582. tracing_session_host,
  583. mojo::PendingRemote<mojom::TracingSessionClient>
  584. tracing_session_client,
  585. const perfetto::TraceConfig& trace_config,
  586. perfetto::base::ScopedFile output_file,
  587. mojom::TracingClientPriority priority) {
  588. if (!weak_this) {
  589. return;
  590. }
  591. weak_this->tracing_session_ =
  592. std::make_unique<TracingSession>(
  593. weak_this.get(), std::move(tracing_session_host),
  594. std::move(tracing_session_client), trace_config,
  595. std::move(output_file), priority);
  596. },
  597. weak_factory_.GetWeakPtr(), std::move(tracing_session_host),
  598. std::move(tracing_session_client), trace_config,
  599. std::move(file), priority));
  600. }
  601. void ConsumerHost::OnConnect() {}
  602. void ConsumerHost::OnDisconnect() {}
  603. void ConsumerHost::OnTracingDisabled(const std::string& error) {
  604. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  605. if (tracing_session_) {
  606. tracing_session_->OnTracingDisabled(error);
  607. }
  608. }
  609. void ConsumerHost::OnTraceData(std::vector<perfetto::TracePacket> packets,
  610. bool has_more) {
  611. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  612. if (tracing_session_) {
  613. tracing_session_->OnTraceData(std::move(packets), has_more);
  614. }
  615. }
  616. void ConsumerHost::OnObservableEvents(
  617. const perfetto::ObservableEvents& events) {
  618. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  619. if (tracing_session_) {
  620. tracing_session_->OnPerfettoEvents(events);
  621. }
  622. }
  623. void ConsumerHost::OnTraceStats(bool success,
  624. const perfetto::TraceStats& stats) {
  625. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  626. if (tracing_session_) {
  627. tracing_session_->OnTraceStats(success, stats);
  628. }
  629. }
  630. void ConsumerHost::DestructTracingSession() {
  631. tracing_session_.reset();
  632. }
  633. } // namespace tracing