Skip to content

Commit 5daf498

Browse files
authored
Consolidate and clean up all API logging (#15737)
`s_TraceApi` was a magic function in Tracing that logged a different event based on what type it was called with. It was bad for two reasons: 1. I wanted to add a field to each trace indicating the originating process and thread. This would have required adding a `CONSOLE_API_MSG` parameter to _every instance_ of `s_TraceApi`, and even then it would have not been particularly consistent. 2. The design of Tracing, where the TraceLogging macros are hidden inside opaque functions, subverts the lightweight trace probe detection present in `TraceLoggingWrite`. Every tracing probe turned into a call to a cold function which, in 99% of cases, returned immediately. To that end, I've introduced a new macro _only_ to ApiDispatchers that emits a named probe with a set of preloaded information. It is a macro to avoid any unnecessary branching or the emission of any explicit tracing functions into the final binary. I have also removed the generic handler for timing any/all API calls, as we never used them and they were largely redundant with the information we were capturing from API-specific reports. I've also removed tracing from all APIs that do not mutate console state. With the notable exception of ReadConsoleInput, we will see logs only for things that change mutable console state. All these things together allows us to construct a process+API-focused timeline of console events, ala: ``` cmd.exe (20304) CookedRead pwsh 4 07/13/2023 22:02:53.751 cmd.exe (20304) API_GetConsoleMode True cmd.exe (20304) API_SetConsoleMode False 0x00000003 cmd.exe (20304) API_SetConsoleMode True 0x000001F7 pwsh.exe (4032) ConsoleAttachDetach 07/13/2023 22:03:17.393 True True pwsh.exe (4032) API_GetConsoleMode False pwsh.exe (4032) API_GetConsoleMode False pwsh.exe (4032) API_SetConsoleMode False 0x00000007 ``` This pull request also switches the ConsoleAttachDetach and CookedRead reports to use the PID and FILETIME markings for their pids and filetimes. This is compatible with the uint32 and uint64 fields that used to use those names, so anybody who was depending on them will experience no change in functionality. I also switched up their order to make them more ergonomic in WPA when combined with the other API_ tracing (as viewed above.)
1 parent 3de496d commit 5daf498

File tree

6 files changed

+103
-310
lines changed

6 files changed

+103
-310
lines changed

src/host/tracing.cpp

+5-238
Original file line numberDiff line numberDiff line change
@@ -18,249 +18,16 @@ enum TraceKeywords
1818
Output = 0x008, // _DBGOUTPUT
1919
General = 0x100,
2020
Input = 0x200,
21-
API = 0x400,
21+
//API = 0x400, // No longer used
2222
UIA = 0x800,
2323
CookedRead = 0x1000,
2424
ConsoleAttachDetach = 0x2000,
2525
All = 0x1FFF
2626
};
2727
DEFINE_ENUM_FLAG_OPERATORS(TraceKeywords);
2828

29-
// Routine Description:
30-
// - Creates a tracing object to assist with automatically firing a stop event
31-
// when this object goes out of scope.
32-
// - Give it back to the caller and they will release it when the event period is over.
33-
// Arguments:
34-
// - onExit - Function to process when the object is destroyed (on exit)
35-
Tracing::Tracing(std::function<void()> onExit) :
36-
_onExit(onExit)
37-
{
38-
}
39-
40-
// Routine Description:
41-
// - Destructs a tracing object, running any on exit routine, if necessary.
42-
Tracing::~Tracing()
43-
{
44-
if (_onExit)
45-
{
46-
_onExit();
47-
}
48-
}
49-
50-
// Routine Description:
51-
// - Provides generic tracing for all API call types in the form of
52-
// start/stop period events for timing and region-of-interest purposes
53-
// while doing performance analysis.
54-
// Arguments:
55-
// - result - Reference to the area where the result code from the Api call
56-
// will be stored for use in the stop event.
57-
// - traceName - The name of the API call to list in the trace details
58-
// Return Value:
59-
// - An object for the caller to hold until the API call is complete.
60-
// Then destroy it to signal that the call is over so the stop trace can be written.
61-
Tracing Tracing::s_TraceApiCall(const NTSTATUS result, PCSTR traceName)
62-
{
63-
// clang-format off
64-
TraceLoggingWrite(
65-
g_hConhostV2EventTraceProvider,
66-
"ApiCall",
67-
TraceLoggingString(traceName, "ApiName"),
68-
TraceLoggingOpcode(WINEVENT_OPCODE_START),
69-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
70-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
71-
TraceLoggingKeyword(TraceKeywords::API));
72-
73-
return Tracing([traceName, &result] {
74-
TraceLoggingWrite(
75-
g_hConhostV2EventTraceProvider,
76-
"ApiCall",
77-
TraceLoggingString(traceName, "ApiName"),
78-
TraceLoggingHResult(result, "Result"),
79-
TraceLoggingOpcode(WINEVENT_OPCODE_STOP),
80-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
81-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
82-
TraceLoggingKeyword(TraceKeywords::API));
83-
});
84-
// clang-format on
85-
}
86-
8729
ULONG Tracing::s_ulDebugFlag = 0x0;
8830

