Skip to content

Commit 1c22582

Browse files
Copilotbrianrob
andauthored
Fix TraceEvent CaptureState API to work with keywords not previously enabled in session (#2222)
* Initial plan for issue * Implement CaptureState keyword merging fix Query existing provider keywords and merge with requested keywords before CaptureState. Enables provider with merged keywords if necessary to ensure CaptureState works even when using keywords that haven't been previously enabled. Co-authored-by: brianrob <[email protected]> * Implement GetEnabledInfoForProviderAndSession with struct return and level support Co-authored-by: brianrob <[email protected]> * Replace stackalloc with fixed keyword for Guid handling Co-authored-by: brianrob <[email protected]> * Fix-up Guid handling. Always enable the provider even if it wasn't previously enabled. * Code review feedback. --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: brianrob <[email protected]> Co-authored-by: Brian Robbins <[email protected]>
1 parent 3af4abd commit 1c22582

File tree

1 file changed

+44
-10
lines changed

1 file changed

+44
-10
lines changed

src/TraceEvent/TraceEventSession.cs

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,22 @@ public void CaptureState(Guid providerGuid, ulong matchAnyKeywords = ulong.MaxVa
11161116
asArray[6] = (byte)(longVal >> 48);
11171117
asArray[7] = (byte)(longVal >> 56);
11181118
}
1119+
// Query existing keywords and merge them with requested keywords before capture state
1120+
ulong mergedKeywords = matchAnyKeywords;
1121+
TraceEventLevel levelToUse = TraceEventLevel.Verbose;
1122+
EnabledProviderInfo? existingInfo = GetEnabledInfoForProviderAndSession(&providerGuid, (ulong)m_SessionId);
1123+
if (existingInfo.HasValue)
1124+
{
1125+
mergedKeywords |= existingInfo.Value.MatchAnyKeywords;
1126+
levelToUse = existingInfo.Value.Level;
1127+
}
1128+
1129+
// Enable the provider with merged keywords first
1130+
int enableHr = TraceEventNativeMethods.EnableTraceEx2(
1131+
m_SessionHandle, providerGuid, TraceEventNativeMethods.EVENT_CONTROL_CODE_ENABLE_PROVIDER,
1132+
levelToUse, mergedKeywords, 0, EnableProviderTimeoutMSec, parameters);
1133+
Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRFromWin32(enableHr));
1134+
11191135
fixed (byte* filterDataPtr = asArray)
11201136
{
11211137
if (asArray != null)
@@ -1125,9 +1141,10 @@ public void CaptureState(Guid providerGuid, ulong matchAnyKeywords = ulong.MaxVa
11251141
filter.Size = asArray.Length;
11261142
filter.Ptr = filterDataPtr;
11271143
}
1144+
11281145
int hr = TraceEventNativeMethods.EnableTraceEx2(
11291146
m_SessionHandle, providerGuid, TraceEventNativeMethods.EVENT_CONTROL_CODE_CAPTURE_STATE,
1130-
TraceEventLevel.Verbose, matchAnyKeywords, 0, EnableProviderTimeoutMSec, parameters);
1147+
TraceEventLevel.Verbose, mergedKeywords, 0, EnableProviderTimeoutMSec, parameters);
11311148
Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRFromWin32(hr));
11321149
}
11331150
}
@@ -2554,17 +2571,23 @@ private static unsafe Dictionary<Guid, ulong> GetEnabledProvidersForSession(ulon
25542571
for (int i = 0; &providerGuids[i] < bufferEnd; i++)
25552572
{
25562573
Guid* providerId = &providerGuids[i];
2557-
long? matchAnyKeyword = GetEnabledKeywordsForProviderAndSession(providerId, sessionId);
2558-
if (matchAnyKeyword != null)
2574+
EnabledProviderInfo? enabledInfo = GetEnabledInfoForProviderAndSession(providerId, sessionId);
2575+
if (enabledInfo != null)
25592576
{
2560-
ret.Add(*providerId, (ulong)matchAnyKeyword);
2577+
ret.Add(*providerId, enabledInfo.Value.MatchAnyKeywords);
25612578
}
25622579
}
25632580

25642581
return ret;
25652582
}
25662583

2567-
private static unsafe long? GetEnabledKeywordsForProviderAndSession(Guid *providerId, ulong sessionId)
2584+
private struct EnabledProviderInfo
2585+
{
2586+
public ulong MatchAnyKeywords;
2587+
public TraceEventLevel Level;
2588+
}
2589+
2590+
private static unsafe EnabledProviderInfo? GetEnabledInfoForProviderAndSession(Guid *providerId, ulong sessionId)
25682591
{
25692592
int buffSize = 256; // An initial guess that probably works most of the time.
25702593
byte* buffer;
@@ -2585,7 +2608,7 @@ private static unsafe Dictionary<Guid, ulong> GetEnabledProvidersForSession(ulon
25852608
}
25862609
}
25872610

2588-
long? matchAnyKeyword = null;
2611+
EnabledProviderInfo? result = null;
25892612

25902613
TraceEventNativeMethods.TRACE_GUID_INFO* guidInfo = (TraceEventNativeMethods.TRACE_GUID_INFO*)buffer;
25912614
byte *pCurrent = buffer + sizeof(TraceEventNativeMethods.TRACE_GUID_INFO);
@@ -2598,20 +2621,31 @@ private static unsafe Dictionary<Guid, ulong> GetEnabledProvidersForSession(ulon
25982621
TraceEventNativeMethods.TRACE_ENABLE_INFO* pEnableInfo = &((TraceEventNativeMethods.TRACE_ENABLE_INFO*)pCurrent)[j];
25992622
if (pEnableInfo->LoggerId == sessionId)
26002623
{
2601-
if (matchAnyKeyword == null)
2624+
if (result == null)
26022625
{
2603-
matchAnyKeyword = pEnableInfo->MatchAnyKeyword;
2626+
result = new EnabledProviderInfo
2627+
{
2628+
MatchAnyKeywords = (ulong)pEnableInfo->MatchAnyKeyword,
2629+
Level = (TraceEventLevel)pEnableInfo->Level
2630+
};
26042631
}
26052632
else
26062633
{
2607-
matchAnyKeyword |= pEnableInfo->MatchAnyKeyword;
2634+
var current = result.Value;
2635+
current.MatchAnyKeywords |= (ulong)pEnableInfo->MatchAnyKeyword;
2636+
// Use the higher (more verbose) level
2637+
if (pEnableInfo->Level > (byte)current.Level)
2638+
{
2639+
current.Level = (TraceEventLevel)pEnableInfo->Level;
2640+
}
2641+
result = current;
26082642
}
26092643
}
26102644
}
26112645
pCurrent += sizeof(TraceEventNativeMethods.TRACE_ENABLE_INFO) * pInstanceInfo->EnableCount;
26122646
}
26132647

2614-
return matchAnyKeyword;
2648+
return result;
26152649
}
26162650

26172651
private static unsafe void CopyStringToPtr(char* toPtr, string str)

0 commit comments

Comments
 (0)