Commit 7a88939a authored by Joe Downing's avatar Joe Downing Committed by Commit Bot

[Windows][Host][Logging] Adding EtwTraceController class

This is the first CL needed to allow the Windows host to log w/o
logman or sawbuck.  Each process on Windows create an ETW trace
provider with a well-known GUID, this is what logman/sawbuck use
to capture a trace.

With this feature, we will update the Windows host so that its log
output can be redirected (likely to the Windows event log, could
also be a human readable file or ETW file).

In this CL, I am adding the class which is used to enable/disable
ETW tracing.  Future CLs will add the ETW consumer which listens
for the events and the logic needed to parse and redirect the
output to a new location.

Bug: 1144185
Change-Id: I01affb28c01d01bde8649faffaf59a17c8a9cd67
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2509948Reviewed-by: default avatarJamie Walch <jamiewalch@chromium.org>
Commit-Queue: Joe Downing <joedow@google.com>
Cr-Commit-Position: refs/heads/master@{#822868}
parent d8bd8f38
...@@ -6,9 +6,23 @@ ...@@ -6,9 +6,23 @@
#define REMOTING_HOST_LOGGING_H_ #define REMOTING_HOST_LOGGING_H_
#include "base/logging.h" #include "base/logging.h"
#include "build/build_config.h"
#if defined(OS_WIN)
#include <guiddef.h>
#endif
namespace remoting { namespace remoting {
#if defined(OS_WIN)
// {2db51ca1-4fd8-4b88-b5a2-fb8606b66b02}
constexpr GUID kRemotingHostLogProviderGuid = {
0x2db51ca1,
0x4fd8,
0x4b88,
{0xb5, 0xa2, 0xfb, 0x86, 0x06, 0xb6, 0x6b, 0x02}};
#endif
// Initializes host logging. // Initializes host logging.
extern void InitHostLogging(); extern void InitHostLogging();
......
...@@ -9,11 +9,6 @@ ...@@ -9,11 +9,6 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/logging_win.h" #include "base/logging_win.h"
// {2db51ca1-4fd8-4b88-b5a2-fb8606b66b02}
const GUID kRemotingHostLogProvider =
{ 0x2db51ca1, 0x4fd8, 0x4b88,
{ 0xb5, 0xa2, 0xfb, 0x86, 0x06, 0xb6, 0x6b, 0x02 } };
namespace remoting { namespace remoting {
void InitHostLogging() { void InitHostLogging() {
...@@ -24,7 +19,7 @@ void InitHostLogging() { ...@@ -24,7 +19,7 @@ void InitHostLogging() {
logging::InitLogging(settings); logging::InitLogging(settings);
// Enable trace control and transport through event tracing for Windows. // Enable trace control and transport through event tracing for Windows.
logging::LogEventProvider::Initialize(kRemotingHostLogProvider); logging::LogEventProvider::Initialize(kRemotingHostLogProviderGuid);
} }
} // namespace remoting } // namespace remoting
...@@ -154,6 +154,8 @@ source_set("unit_tests") { ...@@ -154,6 +154,8 @@ source_set("unit_tests") {
sources = [ sources = [
"elevated_native_messaging_host.cc", "elevated_native_messaging_host.cc",
"elevated_native_messaging_host.h", "elevated_native_messaging_host.h",
"etw_trace_controller.cc",
"etw_trace_controller.h",
"launch_native_messaging_host_process.cc", "launch_native_messaging_host_process.cc",
"launch_native_messaging_host_process.h", "launch_native_messaging_host_process.h",
"rdp_client_unittest.cc", "rdp_client_unittest.cc",
...@@ -361,6 +363,8 @@ shared_library("remoting_core") { ...@@ -361,6 +363,8 @@ shared_library("remoting_core") {
"core_resource.h", "core_resource.h",
"elevated_native_messaging_host.cc", "elevated_native_messaging_host.cc",
"elevated_native_messaging_host.h", "elevated_native_messaging_host.h",
"etw_trace_controller.cc",
"etw_trace_controller.h",
"host_service.cc", "host_service.cc",
"host_service.h", "host_service.h",
"launch_native_messaging_host_process.cc", "launch_native_messaging_host_process.cc",
......
// Copyright 2020 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 "remoting/host/win/etw_trace_controller.h"
#include <stdint.h>
#include <memory>
#include "base/logging.h"
#include "base/macros.h"
#include "remoting/host/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
// Copyright 2020 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 REMOTING_HOST_WIN_ETW_TRACE_CONTROLLER_H_
#define REMOTING_HOST_WIN_ETW_TRACE_CONTROLLER_H_
#include "base/sequence_checker.h"
#include "base/win/event_trace_controller.h"
namespace remoting {
// Used to control an ETW trace session for events logged by the remote access
// host. Note: Only one instance of this class should be active at a time,
// otherwise the session started by the existing controller will be stopped.
class EtwTraceController {
public:
EtwTraceController();
EtwTraceController(const EtwTraceController&) = delete;
EtwTraceController& operator=(const EtwTraceController&) = delete;
~EtwTraceController();
// Starts a trace session for events associated with the host provider GUID.
// Returns true if this instance has started a trace session, otherwise false.
// Note: This will attempt to stop other trace sessions (e.g. from sawbuck).
bool Start();
// Stops the active tracing session, if one has been started by this instance.
void Stop();
// The active trace session name or nullptr if there isn't an active session.
const wchar_t* GetActiveSessionName() const;
private:
// Only one instance should exist at a time to prevent conflicts.
static EtwTraceController* instance_;
// Handles the Windows API calls needed for tracing.
base::win::EtwTraceController controller_;
// Used to ensure public method and destruction calls do not overlap.
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace remoting
#endif // REMOTING_HOST_WIN_ETW_TRACE_CONTROLLER_H_
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