89-
void Tracing::s_TraceApi(const NTSTATUS status, const CONSOLE_GETLARGESTWINDOWSIZE_MSG* const a)
90-
{
91-
TraceLoggingWrite(
92-
g_hConhostV2EventTraceProvider,
93-
"API_GetLargestWindowSize",
94-
TraceLoggingHexInt32(status, "ResultCode"),
95-
TraceLoggingInt32(a->Size.X, "MaxWindowWidthInChars"),
96-
TraceLoggingInt32(a->Size.Y, "MaxWindowHeightInChars"),
97-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
98-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
99-
TraceLoggingKeyword(TraceKeywords::API));
100-
}
101-
102-
void Tracing::s_TraceApi(const NTSTATUS status, const CONSOLE_SCREENBUFFERINFO_MSG* const a, const bool fSet)
103-
{
104-
// Duplicate copies required by TraceLogging documentation ("don't get cute" examples)
105-
// Using logic inside these macros can make problems. Do all logic outside macros.
106-
107-
if (fSet)
108-
{
109-
TraceLoggingWrite(
110-
g_hConhostV2EventTraceProvider,
111-
"API_SetConsoleScreenBufferInfo",
112-
TraceLoggingHexInt32(status, "ResultCode"),
113-
TraceLoggingInt32(a->Size.X, "BufferWidthInChars"),
114-
TraceLoggingInt32(a->Size.Y, "BufferHeightInChars"),
115-
TraceLoggingInt32(a->CurrentWindowSize.X, "WindowWidthInChars"),
116-
TraceLoggingInt32(a->CurrentWindowSize.Y, "WindowHeightInChars"),
117-
TraceLoggingInt32(a->MaximumWindowSize.X, "MaxWindowWidthInChars"),
118-
TraceLoggingInt32(a->MaximumWindowSize.Y, "MaxWindowHeightInChars"),
119-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
120-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
121-
TraceLoggingKeyword(TraceKeywords::API));
122-
}
123-
else
124-
{
125-
TraceLoggingWrite(
126-
g_hConhostV2EventTraceProvider,
127-
"API_GetConsoleScreenBufferInfo",
128-
TraceLoggingHexInt32(status, "ResultCode"),
129-
TraceLoggingInt32(a->Size.X, "BufferWidthInChars"),
130-
TraceLoggingInt32(a->Size.Y, "BufferHeightInChars"),
131-
TraceLoggingInt32(a->CurrentWindowSize.X, "WindowWidthInChars"),
132-
TraceLoggingInt32(a->CurrentWindowSize.Y, "WindowHeightInChars"),
133-
TraceLoggingInt32(a->MaximumWindowSize.X, "MaxWindowWidthInChars"),
134-
TraceLoggingInt32(a->MaximumWindowSize.Y, "MaxWindowHeightInChars"),
135-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
136-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
137-
TraceLoggingKeyword(TraceKeywords::API));
138-
}
139-
}
140-
141-
void Tracing::s_TraceApi(const NTSTATUS status, const CONSOLE_SETSCREENBUFFERSIZE_MSG* const a)
142-
{
143-
TraceLoggingWrite(
144-
g_hConhostV2EventTraceProvider,
145-
"API_SetConsoleScreenBufferSize",
146-
TraceLoggingHexInt32(status, "ResultCode"),
147-
TraceLoggingInt32(a->Size.X, "BufferWidthInChars"),
148-
TraceLoggingInt32(a->Size.Y, "BufferHeightInChars"),
149-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
150-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
151-
TraceLoggingKeyword(TraceKeywords::API));
152-
}
153-
154-
void Tracing::s_TraceApi(const NTSTATUS status, const CONSOLE_SETWINDOWINFO_MSG* const a)
155-
{
156-
TraceLoggingWrite(
157-
g_hConhostV2EventTraceProvider,
158-
"API_SetConsoleWindowInfo",
159-
TraceLoggingHexInt32(status, "ResultCode"),
160-
TraceLoggingBool(a->Absolute, "IsWindowRectAbsolute"),
161-
TraceLoggingInt32(a->Window.Left, "WindowRectLeft"),
162-
TraceLoggingInt32(a->Window.Right, "WindowRectRight"),
163-
TraceLoggingInt32(a->Window.Top, "WindowRectTop"),
164-
TraceLoggingInt32(a->Window.Bottom, "WindowRectBottom"),
165-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
166-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
167-
TraceLoggingKeyword(TraceKeywords::API));
168-
}
169-
170-
void Tracing::s_TraceApi(_In_ const void* const buffer, const CONSOLE_WRITECONSOLE_MSG* const a)
171-
{
172-
// clang-format off
173-
if (a->Unicode)
174-
{
175-
const auto buf = static_cast<const wchar_t* const>(buffer);
176-
TraceLoggingWrite(
177-
g_hConhostV2EventTraceProvider,
178-
"API_WriteConsole",
179-
TraceLoggingBoolean(a->Unicode, "Unicode"),
180-
TraceLoggingUInt32(a->NumBytes, "NumBytes"),
181-
TraceLoggingCountedWideString(buf, static_cast<UINT16>(a->NumBytes / sizeof(wchar_t)), "input buffer"),
182-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
183-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
184-
TraceLoggingKeyword(TraceKeywords::API));
185-
}
186-
else
187-
{
188-
const auto buf = static_cast<const char* const>(buffer);
189-
TraceLoggingWrite(
190-
g_hConhostV2EventTraceProvider,
191-
"API_WriteConsole",
192-
TraceLoggingBoolean(a->Unicode, "Unicode"),
193-
TraceLoggingUInt32(a->NumBytes, "NumBytes"),
194-
TraceLoggingCountedString(buf, static_cast<UINT16>(a->NumBytes / sizeof(char)), "input buffer"),
195-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
196-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
197-
TraceLoggingKeyword(TraceKeywords::API));
198-
}
199-
// clang-format on
200-
}
201-
202-
void Tracing::s_TraceApi(const CONSOLE_SCREENBUFFERINFO_MSG* const a)
203-
{
204-
TraceLoggingWrite(
205-
g_hConhostV2EventTraceProvider,
206-
"API_GetConsoleScreenBufferInfo",
207-
TraceLoggingInt16(a->Size.X, "Size.X"),
208-
TraceLoggingInt16(a->Size.Y, "Size.Y"),
209-
TraceLoggingInt16(a->CursorPosition.X, "CursorPosition.X"),
210-
TraceLoggingInt16(a->CursorPosition.Y, "CursorPosition.Y"),
211-
TraceLoggingInt16(a->ScrollPosition.X, "ScrollPosition.X"),
212-
TraceLoggingInt16(a->ScrollPosition.Y, "ScrollPosition.Y"),
213-
TraceLoggingHexUInt16(a->Attributes, "Attributes"),
214-
TraceLoggingInt16(a->CurrentWindowSize.X, "CurrentWindowSize.X"),
215-
TraceLoggingInt16(a->CurrentWindowSize.Y, "CurrentWindowSize.Y"),
216-
TraceLoggingInt16(a->MaximumWindowSize.X, "MaximumWindowSize.X"),
217-
TraceLoggingInt16(a->MaximumWindowSize.Y, "MaximumWindowSize.Y"),
218-
TraceLoggingHexUInt16(a->PopupAttributes, "PopupAttributes"),
219-
TraceLoggingBoolean(a->FullscreenSupported, "FullscreenSupported"),
220-
TraceLoggingHexUInt32FixedArray((UINT32 const*)a->ColorTable, _countof(a->ColorTable), "ColorTable"),
221-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
222-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
223-
TraceLoggingKeyword(TraceKeywords::API));
224-
static_assert(sizeof(UINT32) == sizeof(*a->ColorTable), "a->ColorTable");
225-
}
226-
227-
void Tracing::s_TraceApi(const CONSOLE_MODE_MSG* const a, const std::wstring_view handleType)
228-
{
229-
TraceLoggingWrite(
230-
g_hConhostV2EventTraceProvider,
231-
"API_GetConsoleMode",
232-
TraceLoggingHexUInt32(a->Mode, "Mode"),
233-
TraceLoggingCountedWideString(handleType.data(), gsl::narrow_cast<ULONG>(handleType.size()), "Handle type"),
234-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
235-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
236-
TraceLoggingKeyword(TraceKeywords::API));
237-
}
238-
239-
void Tracing::s_TraceApi(const CONSOLE_SETTEXTATTRIBUTE_MSG* const a)
240-
{
241-
TraceLoggingWrite(
242-
g_hConhostV2EventTraceProvider,
243-
"API_SetConsoleTextAttribute",
244-
TraceLoggingHexUInt16(a->Attributes, "Attributes"),
245-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
246-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
247-
TraceLoggingKeyword(TraceKeywords::API));
248-
}
249-
250-
void Tracing::s_TraceApi(const CONSOLE_WRITECONSOLEOUTPUTSTRING_MSG* const a)
251-
{
252-
TraceLoggingWrite(
253-
g_hConhostV2EventTraceProvider,
254-
"API_WriteConsoleOutput",
255-
TraceLoggingInt16(a->WriteCoord.X, "WriteCoord.X"),
256-
TraceLoggingInt16(a->WriteCoord.Y, "WriteCoord.Y"),
257-
TraceLoggingHexUInt32(a->StringType, "StringType"),
258-
TraceLoggingUInt32(a->NumRecords, "NumRecords"),
259-
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
260-
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
261-
TraceLoggingKeyword(TraceKeywords::API));
262-
}
263-
26431
void Tracing::s_TraceWindowViewport(const Viewport& viewport)
26532
{
26633
TraceLoggingWrite(
@@ -413,10 +180,10 @@ void Tracing::s_TraceCookedRead(_In_ ConsoleProcessHandle* const pConsoleProcess
413180
TraceLoggingWrite(
414181
g_hConhostV2EventTraceProvider,
415182
"CookedRead",
183+
TraceLoggingPid(pConsoleProcessHandle->dwProcessId, "AttachedProcessId"),
416184
TraceLoggingCountedWideString(pwchCookedBuffer, cchCookedBufferLength, "ReadBuffer"),
417185
TraceLoggingULong(cchCookedBufferLength, "ReadBufferLength"),
418-
TraceLoggingUInt32(pConsoleProcessHandle->dwProcessId, "AttachedProcessId"),
419-
TraceLoggingUInt64(pConsoleProcessHandle->GetProcessCreationTime(), "AttachedProcessCreationTime"),
186+
TraceLoggingFileTime(pConsoleProcessHandle->GetProcessCreationTime(), "AttachedProcessCreationTime"),
420187
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
421188
TraceLoggingKeyword(TraceKeywords::CookedRead));
422189
}
@@ -431,8 +198,8 @@ void Tracing::s_TraceConsoleAttachDetach(_In_ ConsoleProcessHandle* const pConso
431198
TraceLoggingWrite(
432199
g_hConhostV2EventTraceProvider,
433200
"ConsoleAttachDetach",
434-
TraceLoggingUInt32(pConsoleProcessHandle->dwProcessId, "AttachedProcessId"),
435-
TraceLoggingUInt64(pConsoleProcessHandle->GetProcessCreationTime(), "AttachedProcessCreationTime"),
201+
TraceLoggingPid(pConsoleProcessHandle->dwProcessId, "AttachedProcessId"),
202+
TraceLoggingFileTime(pConsoleProcessHandle->GetProcessCreationTime(), "AttachedProcessCreationTime"),
436203
TraceLoggingBool(bIsAttach, "IsAttach"),
437204
TraceLoggingBool(bIsUserInteractive, "IsUserInteractive"),
438205
TraceLoggingKeyword(TIL_KEYWORD_TRACE),

src/host/tracing.hpp

+5-20
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,14 @@ Author(s):
3535
#define DBGOUTPUT(_params_)
3636
#endif
3737

38+
#define TraceLoggingConsoleCoord(value, name) \
39+
TraceLoggingStruct(2, name), \
40+
TraceLoggingInt32(value.X, "X"), \
41+
TraceLoggingInt32(value.Y, "Y")
42+
3843
class Tracing
3944
{
4045
public:
41-
~Tracing();
42-
43-
static Tracing s_TraceApiCall(const NTSTATUS result, PCSTR traceName);
44-
45-
static void s_TraceApi(const NTSTATUS status, const CONSOLE_GETLARGESTWINDOWSIZE_MSG* const a);
46-
static void s_TraceApi(const NTSTATUS status, const CONSOLE_SCREENBUFFERINFO_MSG* const a, const bool fSet);
47-
static void s_TraceApi(const NTSTATUS status, const CONSOLE_SETSCREENBUFFERSIZE_MSG* const a);
48-
static void s_TraceApi(const NTSTATUS status, const CONSOLE_SETWINDOWINFO_MSG* const a);
49-
50-
static void s_TraceApi(_In_ const void* const buffer, const CONSOLE_WRITECONSOLE_MSG* const a);
51-
52-
static void s_TraceApi(const CONSOLE_SCREENBUFFERINFO_MSG* const a);
53-
static void s_TraceApi(const CONSOLE_MODE_MSG* const a, const std::wstring_view handleType);
54-
static void s_TraceApi(const CONSOLE_SETTEXTATTRIBUTE_MSG* const a);
55-
static void s_TraceApi(const CONSOLE_WRITECONSOLEOUTPUTSTRING_MSG* const a);
56-
5746
static void s_TraceWindowViewport(const Microsoft::Console::Types::Viewport& viewport);
5847

5948
static void s_TraceChars(_In_z_ const char* pszMessage, ...);
@@ -69,8 +58,4 @@ class Tracing
6958

7059
private:
7160
static ULONG s_ulDebugFlag;
72-
73-
Tracing(std::function<void()> onExit);
74-
75-
std::function<void()> _onExit;
7661
};

0 commit comments

Comments
 (0)