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

Update provider_compute_event_enable_mask so EventSouces with no keywords show up by default #75248

Merged
merged 3 commits into from
Oct 4, 2022

Conversation

davmason
Copy link
Member

@davmason davmason commented Sep 8, 2022

Fixes dotnet/diagnostics#3298

EventSource uses bits 44-47 of the keywords to store data about sessions:

internal const int SHIFT_SESSION_TO_KEYWORD = 44; // bits 44-47 inclusive are reserved
internal const uint MASK = 0x0fU; // the mask of 4 reserved bits
internal const uint MAX = 4; // maximum number of simultaneous ETW sessions supported

And we set them all to 1 by default in the manifest:
metadata.Descriptor = new EventDescriptor(
eventAttribute.EventId,
eventAttribute.Version,
#if FEATURE_MANAGED_ETW_CHANNELS
(byte)eventAttribute.Channel,
#else
(byte)0,
#endif
(byte)eventAttribute.Level,
(byte)eventAttribute.Opcode,
(int)eventAttribute.Task,
unchecked((long)((ulong)eventAttribute.Keywords | SessionMask.All.ToEventKeywords())));

This means that when we compute whether an event should be enabled we won't turn on EventSource events by default, since the event keywords are non-zero 0xF00000000000:

bool keyword_enabled = (keywords == 0) || ((session_keyword & keywords) != 0);

We have a workaround in the DiagnosticClient introduced here: dotnet/diagnostics#1091, but any other way of enabling EventPipe (env vars, other clients, etc) will still have this issue.

This fix lets the default EventSource keyword act as if it were 0 for all sessions.

This does have two compat issues

  • If someone has a provider that was using any of the masked bits it would now start to show up in traces that didn't have the keyword set
  • We cannot use those keywords for runtime events, our current high bit is 42 0x20000000000 so we are very close to that number. I don't think we have a choice regardless of this change though, due to EventSource treating those bits as reserved.

Copy link
Member

@lateralusX lateralusX left a comment

Choose a reason for hiding this comment

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

LGTM!

@@ -145,11 +145,13 @@ provider_compute_event_enable_mask (
if (session_provider) {
int64_t session_keyword = ep_session_provider_get_keywords (session_provider);
EventPipeEventLevel session_level = ep_session_provider_get_logging_level (session_provider);
// EventSources always set 0xF00000000000 to signify no keywords
int64_t session_mask = ~0xF00000000000;
Copy link
Member

Choose a reason for hiding this comment

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

Rather than do this filtering at the point of use, how about we filter these keyword bits at the point we are initializing the event in provider_add_event?

@noahfalk
Copy link
Member

noahfalk commented Sep 9, 2022

We have a workaround in the DiagnosticClient introduced here: dotnet/diagnostics#1091

Rats, I missed when this change went in. I may be unaware of constraints Sung was under when he did that, but this change you have here looks like a much better approach.

@noahfalk
Copy link
Member

noahfalk commented Sep 9, 2022

If someone has a provider that was using any of the masked bits it would now start to show up in traces that didn't have the keyword set

If they did that they would already be seeing weird behavior under ETW. Its possible someone does it and never uses their EventSource with ETW, but the odds of that seem low enough that I am willing to risk inconveniencing them.

@mikelle-rogers
Copy link
Member

Is there documentation that needs to be updated with this change?

@davmason
Copy link
Member Author

@mikelle-rogers no documentation needed, this is making things work as already documented

@davmason davmason closed this Sep 30, 2022
@davmason davmason reopened this Sep 30, 2022
@davmason
Copy link
Member Author

davmason commented Oct 1, 2022

I found out via failing tests that -1 as a keyword is special and we can't modify it, so I added that check

@davmason davmason merged commit 28c7eb8 into dotnet:main Oct 4, 2022
@adamsitnik
Copy link
Member

@davmason are you going to backport this PR to 7 and 6?

@davmason
Copy link
Member Author

@adamsitnik do you know of any customers that are asking for it? I'm happy to go through the process but the servicing bar requires a customer blocked on it

@adamsitnik
Copy link
Member

@davmason From my perspective I wonder if this related to microsoft/perfview#1718

do you know of any customers that are asking for it?

@tmds ?

@davmason
Copy link
Member Author

@davmason From my perspective I wonder if this related to microsoft/perfview#1718

Yes, that looks like the same issue. Trying to collect EventSources using the environment variables is broken. You can work around by either using dotnet-trace to collect instead, or setting keywords to 0xFFFFFFFF for any EventSources you want events from.

If we have people asking for the fix just point them to me and I can start the servicing process

@adamsitnik
Copy link
Member

Yes, that looks like the same issue.
If we have people asking for the fix just point them to me and I can start the servicing process

Then this would be me as I want to publish a new BenchmarkDotNet version with the PerfCollectDiagnoser (dotnet/BenchmarkDotNet#2117). It's a plugin that does allow for profiling with perfcollect during the benchmarking (we already have sth like that for EventPipe, but it's missing the native call stack info which is often important).

I need the BDN events to be able to tell when given benchmark iteration started and finished to be able to implement detection of regression on top of it. This year I am aiming at adding a BDN feature where the user just specifies the benchmark that has regressed between .NET releases, BDN runs it with profiler attached, loads the trace file using Trace Event, filters it based on the events to selected time frame and then uses Trace Event to diff the traces and just tell the user where the regression is.

@davmason
Copy link
Member Author

I'm happy to take it to servicing if that is the best outcome, but the next servicing date is in January so no fixes would be available until then. I suspect it will work better for you to find a workaround

Are you able to use the diagnostics client instead of the environment variables? https://learn.microsoft.com/en-us/dotnet/core/diagnostics/diagnostics-client-library

There is already a workaround in that library and you wouldn't have to wait on any servicing fixes, the client and runtime support attaching to your own process and attaching at startup, so it should work for most scenarios

davmason added a commit to davmason/runtime that referenced this pull request Nov 2, 2022
carlossanlop pushed a commit that referenced this pull request Nov 7, 2022
…Pipe sessions (#75248) (#77811)

* Update provider_compute_event_enable_mask so EventSouces with no keywords show up by default (#75248)

Update ep-provider.c

* Update ep-provider.c

* Update src/native/eventpipe/ep-provider.c

Co-authored-by: Juan Hoyos <juan.hoyos@microsoft.com>

Co-authored-by: Juan Hoyos <juan.hoyos@microsoft.com>
@ghost ghost locked as resolved and limited conversation to collaborators Nov 13, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unable to set providers using EventPipeConfig
5 participants