Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consolidate and clean up all API logging #15737

Conversation

DHowett
Copy link
Member

@DHowett DHowett commented Jul 20, 2023

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.)

`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
```
They were originally using uint32/64, which did not allow for tools like
WPA to infer their connection to processes and dates.

I cleared this with David Kaplan, as he is relying on those events.
TraceLoggingWrite( \
g_hConhostV2EventTraceProvider, \
"API_" ApiName, \
TraceLoggingPid([&] { const auto p=m->GetProcessHandle(); return p ? p->dwProcessId : 0; }(), "OriginatingProcess"), \
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These could be lifted out if reviewers desire.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally would prefer that. This will produce a unique lambda instance per macro invocation which then might get folded into a single instance in Release builds if the compiler realizes they're all the same assembly. But I believe it's safer if we add free-standing TraceGetProcessId and TraceGetThreadId functions instead that take a CONSOLE_API_MSG* and put them above the macro. It would also make compilation a teeny tiny bit cheaper.

(We could also add them as member functions to CONSOLE_API_MSG, but I would greatly prefer if we moved CONSOLE_API_MSG back to being a trivial class. I'm really not sure if the "writing data off the end of the class" thing is legal C++ when the struct is non-trivial and I'd rather not tempt fate. 😓)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I switched to functions. Trust me, the CONSOLE_API_MSG class gives me the ABSOLUTE willies

src/server/ApiDispatchers.cpp Outdated Show resolved Hide resolved
Comment on lines 650 to 651
TraceLoggingInt32(a->CurrentWindowSize.X, "WindowWidthInChars"),
TraceLoggingInt32(a->CurrentWindowSize.Y, "WindowHeightInChars"),
Copy link
Member

@lhecker lhecker Jul 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit 1: These have a different name than the actual fields.

nit 2: Technically these are Int16 right? We can improve the way COORDs are formatted in traces if we use TraceLoggingStruct here. If we add a new macro like TraceLoggingConsoleCoord that abstracts this away, I think it might look pretty neat. Something like

#define TraceLoggingConsoleCoord(value, name) \
    TraceLoggingStruct(2, name), \
    TraceLoggingInt16(value.X, "X"), \
    TraceLoggingInt16(value.Y, "Y")

Alternatively, we could also use TraceLoggingInt16FixedArray(&a->CurrentWindowSize, "CurrentWindowSize").

nit 3: People depend on our trace logs and we can't change their names? 😟

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh, these names, types and values were ported directly from the original tracing.cpp code. We can definitely change them. I like T.L.Struct.

The only logs people are depending on are CookedRead and ConsoleAttachDetach. The rest, we can blow up any way we wish.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE LOOKS GREAT

@lhecker lhecker added the AutoMerge Marked for automatic merge by the bot when requirements are met label Jul 21, 2023
@microsoft-github-policy-service microsoft-github-policy-service bot merged commit 5daf498 into main Jul 21, 2023
16 checks passed
@microsoft-github-policy-service microsoft-github-policy-service bot deleted the dev/duhowett/trace-it-better-move-it-faster branch July 21, 2023 19:00
@DHowett DHowett added this to To Cherry Pick in 1.17 Servicing Pipeline via automation Jul 27, 2023
@DHowett DHowett added this to To Cherry Pick in 1.18 Servicing Pipeline via automation Jul 27, 2023
@DHowett DHowett moved this from To Cherry Pick to Cherry Picked in 1.17 Servicing Pipeline Jul 27, 2023
DHowett added a commit that referenced this pull request Jul 27, 2023
`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.)

(cherry picked from commit 5daf498)
Service-Card-Id: 90012630
Service-Version: 1.17
@DHowett DHowett moved this from To Cherry Pick to Cherry Picked in 1.18 Servicing Pipeline Jul 27, 2023
DHowett added a commit that referenced this pull request Jul 27, 2023
`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.)

(cherry picked from commit 5daf498)
Service-Card-Id: 90012631
Service-Version: 1.18
@DHowett DHowett moved this from Cherry Picked to Validated in 1.17 Servicing Pipeline Aug 2, 2023
@DHowett DHowett moved this from Cherry Picked to Validated in 1.18 Servicing Pipeline Sep 25, 2023
@DHowett DHowett moved this from Validated to Shipped in 1.18 Servicing Pipeline Oct 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
AutoMerge Marked for automatic merge by the bot when requirements are met
Development

Successfully merging this pull request may close these issues.

None yet

3 participants