Commit 4b8ad57a authored by Eric Seckler's avatar Eric Seckler Committed by Commit Bot

tracing: Remove ETW tracing agent

The ETW tracing agent isn't currently used widely. In light of the move
towards perfetto, we've decided to remove it until we can replace it
with a new data source (which would provide more selective information
about the OS's scheduling behavior, e.g. chrome's CPU time slices).

Developers can still export chrome's trace events into ETW for the time
being.

Bug: 900603
Change-Id: Ie482f4377359f54e166636af65a94dac69767b45
Reviewed-on: https://chromium-review.googlesource.com/c/1341989
Commit-Queue: Eric Seckler <eseckler@chromium.org>
Reviewed-by: default avataroysteine <oysteine@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612143}
parent 0c155df8
...@@ -1742,8 +1742,6 @@ jumbo_source_set("browser") { ...@@ -1742,8 +1742,6 @@ jumbo_source_set("browser") {
"tracing/background_tracing_manager_impl.h", "tracing/background_tracing_manager_impl.h",
"tracing/background_tracing_rule.cc", "tracing/background_tracing_rule.cc",
"tracing/background_tracing_rule.h", "tracing/background_tracing_rule.h",
"tracing/etw_tracing_agent_win.cc",
"tracing/etw_tracing_agent_win.h",
"tracing/file_tracing_provider_impl.cc", "tracing/file_tracing_provider_impl.cc",
"tracing/file_tracing_provider_impl.h", "tracing/file_tracing_provider_impl.h",
"tracing/trace_message_filter.cc", "tracing/trace_message_filter.cc",
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/tracing/etw_tracing_agent_win.h"
#include <stdint.h>
#include <utility>
#include "base/base64.h"
#include "base/json/json_string_value_serializer.h"
#include "base/lazy_instance.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_config.h"
#include "base/trace_event/trace_event_impl.h"
#include "base/values.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "services/service_manager/public/cpp/connector.h"
namespace content {
namespace {
EtwTracingAgent* g_etw_tracing_agent = nullptr;
const char kETWTraceLabel[] = "systemTraceEvents";
const int kEtwBufferSizeInKBytes = 16;
const int kEtwBufferFlushTimeoutInSeconds = 1;
std::string GuidToString(const GUID& guid) {
return base::StringPrintf("%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid.Data1, guid.Data2, guid.Data3, guid.Data4[0],
guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6],
guid.Data4[7]);
}
} // namespace
EtwTracingAgent::EtwTracingAgent(service_manager::Connector* connector)
: BaseAgent(connector,
kETWTraceLabel,
tracing::mojom::TraceDataType::OBJECT,
false /* supports_explicit_clock_sync */,
base::kNullProcessId),
tracing_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE})),
is_tracing_(false) {
DCHECK(!g_etw_tracing_agent);
g_etw_tracing_agent = this;
}
EtwTracingAgent::~EtwTracingAgent() {
if (is_tracing_)
StopKernelSessionTracing();
g_etw_tracing_agent = nullptr;
}
void EtwTracingAgent::StartTracing(const std::string& config,
base::TimeTicks coordinator_time,
Agent::StartTracingCallback callback) {
base::trace_event::TraceConfig trace_config(config);
// Activate kernel tracing.
if (!trace_config.IsSystraceEnabled() || !StartKernelSessionTracing()) {
std::move(callback).Run(false /* success */);
return;
}
is_tracing_ = true;
// Tracing agents, e.g. this, live as long as BrowserMainLoop lives and so
// using base::Unretained here is safe.
tracing_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&EtwTracingAgent::TraceAndConsumeOnTracingSequence,
base::Unretained(this)));
std::move(callback).Run(true /* success */);
}
void EtwTracingAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) {
DCHECK(is_tracing_);
// Deactivate kernel tracing.
if (!StopKernelSessionTracing()) {
LOG(FATAL) << "Could not stop system tracing.";
}
recorder_ = std::move(recorder);
// Stop consuming and flush events. Tracing agents, e.g. this, live as long as
// BrowserMainLoop lives and so using base::Unretained here is safe.
tracing_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&EtwTracingAgent::FlushOnTracingSequence,
base::Unretained(this)));
}
void EtwTracingAgent::OnStopSystemTracingDone(const std::string& output) {
recorder_->AddChunk(output);
recorder_.reset();
is_tracing_ = false;
}
bool EtwTracingAgent::StartKernelSessionTracing() {
// Enabled flags (tracing facilities).
uint32_t enabled_flags = EVENT_TRACE_FLAG_IMAGE_LOAD |
EVENT_TRACE_FLAG_PROCESS | EVENT_TRACE_FLAG_THREAD |
EVENT_TRACE_FLAG_CSWITCH;
EVENT_TRACE_PROPERTIES& p = *properties_.get();
p.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
p.FlushTimer = kEtwBufferFlushTimeoutInSeconds;
p.BufferSize = kEtwBufferSizeInKBytes;
p.LogFileNameOffset = 0;
p.EnableFlags = enabled_flags;
p.Wnode.ClientContext = 1; // QPC timer accuracy.
HRESULT hr = base::win::EtwTraceController::Start(
KERNEL_LOGGER_NAME, &properties_, &session_handle_);
// It's possible that a previous tracing session has been orphaned. If so
// try stopping and restarting it.
if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) {
VLOG(1) << "Session already exists, stopping and restarting it.";
hr = base::win::EtwTraceController::Stop(
KERNEL_LOGGER_NAME, &properties_);
if (FAILED(hr)) {
VLOG(1) << "EtwTraceController::Stop failed with " << hr << ".";
return false;
}
// The session was successfully shutdown so try to restart it.
hr = base::win::EtwTraceController::Start(
KERNEL_LOGGER_NAME, &properties_, &session_handle_);
}
if (FAILED(hr)) {
VLOG(1) << "EtwTraceController::Start failed with " << hr << ".";
return false;
}
return true;
}
bool EtwTracingAgent::StopKernelSessionTracing() {
HRESULT hr = base::win::EtwTraceController::Stop(
KERNEL_LOGGER_NAME, &properties_);
return SUCCEEDED(hr);
}
// static
EtwTracingAgent* EtwTracingAgent::GetInstance() {
return g_etw_tracing_agent;
}
// static
void EtwTracingAgent::ProcessEvent(EVENT_TRACE* event) {
auto* instance = EtwTracingAgent::GetInstance();
// Ignore events that are received after the browser is closed.
if (instance)
instance->AppendEventToBuffer(event);
}
void EtwTracingAgent::AddSyncEventToBuffer() {
// Sync the clocks.
base::Time walltime = base::subtle::TimeNowFromSystemTimeIgnoringOverride();
base::TimeTicks now = TRACE_TIME_TICKS_NOW();
LARGE_INTEGER walltime_in_us;
walltime_in_us.QuadPart = walltime.ToInternalValue();
LARGE_INTEGER now_in_us;
now_in_us.QuadPart = now.ToInternalValue();
// Add fields to the event.
auto value = std::make_unique<base::DictionaryValue>();
value->SetString("guid", "ClockSync");
value->SetString("walltime",
base::StringPrintf("%08lX%08lX", walltime_in_us.HighPart,
walltime_in_us.LowPart));
value->SetString("tick", base::StringPrintf("%08lX%08lX", now_in_us.HighPart,
now_in_us.LowPart));
// Append it to the events buffer.
events_->Append(std::move(value));
}
void EtwTracingAgent::AppendEventToBuffer(EVENT_TRACE* event) {
auto value = std::make_unique<base::DictionaryValue>();
// Add header fields to the event.
LARGE_INTEGER ts_us;
ts_us.QuadPart = event->Header.TimeStamp.QuadPart / 10;
value->SetString(
"ts", base::StringPrintf("%08lX%08lX", ts_us.HighPart, ts_us.LowPart));
value->SetString("guid", GuidToString(event->Header.Guid));
value->SetInteger("op", event->Header.Class.Type);
value->SetInteger("ver", event->Header.Class.Version);
value->SetInteger("pid", static_cast<int>(event->Header.ProcessId));
value->SetInteger("tid", static_cast<int>(event->Header.ThreadId));
value->SetInteger("cpu", event->BufferContext.ProcessorNumber);
// Base64 encode the payload bytes.
base::StringPiece buffer(static_cast<const char*>(event->MofData),
event->MofLength);
std::string payload;
base::Base64Encode(buffer, &payload);
value->SetString("payload", payload);
// Append it to the events buffer.
events_->Append(std::move(value));
}
void EtwTracingAgent::TraceAndConsumeOnTracingSequence() {
DCHECK(tracing_task_runner_->RunsTasksInCurrentSequence());
// Create the events buffer.
events_.reset(new base::ListValue());
// Output a clock sync event.
AddSyncEventToBuffer();
HRESULT hr = OpenRealtimeSession(KERNEL_LOGGER_NAME);
if (FAILED(hr))
return;
Consume();
Close();
}
void EtwTracingAgent::FlushOnTracingSequence() {
DCHECK(tracing_task_runner_->RunsTasksInCurrentSequence());
// Add the header information to the stream.
auto header = std::make_unique<base::DictionaryValue>();
header->SetString("name", "ETW");
// Release and pass the events buffer.
header->Set("content", std::move(events_));
// Serialize the results as a JSon string.
std::string output;
JSONStringValueSerializer serializer(&output);
serializer.Serialize(*header.get());
// TODO(chiniforooshan): Find a way to eliminate the extra string copy here.
// This is not too bad for now, since it happens only once when tracing is
// stopped.
DCHECK_EQ('{', output.front());
DCHECK_EQ('}', output.back());
output = output.substr(1, output.size() - 2);
// Tracing agents, e.g. this, live as long as BrowserMainLoop lives and so
// using base::Unretained here is safe.
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
base::Bind(&EtwTracingAgent::OnStopSystemTracingDone,
base::Unretained(this), output));
}
} // namespace content
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_TRACING_ETW_TRACING_AGENT_H_
#define CONTENT_BROWSER_TRACING_ETW_TRACING_AGENT_H_
#include <memory>
#include <string>
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/sequenced_task_runner.h"
#include "base/values.h"
#include "base/win/event_trace_consumer.h"
#include "base/win/event_trace_controller.h"
#include "services/tracing/public/cpp/base_agent.h"
#include "services/tracing/public/mojom/tracing.mojom.h"
namespace service_manager {
class Connector;
}
namespace content {
class EtwTracingAgent : public base::win::EtwTraceConsumerBase<EtwTracingAgent>,
public tracing::BaseAgent {
public:
explicit EtwTracingAgent(service_manager::Connector* connector);
// Retrieve the ETW consumer instance.
static EtwTracingAgent* GetInstance();
private:
friend std::default_delete<EtwTracingAgent>;
~EtwTracingAgent() override;
void AddSyncEventToBuffer();
void AppendEventToBuffer(EVENT_TRACE* event);
// tracing::mojom::Agent. Called by Mojo internals on the UI thread.
void StartTracing(const std::string& config,
base::TimeTicks coordinator_time,
Agent::StartTracingCallback callback) override;
void StopAndFlush(tracing::mojom::RecorderPtr recorder) override;
// Static override of EtwTraceConsumerBase::ProcessEvent.
// @param event the raw ETW event to process.
friend class base::win::EtwTraceConsumerBase<EtwTracingAgent>;
static void ProcessEvent(EVENT_TRACE* event);
// Request the ETW trace controller to activate the kernel tracing.
// returns true on success, false if the kernel tracing isn't activated.
bool StartKernelSessionTracing();
// Request the ETW trace controller to deactivate the kernel tracing.
// @param callback the callback to call with the consumed events.
// @returns true on success, false if an error occurred.
bool StopKernelSessionTracing();
void OnStopSystemTracingDone(const std::string& output);
void TraceAndConsumeOnTracingSequence();
void FlushOnTracingSequence();
// Task runner used to communicate with the native tracing interface.
scoped_refptr<base::SequencedTaskRunner> tracing_task_runner_;
std::unique_ptr<base::ListValue> events_;
TRACEHANDLE session_handle_;
base::win::EtwTraceProperties properties_;
tracing::mojom::RecorderPtr recorder_;
bool is_tracing_;
DISALLOW_COPY_AND_ASSIGN(EtwTracingAgent);
};
} // namespace content
#endif // CONTENT_BROWSER_TRACING_ETW_TRACING_AGENT_H_
...@@ -519,7 +519,7 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, DoubleStopTracing) { ...@@ -519,7 +519,7 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, DoubleStopTracing) {
run_loop.Run(); run_loop.Run();
} }
// Only CrOS, and Cast support system tracing. // Only CrOS and Cast support system tracing.
#if defined(OS_CHROMEOS) || (defined(IS_CHROMECAST) && defined(OS_LINUX)) #if defined(OS_CHROMEOS) || (defined(IS_CHROMECAST) && defined(OS_LINUX))
#define MAYBE_SystemTraceEvents SystemTraceEvents #define MAYBE_SystemTraceEvents SystemTraceEvents
#else #else
......
...@@ -50,7 +50,6 @@ ...@@ -50,7 +50,6 @@
#if defined(OS_WIN) #if defined(OS_WIN)
#include "base/win/windows_version.h" #include "base/win/windows_version.h"
#include "content/browser/tracing/etw_tracing_agent_win.h"
#endif #endif
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
...@@ -136,8 +135,6 @@ void TracingControllerImpl::AddAgents() { ...@@ -136,8 +135,6 @@ void TracingControllerImpl::AddAgents() {
agents_.push_back(std::make_unique<CrOSTracingAgent>(connector)); agents_.push_back(std::make_unique<CrOSTracingAgent>(connector));
#elif defined(CAST_TRACING_AGENT) #elif defined(CAST_TRACING_AGENT)
agents_.push_back(std::make_unique<CastTracingAgent>(connector)); agents_.push_back(std::make_unique<CastTracingAgent>(connector));
#elif defined(OS_WIN)
agents_.push_back(std::make_unique<EtwTracingAgent>(connector));
#endif #endif
auto trace_event_agent = tracing::TraceEventAgent::Create( auto trace_event_agent = tracing::TraceEventAgent::Create(
......
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