Commit 62404558 authored by Eric Seckler's avatar Eric Seckler Committed by Commit Bot

tracing: Port ARC tracing agent to perfetto

Adds a new DataSource for the ARC++ system tracing agent.
Each ArcTracingBridge registers with the data source and keeps track of
its state, so that the data source can coordinate tracing between all
the bridges.

TBR=oysteine@google.com

Test: Manually capture a trace with and without perfetto backend.
Bug: 900603
Change-Id: Ieb29bcb65de9f4802965a30844e9f76af55db1f3
Reviewed-on: https://chromium-review.googlesource.com/c/1360736Reviewed-by: default avatarEric Seckler <eseckler@chromium.org>
Reviewed-by: default avatarYusuke Sato <yusukes@chromium.org>
Reviewed-by: default avataroysteine <oysteine@chromium.org>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Commit-Queue: Eric Seckler <eseckler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#615483}
parent 3a584d80
include_rules = [
"+third_party/perfetto/include",
"+third_party/perfetto/protos",
]
......@@ -19,6 +19,7 @@
#include "components/arc/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "services/tracing/public/cpp/base_agent.h"
#include "services/tracing/public/cpp/perfetto/producer_client.h"
#include "services/tracing/public/mojom/tracing.mojom.h"
namespace content {
......@@ -31,7 +32,6 @@ class ArcBridgeService;
// This class provides the interface to trigger tracing in the container.
class ArcTracingBridge : public KeyedService,
public tracing::BaseAgent,
public ConnectionObserver<mojom::TracingInstance> {
public:
// Returns singleton instance for the given BrowserContext,
......@@ -46,64 +46,92 @@ class ArcTracingBridge : public KeyedService,
// ConnectionObserver<mojom::TracingInstance> overrides:
void OnConnectionReady() override;
// State of the tracing activity of the bridge.
enum class State { kDisabled, kStarting, kEnabled, kStopping };
State state() const { return state_; }
using SuccessCallback = base::OnceCallback<void(bool)>;
using TraceDataCallback = base::OnceCallback<void(const std::string& data)>;
// Starts tracing and calls |callback| when started indicating whether tracing
// was started successfully via its parameter.
void StartTracing(const std::string& config, SuccessCallback callback);
// Stops tracing and calls |callback| with the recorded trace data once
// stopped. If unsuccessful, calls |callback| with an empty data string.
void StopAndFlush(TraceDataCallback callback);
private:
// TODO(crbug.com/839086): Remove once we have replaced the legacy tracing
// service with perfetto.
class ArcTracingAgent : public tracing::BaseAgent {
public:
explicit ArcTracingAgent(ArcTracingBridge* bridge);
~ArcTracingAgent() override;
private:
// tracing::mojom::Agent.
void StartTracing(const std::string& config,
base::TimeTicks coordinator_time,
Agent::StartTracingCallback callback) override;
void StopAndFlush(tracing::mojom::RecorderPtr recorder) override;
void OnTraceData(const std::string& data);
ArcTracingBridge* const bridge_;
tracing::mojom::RecorderPtr recorder_;
DISALLOW_COPY_AND_ASSIGN(ArcTracingAgent);
};
// A helper class for reading trace data from the client side. We separate
// this from |ArcTracingAgentImpl| to isolate the logic that runs on browser's
// IO thread. All the functions in this class except for constructor,
// destructor, and |GetWeakPtr| are expected to be run on browser's IO thread.
// IO thread. All the functions in this class except for constructor are
// expected to be run on browser's IO thread.
class ArcTracingReader {
public:
ArcTracingReader();
~ArcTracingReader();
// Starts reading trace data from the given file descriptor.
void StartTracing(base::ScopedFD read_fd);
void OnTraceDataAvailable();
void StopTracing(base::OnceCallback<void(const std::string&)> callback);
base::WeakPtr<ArcTracingReader> GetWeakPtr();
// Stops reading and returns the collected trace data.
std::string StopTracing();
private:
void OnTraceDataAvailable();
// Number of events for the ring buffer.
static constexpr size_t kTraceEventBufferSize = 64000;
base::ScopedFD read_fd_;
std::unique_ptr<base::FileDescriptorWatcher::Controller> fd_watcher_;
base::RingBuffer<std::string, kTraceEventBufferSize> ring_buffer_;
// NOTE: Weak pointers must be invalidated before all other member variables
// so it must be the last member.
base::WeakPtrFactory<ArcTracingReader> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ArcTracingReader);
};
struct Category;
// tracing::mojom::Agent.
void StartTracing(const std::string& config,
base::TimeTicks coordinator_time,
Agent::StartTracingCallback callback) override;
void StopAndFlush(tracing::mojom::RecorderPtr recorder) override;
// Callback for QueryAvailableCategories.
void OnCategoriesReady(const std::vector<std::string>& categories);
void OnArcTracingStopped(bool success);
void OnTracingReaderStopped(const std::string& data);
void OnArcTracingStarted(SuccessCallback callback, bool success);
void OnArcTracingStopped(TraceDataCallback tracing_stopped_callback,
bool success);
void OnTracingReaderStopped(TraceDataCallback tracing_stopped_callback,
const std::string& data);
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
// List of available categories.
std::vector<Category> categories_;
// We use |reader_.GetWeakPtr()| when binding callbacks with its functions.
// Notes that the weak pointer returned by it can only be deferenced or
// invalided in the same task runner to avoid racing condition. The
// destruction of |reader_| is also a source of invalidation. However, we're
// lucky as we're using |ArcTracingAgentImpl| as a singleton, the
// destruction is always performed after all MessageLoops are destroyed, and
// thus there are no race conditions in such situation.
ArcTracingReader reader_;
bool is_stopping_ = false;
tracing::mojom::RecorderPtr recorder_;
ArcTracingAgent agent_;
std::unique_ptr<ArcTracingReader> reader_;
State state_ = State::kDisabled;
// NOTE: Weak pointers must be invalidated before all other member variables
// so it must be the last member.
......
......@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/chromecast_build.gni")
import("//services/service_manager/public/service_manifest.gni")
# There should be only one tracing service. It is currently
......@@ -45,6 +46,10 @@ source_set("lib") {
public_deps += [ "//third_party/perfetto:libperfetto" ]
}
if (is_chromecast) {
defines = [ "IS_CHROMECAST" ]
}
}
service_manifest("manifest") {
......@@ -103,4 +108,8 @@ source_set("tests") {
"//third_party/perfetto/protos/perfetto/trace/chrome:lite",
]
}
if (is_chromecast) {
defines = [ "IS_CHROMECAST" ]
}
}
......@@ -14,6 +14,7 @@
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "services/tracing/public/mojom/perfetto_service.mojom.h"
#include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h"
#include "third_party/perfetto/include/perfetto/tracing/core/trace_packet.h"
......@@ -296,11 +297,22 @@ JSONTraceExporter::JSONTraceExporter(const std::string& config,
auto* chrome_config = trace_event_config->mutable_chrome_config();
chrome_config->set_trace_config(config_);
// Only CrOS and Cast support system tracing.
#if defined(OS_CHROMEOS) || (defined(IS_CHROMECAST) && defined(OS_LINUX))
auto* system_trace_config = trace_config.add_data_sources()->mutable_config();
system_trace_config->set_name(mojom::kSystemTraceDataSourceName);
system_trace_config->set_target_buffer(0);
auto* system_chrome_config = system_trace_config->mutable_chrome_config();
system_chrome_config->set_trace_config(config_);
#endif
#if defined(OS_CHROMEOS)
auto* arc_trace_config = trace_config.add_data_sources()->mutable_config();
arc_trace_config->set_name(mojom::kArcTraceDataSourceName);
arc_trace_config->set_target_buffer(0);
auto* arc_chrome_config = arc_trace_config->mutable_chrome_config();
arc_chrome_config->set_trace_config(config_);
#endif
auto* trace_metadata_config =
trace_config.add_data_sources()->mutable_config();
......
......@@ -7,6 +7,7 @@ module tracing.mojom;
const string kTraceEventDataSourceName = "org.chromium.trace_event";
const string kMetaDataSourceName = "org.chromium.trace_metadata";
const string kSystemTraceDataSourceName = "org.chromium.trace_system";
const string kArcTraceDataSourceName = "org.chromium.trace_arc";
// Brief description of the flow: There's a per-process ProducerClient which
// connects to the central PerfettoService and establishes a two-way connection
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment