Task 45828333: Move existing ETW tracing into LHC (#772)
This commit is contained in:
Родитель
cc017c12da
Коммит
670f91ce4b
|
@ -208,6 +208,12 @@ STDAPI_(void) HCTraceSetClientCallback(_In_opt_ HCTraceCallback* callback) noexc
|
|||
/// <returns></returns>
|
||||
STDAPI_(void) HCTraceSetTraceToDebugger(_In_ bool traceToDebugger) noexcept;
|
||||
|
||||
#if HC_PLATFORM_IS_MICROSOFT
|
||||
/// <summary>
|
||||
/// Enables or disables ETW tracing for Xbox and PC platforms.
|
||||
/// </summary>
|
||||
STDAPI_(void) HCTraceSetEtwEnabled(_In_ bool enabled) noexcept;
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Trace macros
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
#include "utils.h"
|
||||
#include "Platform/PlatformTrace.h"
|
||||
|
||||
#if HC_PLATFORM_IS_MICROSOFT
|
||||
#include <TraceLoggingProvider.h>
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
@ -46,21 +50,49 @@ int vsprintf_s(char(&buffer)[SIZE], _Printf_format_string_ char const* format, v
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if HC_PLATFORM_IS_MICROSOFT
|
||||
TRACELOGGING_DEFINE_PROVIDER(
|
||||
g_hTraceLoggingProvider,
|
||||
"libHttpClient",
|
||||
(0x2b6274b2, 0x159f, 0x4e6f, 0xb8, 0x0, 0xd, 0x17, 0x0, 0x9e, 0x14, 0x7a) // {2B6274B2-159F-4E6F-B800-0D17009E147A}
|
||||
);
|
||||
|
||||
|
||||
// Helper method to ensure our ETW Provider never gets registered twice. Registering an ETW provider twice may result
|
||||
// in a crash or undefined behavior. See https://learn.microsoft.com/en-us/windows/win32/api/traceloggingprovider/nf-traceloggingprovider-traceloggingregister
|
||||
// for more details.
|
||||
void RegisterProvider()
|
||||
{
|
||||
struct ProviderRegistrar
|
||||
{
|
||||
ProviderRegistrar()
|
||||
{
|
||||
TraceLoggingRegister(g_hTraceLoggingProvider);
|
||||
}
|
||||
~ProviderRegistrar()
|
||||
{
|
||||
TraceLoggingUnregister(g_hTraceLoggingProvider);
|
||||
}
|
||||
};
|
||||
|
||||
static ProviderRegistrar s_registrar{};
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Trace implementation
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void TraceMessageToDebugger(
|
||||
template<size_t SIZE>
|
||||
void FormatTrace(
|
||||
char const* areaName,
|
||||
HCTraceLevel level,
|
||||
uint64_t threadId,
|
||||
uint64_t timestamp,
|
||||
char const* message
|
||||
) noexcept
|
||||
char const* message,
|
||||
char (&outputBuffer)[SIZE]
|
||||
)
|
||||
{
|
||||
if (!GetTraceState().GetTraceToDebugger())
|
||||
return;
|
||||
|
||||
// Needs to match the HCTraceLevel enum
|
||||
static char const* traceLevelNames[] =
|
||||
{
|
||||
|
@ -72,8 +104,6 @@ void TraceMessageToDebugger(
|
|||
"V",
|
||||
};
|
||||
|
||||
static size_t const BUFFER_SIZE = 4096;
|
||||
|
||||
std::time_t timeTInSec = static_cast<std::time_t>(timestamp / 1000);
|
||||
uint32_t fractionMSec = static_cast<uint32_t>(timestamp % 1000);
|
||||
std::tm fmtTime = {};
|
||||
|
@ -86,7 +116,6 @@ void TraceMessageToDebugger(
|
|||
localtime_r(&timeTInSec, &fmtTime);
|
||||
#endif
|
||||
|
||||
char outputBuffer[BUFFER_SIZE] = {};
|
||||
// [threadId][level][time][area] message
|
||||
auto written = sprintf_s(outputBuffer, "[%04llX][%s][%02d:%02d:%02d.%03u][%s] %s",
|
||||
threadId,
|
||||
|
@ -104,8 +133,8 @@ void TraceMessageToDebugger(
|
|||
}
|
||||
|
||||
// Make sure there is room for the \r \n and \0
|
||||
written = std::min(written, static_cast<int>(BUFFER_SIZE - 3));
|
||||
auto remaining = BUFFER_SIZE - written;
|
||||
written = std::min(written, static_cast<int>(SIZE - 3));
|
||||
auto remaining = SIZE - written;
|
||||
|
||||
// Print new line
|
||||
auto written2 = sprintf_s(outputBuffer + written, remaining, "\r\n");
|
||||
|
@ -113,6 +142,24 @@ void TraceMessageToDebugger(
|
|||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void TraceMessageToDebugger(
|
||||
char const* areaName,
|
||||
HCTraceLevel level,
|
||||
uint64_t threadId,
|
||||
uint64_t timestamp,
|
||||
char const* message
|
||||
) noexcept
|
||||
{
|
||||
if (!GetTraceState().GetTraceToDebugger())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static size_t const BUFFER_SIZE = 4096;
|
||||
char outputBuffer[BUFFER_SIZE] = {};
|
||||
FormatTrace(areaName, level, threadId, timestamp, message, outputBuffer);
|
||||
|
||||
xbox::httpclient::TraceToDebugger(areaName, level, outputBuffer);
|
||||
}
|
||||
|
@ -132,6 +179,32 @@ void TraceMessageToClient(
|
|||
}
|
||||
}
|
||||
|
||||
#if HC_PLATFORM_IS_MICROSOFT
|
||||
void TraceMessageToETW(
|
||||
char const* areaName,
|
||||
HCTraceLevel level,
|
||||
uint64_t threadId,
|
||||
uint64_t timestamp,
|
||||
char const* message
|
||||
) noexcept
|
||||
{
|
||||
if (!GetTraceState().GetEtwEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static size_t const BUFFER_SIZE = 4096;
|
||||
char outputBuffer[BUFFER_SIZE] = {};
|
||||
FormatTrace(areaName, level, threadId, timestamp, message, outputBuffer);
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTraceLoggingProvider,
|
||||
"libHttpClient_TraceMessage",
|
||||
TraceLoggingString(outputBuffer, "Message")
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
STDAPI_(void) HCTraceSetTraceToDebugger(_In_ bool traceToDebugger) noexcept
|
||||
|
@ -144,6 +217,18 @@ STDAPI_(void) HCTraceSetClientCallback(_In_opt_ HCTraceCallback* callback) noexc
|
|||
GetTraceState().SetClientCallback(callback);
|
||||
}
|
||||
|
||||
#if HC_PLATFORM_IS_MICROSOFT
|
||||
STDAPI_(void) HCTraceSetEtwEnabled(_In_ bool enabled) noexcept
|
||||
{
|
||||
GetTraceState().SetEtwEnabled(enabled);
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
RegisterProvider();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
STDAPI_(void) HCTraceImplMessage(
|
||||
struct HCTraceImplArea const* area,
|
||||
HCTraceLevel level,
|
||||
|
@ -185,7 +270,7 @@ STDAPI_(void) HCTraceImplMessage_v(
|
|||
}
|
||||
|
||||
// Only do work if there's reason to
|
||||
if (GetTraceState().GetClientCallback() == nullptr && !GetTraceState().GetTraceToDebugger())
|
||||
if (GetTraceState().GetClientCallback() == nullptr && !GetTraceState().GetTraceToDebugger() && !GetTraceState().GetEtwEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -204,6 +289,9 @@ STDAPI_(void) HCTraceImplMessage_v(
|
|||
|
||||
TraceMessageToDebugger(area->Name, level, threadId, timestamp, message);
|
||||
TraceMessageToClient(area->Name, level, threadId, timestamp, message);
|
||||
#if HC_PLATFORM_IS_MICROSOFT
|
||||
TraceMessageToETW(area->Name, level, threadId, timestamp, message);
|
||||
#endif
|
||||
}
|
||||
|
||||
STDAPI_(uint64_t) HCTraceImplScopeId() noexcept
|
||||
|
@ -244,6 +332,18 @@ void TraceState::SetTraceToDebugger(_In_ bool traceToDebugger) noexcept
|
|||
m_traceToDebugger = traceToDebugger;
|
||||
}
|
||||
|
||||
bool TraceState::GetEtwEnabled() const noexcept
|
||||
{
|
||||
return m_etwEnabled;
|
||||
}
|
||||
|
||||
#if HC_PLATFORM_IS_MICROSOFT
|
||||
void TraceState::SetEtwEnabled(_In_ bool etwEnabled) noexcept
|
||||
{
|
||||
m_etwEnabled = etwEnabled;
|
||||
}
|
||||
#endif
|
||||
|
||||
void TraceState::SetClientCallback(HCTraceCallback* callback) noexcept
|
||||
{
|
||||
m_clientCallback = callback;
|
||||
|
|
|
@ -14,6 +14,10 @@ public:
|
|||
void SetClientCallback(HCTraceCallback* callback) noexcept;
|
||||
HCTraceCallback* GetClientCallback() const noexcept;
|
||||
uint64_t GetTimestamp() const noexcept;
|
||||
bool GetEtwEnabled() const noexcept;
|
||||
#if HC_PLATFORM_IS_MICROSOFT
|
||||
void SetEtwEnabled(_In_ bool enabled) noexcept;
|
||||
#endif
|
||||
|
||||
private:
|
||||
std::atomic<uint32_t> m_tracingClients{ 0 };
|
||||
|
@ -23,6 +27,7 @@ private:
|
|||
};
|
||||
std::atomic<HCTraceCallback*> m_clientCallback{ nullptr };
|
||||
bool m_traceToDebugger = false;
|
||||
bool m_etwEnabled = false;
|
||||
};
|
||||
|
||||
TraceState& GetTraceState() noexcept;
|
||||
|
|
Загрузка…
Ссылка в новой задаче