master
cpp 101 lines 3.3 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 GuestTelemetryLogger.cpp
8
9 Abstract:
10
11 This file contains logic to log guest telemetry.
12
13 --*/
14
15 #include "precomp.h"
16 #include "GuestTelemetryLogger.h"
17
18 GuestTelemetryLogger::GuestTelemetryLogger(GUID VmId) : m_runtimeId(VmId)
19 {
20 m_threadExit.create(wil::EventOptions::ManualReset);
21 }
22
23 GuestTelemetryLogger::~GuestTelemetryLogger()
24 {
25 m_threadExit.SetEvent();
26 if (m_thread.joinable())
27 {
28 m_thread.join();
29 }
30 }
31
32 std::shared_ptr<GuestTelemetryLogger> GuestTelemetryLogger::Create(GUID VmId, const wil::unique_event& ExitEvent)
33 {
34 auto logger = std::shared_ptr<GuestTelemetryLogger>(new GuestTelemetryLogger(VmId));
35 logger->Start(ExitEvent);
36 return logger;
37 }
38
39 LPCWSTR GuestTelemetryLogger::GetPipeName() const
40 {
41 return m_pipeName.c_str();
42 }
43
44 void GuestTelemetryLogger::Start(const wil::unique_event& ExitEvent)
45 {
46 THROW_HR_IF(E_UNEXPECTED, !m_pipeName.empty());
47
48 m_pipeName = wsl::windows::common::helpers::GetUniquePipeName();
49 wil::unique_hfile pipe(CreateNamedPipeW(
50 m_pipeName.c_str(), (PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED), (PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT), 1, LX_RELAY_BUFFER_SIZE, LX_RELAY_BUFFER_SIZE, 0, nullptr));
51
52 THROW_LAST_ERROR_IF(!pipe);
53
54 wil::unique_handle exitEvent(wsl::windows::common::wslutil::DuplicateHandle(ExitEvent.get()));
55 m_thread = std::thread([this, Pipe = std::move(pipe), ExitEvent = std::move(exitEvent)]() {
56 try
57 {
58 wsl::windows::common::wslutil::SetThreadDescription(L"GuestTelemetryLogger");
59
60 // When the pipe connects, start reading data.
61 const std::vector<HANDLE> exitEvents = {m_threadExit.get(), ExitEvent.get()};
62 wsl::windows::common::helpers::ConnectPipe(Pipe.get(), INFINITE, exitEvents);
63
64 namespace io = wsl::windows::common::io;
65 io::MultiHandleWait ioWait;
66 ioWait.AddHandle(
67 std::make_unique<io::ReadHandle>(
68 io::HandleWrapper{Pipe.get()},
69 [this](const gsl::span<char>& buffer) {
70 if (!buffer.empty())
71 {
72 ProcessInput(std::string_view{buffer.data(), static_cast<size_t>(buffer.size())});
73 }
74 }),
75 io::MultiHandleWait::IgnoreErrors);
76
77 ioWait.AddHandle(
78 std::make_unique<io::EventHandle>(io::HandleWrapper{m_threadExit.get()}),
79 io::MultiHandleWait::CancelOnCompleted | io::MultiHandleWait::NeedNotComplete);
80
81 ioWait.AddHandle(
82 std::make_unique<io::EventHandle>(io::HandleWrapper{ExitEvent.get()}),
83 io::MultiHandleWait::CancelOnCompleted | io::MultiHandleWait::NeedNotComplete);
84
85 ioWait.Run(std::nullopt);
86 }
87 CATCH_LOG()
88 });
89 }
90
91 void GuestTelemetryLogger::ProcessInput(const std::string_view Input)
92 {
93 m_ringBuffer.Insert(Input);
94
95 const auto delimiterCount = std::count(Input.begin(), Input.end(), '\n');
96 const auto newStrings = m_ringBuffer.GetLastDelimitedStrings('\n', delimiterCount);
97 for (const auto& logLine : newStrings)
98 {
99 WSL_LOG("GuestTelemetry", TraceLoggingValue(logLine.c_str(), "text"), TraceLoggingValue(m_runtimeId, "vmId"));
100 }
101 }