blob: 83f3749f7b180bf13bb750cbf405a1e3f71da31f [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/win/etw_trace_controller.h"
#include <stdint.h>
#include <memory>
#include "base/check_op.h"
#include "base/logging.h"
#include "base/sequence_checker.h"
#include "remoting/base/logging.h"
namespace remoting {
namespace {
constexpr wchar_t kSessionName[] = L"chrome_remote_desktop_host_logger";
constexpr uint8_t kDefaultTracingLevel = 4;
constexpr uint32_t kDefaultTracingFlags = 0;
constexpr size_t kDefaultBufferSizeKb = 16;
} // namespace
EtwTraceController* EtwTraceController::instance_ = nullptr;
EtwTraceController::EtwTraceController() = default;
EtwTraceController::~EtwTraceController() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Stop();
}
const wchar_t* EtwTraceController::GetActiveSessionName() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return (instance_ == this) ? kSessionName : nullptr;
}
bool EtwTraceController::Start() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(instance_, nullptr);
instance_ = this;
// The shared Chromium event tracing class registers itself as a 'classic'
// provider which only supports one session so stop any existing sessions now.
// More info on ETW provider registration:
// https://docs.microsoft.com/en-us/windows/win32/etw/about-event-tracing#mof-classic-providers
base::win::EtwTraceProperties ignore;
HRESULT hr = base::win::EtwTraceController::Stop(kSessionName, &ignore);
LOG_IF(ERROR,
FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_WMI_INSTANCE_NOT_FOUND))
<< "Failed to stop previous trace session: 0x" << std::hex << hr;
hr = controller_.StartRealtimeSession(kSessionName, kDefaultBufferSizeKb);
if (FAILED(hr)) {
LOG(ERROR) << "Failed to start ETW realtime session: 0x" << std::hex << hr;
return false;
}
hr = controller_.EnableProvider(kRemotingHostLogProviderGuid,
kDefaultTracingLevel, kDefaultTracingFlags);
if (FAILED(hr)) {
LOG(ERROR) << "Failed to configure ETW provider: 0x" << std::hex << hr;
controller_.Stop(nullptr);
return false;
}
return true;
}
void EtwTraceController::Stop() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (instance_ != this) {
DCHECK_EQ(instance_, nullptr);
return;
}
// The following are all best effort, so try to stop tracing and clean up but
// don't skip any steps if a previous one failed.
HRESULT hr = controller_.DisableProvider(kRemotingHostLogProviderGuid);
LOG_IF(ERROR, FAILED(hr))
<< "Failed to disable ETW provider: 0x" << std::hex << hr;
hr = controller_.Flush(nullptr);
LOG_IF(ERROR, FAILED(hr)) << "Failed to flush events: 0x" << std::hex << hr;
hr = controller_.Stop(nullptr);
LOG_IF(ERROR, FAILED(hr))
<< "Failed to stop ETW trace session: 0x" << std::hex << hr;
instance_ = nullptr;
}
} // namespace remoting