-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Add event to RuntimeEventSource for AppContext switches #57303
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
Changes from 1 commit
e0a1602
c6503d3
c52f044
8002ac9
451ee4b
6dd83dc
bc59e00
737492b
4facebf
b0235f8
58a87f5
5d4060c
1044a0f
f352689
6a62a27
fad8256
8989c1b
01288ae
0da1677
740a750
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Fixes #56142
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,6 +50,12 @@ public static void Initialize() | |
| // as you can't make a constructor partial. | ||
| private RuntimeEventSource(int _) { } | ||
|
|
||
| [Event(2, Level = EventLevel.Informational)] | ||
|
||
| internal void LogAppContextSwitch(string switchName, int value) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @brianrob Would a single event with all of the data be better for something like this?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think one event per switch is good. It makes it easy to consume the data, and I can't imagine we'll have so many that the cost of this event will be painful. If/when we choose to create events were we dump data in bulk, it makes both the event production and event consumption code more complex. On the production side, you have to chunk the data to ensure that you don't run up against size limitations (e.g. ETW has a 64K size limit per event). On the consumption side, you have to be more sophisticated in how you parse the event. There are definitely places were it's valuable - for example BulkType events in the runtime when we log heap snapshots. There are just tons of types, and so emitting each one in its own event is very costly.
agocke marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| base.WriteEvent(2, switchName, value); | ||
| } | ||
agocke marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| protected override void OnEventCommand(EventCommandEventArgs command) | ||
| { | ||
| if (command.Command == EventCommand.Enable) | ||
agocke marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
@@ -87,6 +93,8 @@ protected override void OnEventCommand(EventCommandEventArgs command) | |
| _ilBytesJittedCounter ??= new PollingCounter("il-bytes-jitted", this, () => System.Runtime.JitInfo.GetCompiledILBytes()) { DisplayName = "IL Bytes Jitted", DisplayUnits = "B" }; | ||
| _methodsJittedCounter ??= new PollingCounter("methods-jitted-count", this, () => System.Runtime.JitInfo.GetCompiledMethodCount()) { DisplayName = "Number of Methods Jitted" }; | ||
| _jitTimeCounter ??= new IncrementingPollingCounter("time-in-jit", this, () => System.Runtime.JitInfo.GetCompilationTime().TotalMilliseconds) { DisplayName = "Time spent in JIT", DisplayUnits = "ms", DisplayRateTimeScale = new TimeSpan(0, 0, 1) }; | ||
|
|
||
| AppContext.LogSwitchValues(this); | ||
josalem marked this conversation as resolved.
Show resolved
Hide resolved
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is just logging values at a specific point in time (when the event source is enabled) - is that the desire? I'm thinking of the possibility of scenarios like:
or
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think most of those are edge cases. The 90% usage is:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Definitely agree that those should not be the common case, but wanted to call it out.
I think part of my question is what does this end up looking like when tracing startup (where I'd expect the event source is enabled before the app's entry is is run)? Could it end up being the first scenario I had above?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure, @brianrob @josalem do event sources OnCommand run before Main executes when you attach the event source at startup (which not many do). @elinor-fung These are great questions BTW 👍🏾
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They definitely can, but not all will. If the EventSource comes into existence before Main is called and it is told to turn on (e.g. EventPipe, ETW, or some EventListener tells it to), then it will trigger before Main. By design, there isn't anything that requires that Main run before events can be emitted. A good example here is FrameworkEventSource which often comes into existence before Main.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To add to this, if you want to ensure that these can be emitted early, make sure that the EventSource that emits them comes into existence early. That may already be the case, but if not, make sure it gets instantiated early, even if it doesn't log any events when instantiated. Just the instantiation will allow it to be enabled immediately (at least by ETW, but shortly by EventPipe once it comes up).
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @elinor-fung, just read your first scenario - I think that the right way to handle a race between logging the current state and changes to switches is to dump the set of switches at the beginning of the tracing session as this code does. Additionally, any time a switch is configured, it should be logged immediately. This ensures that if switches change value or get set after the session is created, we see the change. This, combined with instantiating the EventSource early will ensure that we don't miss any data. |
||
| } | ||
|
|
||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only going to log switches set using
AppContext.SetSwitch. It won't log switches set using build properties and runtime.json that I think are much more common these days. Do we need to log those too?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I would like to include those as well -- do you know which API they go through if not SetSwitch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AppDomain.SetData(#47922 tracks addingAppContext.SetDatafor completeness)Also, the runtime startup goes over everything that is in runtime.json and calls
AppDomain.SetDatafor it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case I will also add everything in
s_dataStorewhich has a boolean value. I'm trying to avoid grabbing everything in s_dataStore to limit the amount of potential user data that's recorded.