Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 016f7cc

Browse files
authored
Implement Activity ID / Related Activity ID for EventSources Writing to EventPipe (#11916)
* Implement thread-local storage of activity ids. * Plumb the activity id and related activity id into the trace file.
1 parent 007fa10 commit 016f7cc

12 files changed

+98
-34
lines changed

src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,6 @@ internal static class EventPipeInternal
170170

171171
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
172172
[SuppressUnmanagedCodeSecurity]
173-
internal static extern unsafe void WriteEvent(IntPtr eventHandle, uint eventID, void* pData, uint length);
173+
internal static extern unsafe void WriteEvent(IntPtr eventHandle, uint eventID, void* pData, uint length, Guid* activityId, Guid* relatedActivityId);
174174
}
175175
}

src/mscorlib/src/System/Diagnostics/Eventing/EventPipeEventProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ unsafe int IEventProvider.EventWriteTransferWrapper(
6262
{
6363
if (userDataCount == 0)
6464
{
65-
EventPipeInternal.WriteEvent(eventHandle, eventID, null, 0);
65+
EventPipeInternal.WriteEvent(eventHandle, eventID, null, 0, activityId, relatedActivityId);
6666
return 0;
6767
}
6868

@@ -82,7 +82,7 @@ unsafe int IEventProvider.EventWriteTransferWrapper(
8282
uint singleUserDataSize = userData[i].Size;
8383
WriteToBuffer(pData, length, ref offset, singleUserDataPtr, singleUserDataSize);
8484
}
85-
EventPipeInternal.WriteEvent(eventHandle, eventID, pData, length);
85+
EventPipeInternal.WriteEvent(eventHandle, eventID, pData, length, activityId, relatedActivityId);
8686
}
8787
}
8888
return 0;

src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ namespace System.Diagnostics.Tracing
1111
{
1212
public partial class EventSource
1313
{
14+
#if FEATURE_MANAGED_ETW && FEATURE_PERFTRACING
15+
// For non-Windows, we use a thread-local variable to hold the activity ID.
16+
// On Windows, ETW has it's own thread-local variable and we participate in its use.
17+
[ThreadStatic]
18+
private static Guid s_currentThreadActivityId;
19+
#endif // FEATURE_MANAGED_ETW && FEATURE_PERFTRACING
20+
1421
// ActivityID support (see also WriteEventWithRelatedActivityIdCore)
1522
/// <summary>
1623
/// When a thread starts work that is on behalf of 'something else' (typically another
@@ -33,16 +40,20 @@ public static void SetCurrentThreadActivityId(Guid activityId)
3340
{
3441
if (TplEtwProvider.Log != null)
3542
TplEtwProvider.Log.SetActivityId(activityId);
36-
#if FEATURE_MANAGED_ETW && PLATFORM_WINDOWS
43+
#if FEATURE_MANAGED_ETW
3744
#if FEATURE_ACTIVITYSAMPLING
3845
Guid newId = activityId;
3946
#endif // FEATURE_ACTIVITYSAMPLING
4047
// We ignore errors to keep with the convention that EventSources do not throw errors.
4148
// Note we can't access m_throwOnWrites because this is a static method.
4249

50+
#if FEATURE_PERFTRACING
51+
s_currentThreadActivityId = activityId;
52+
#elif PLATFORM_WINDOWS
4353
if (UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
4454
UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
4555
ref activityId) == 0)
56+
#endif // FEATURE_PERFTRACING
4657
{
4758
#if FEATURE_ACTIVITYSAMPLING
4859
var activityDying = s_activityDying;
@@ -57,7 +68,7 @@ public static void SetCurrentThreadActivityId(Guid activityId)
5768
}
5869
#endif // FEATURE_ACTIVITYSAMPLING
5970
}
60-
#endif // FEATURE_MANAGED_ETW && PLATFORM_WINDOWS
71+
#endif // FEATURE_MANAGED_ETW
6172
}
6273

6374
/// <summary>
@@ -82,14 +93,19 @@ public static void SetCurrentThreadActivityId(Guid activityId)
8293
public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue)
8394
{
8495
oldActivityThatWillContinue = activityId;
85-
#if FEATURE_MANAGED_ETW && PLATFORM_WINDOWS
96+
#if FEATURE_MANAGED_ETW
8697
// We ignore errors to keep with the convention that EventSources do not throw errors.
8798
// Note we can't access m_throwOnWrites because this is a static method.
8899

100+
#if FEATURE_PERFTRACING
101+
oldActivityThatWillContinue = s_currentThreadActivityId;
102+
s_currentThreadActivityId = activityId;
103+
#elif PLATFORM_WINDOWS
89104
UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
90105
UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
91106
ref oldActivityThatWillContinue);
92-
#endif // FEATURE_MANAGED_ETW && PLATFORM_WINDOWS
107+
#endif // FEATURE_PERFTRACING
108+
#endif // FEATURE_MANAGED_ETW
93109

94110
// We don't call the activityDying callback here because the caller has declared that
95111
// it is not dying.
@@ -107,11 +123,15 @@ public static Guid CurrentThreadActivityId
107123
// We ignore errors to keep with the convention that EventSources do not throw
108124
// errors. Note we can't access m_throwOnWrites because this is a static method.
109125
Guid retVal = new Guid();
110-
#if FEATURE_MANAGED_ETW && PLATFORM_WINDOWS
126+
#if FEATURE_MANAGED_ETW
127+
#if FEATURE_PERFTRACING
128+
retVal = s_currentThreadActivityId;
129+
#elif PLATFORM_WINDOWS
111130
UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
112131
UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID,
113132
ref retVal);
114-
#endif // FEATURE_MANAGED_ETW && PLATFORM_WINDOWS
133+
#endif // FEATURE_PERFTRACING
134+
#endif // FEATURE_MANAGED_ETW
115135
return retVal;
116136
}
117137
}

src/vm/eventpipe.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ void EventPipe::DeleteProvider(EventPipeProvider *pProvider)
282282
}
283283
}
284284

285-
void EventPipe::WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length)
285+
void EventPipe::WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length, LPCGUID pActivityId, LPCGUID pRelatedActivityId)
286286
{
287287
CONTRACTL
288288
{
@@ -309,7 +309,7 @@ void EventPipe::WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int leng
309309

310310
if(!s_pConfig->RundownEnabled() && s_pBufferManager != NULL)
311311
{
312-
if(!s_pBufferManager->WriteEvent(pThread, event, pData, length))
312+
if(!s_pBufferManager->WriteEvent(pThread, event, pData, length, pActivityId, pRelatedActivityId))
313313
{
314314
// This is used in DEBUG to make sure that we don't log an event synchronously that we didn't log to the buffer.
315315
return;
@@ -323,7 +323,9 @@ void EventPipe::WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int leng
323323
event,
324324
pThread->GetOSThreadId(),
325325
pData,
326-
length);
326+
length,
327+
pActivityId,
328+
pRelatedActivityId);
327329

328330
if(s_pFile != NULL)
329331
{
@@ -340,7 +342,9 @@ void EventPipe::WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int leng
340342
event,
341343
pThread->GetOSThreadId(),
342344
pData,
343-
length);
345+
length,
346+
pActivityId,
347+
pRelatedActivityId);
344348

345349
// Write to the EventPipeFile if it exists.
346350
if(s_pSyncFile != NULL)
@@ -372,7 +376,7 @@ void EventPipe::WriteSampleProfileEvent(Thread *pSamplingThread, EventPipeEvent
372376
{
373377
// Specify the sampling thread as the "current thread", so that we select the right buffer.
374378
// Specify the target thread so that the event gets properly attributed.
375-
if(!s_pBufferManager->WriteEvent(pSamplingThread, *pEvent, pData, length, pTargetThread, &stackContents))
379+
if(!s_pBufferManager->WriteEvent(pSamplingThread, *pEvent, pData, length, NULL /* pActivityId */, NULL /* pRelatedActivityId */, pTargetThread, &stackContents))
376380
{
377381
// This is used in DEBUG to make sure that we don't log an event synchronously that we didn't log to the buffer.
378382
return;
@@ -577,14 +581,16 @@ void QCALLTYPE EventPipeInternal::WriteEvent(
577581
INT_PTR eventHandle,
578582
unsigned int eventID,
579583
void *pData,
580-
unsigned int length)
584+
unsigned int length,
585+
LPCGUID pActivityId,
586+
LPCGUID pRelatedActivityId)
581587
{
582588
QCALL_CONTRACT;
583589
BEGIN_QCALL;
584590

585591
_ASSERTE(eventHandle != NULL);
586592
EventPipeEvent *pEvent = reinterpret_cast<EventPipeEvent *>(eventHandle);
587-
EventPipe::WriteEvent(*pEvent, (BYTE *)pData, length);
593+
EventPipe::WriteEvent(*pEvent, (BYTE *)pData, length, pActivityId, pRelatedActivityId);
588594

589595
END_QCALL;
590596
}

src/vm/eventpipe.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ class EventPipe
188188

189189
// Write out an event.
190190
// Data is written as a serialized blob matching the ETW serialization conventions.
191-
static void WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length);
191+
static void WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length, LPCGUID pActivityId = NULL, LPCGUID pRelatedActivityId = NULL);
192192

193193
// Write out a sample profile event.
194194
static void WriteSampleProfileEvent(Thread *pSamplingThread, EventPipeEvent *pEvent, Thread *pTargetThread, StackContents &stackContents, BYTE *pData = NULL, unsigned int length = 0);
@@ -305,7 +305,8 @@ class EventPipeInternal
305305
INT_PTR eventHandle,
306306
unsigned int eventID,
307307
void *pData,
308-
unsigned int length);
308+
unsigned int length,
309+
LPCGUID pActivityId, LPCGUID pRelatedActivityId);
309310
};
310311

311312
#endif // FEATURE_PERFTRACING

src/vm/eventpipebuffer.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ EventPipeBuffer::~EventPipeBuffer()
4646
}
4747
}
4848

49-
bool EventPipeBuffer::WriteEvent(Thread *pThread, EventPipeEvent &event, BYTE *pData, unsigned int dataLength, StackContents *pStack)
49+
bool EventPipeBuffer::WriteEvent(Thread *pThread, EventPipeEvent &event, BYTE *pData, unsigned int dataLength, LPCGUID pActivityId, LPCGUID pRelatedActivityId, StackContents *pStack)
5050
{
5151
CONTRACTL
5252
{
@@ -77,7 +77,9 @@ bool EventPipeBuffer::WriteEvent(Thread *pThread, EventPipeEvent &event, BYTE *p
7777
event,
7878
pThread->GetOSThreadId(),
7979
pDataDest,
80-
dataLength);
80+
dataLength,
81+
pActivityId,
82+
pRelatedActivityId);
8183

8284
// Copy the stack if a separate stack trace was provided.
8385
if(pStack != NULL)

src/vm/eventpipebuffer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class EventPipeBuffer
8181
// Returns:
8282
// - true: The write succeeded.
8383
// - false: The write failed. In this case, the buffer should be considered full.
84-
bool WriteEvent(Thread *pThread, EventPipeEvent &event, BYTE *pData, unsigned int dataLength, StackContents *pStack = NULL);
84+
bool WriteEvent(Thread *pThread, EventPipeEvent &event, BYTE *pData, unsigned int dataLength, LPCGUID pActivityId, LPCGUID pRelatedActivityId, StackContents *pStack = NULL);
8585

8686
// Get the timestamp of the most recent event in the buffer.
8787
LARGE_INTEGER GetMostRecentTimeStamp() const;

src/vm/eventpipebuffermanager.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ void EventPipeBufferManager::DeAllocateBuffer(EventPipeBuffer *pBuffer)
217217
}
218218
}
219219

220-
bool EventPipeBufferManager::WriteEvent(Thread *pThread, EventPipeEvent &event, BYTE *pData, unsigned int length, Thread *pEventThread, StackContents *pStack)
220+
bool EventPipeBufferManager::WriteEvent(Thread *pThread, EventPipeEvent &event, BYTE *pData, unsigned int length, LPCGUID pActivityId, LPCGUID pRelatedActivityId, Thread *pEventThread, StackContents *pStack)
221221
{
222222
CONTRACTL
223223
{
@@ -276,7 +276,7 @@ bool EventPipeBufferManager::WriteEvent(Thread *pThread, EventPipeEvent &event,
276276
else
277277
{
278278
// Attempt to write the event to the buffer. If this fails, we should allocate a new buffer.
279-
allocNewBuffer = !pBuffer->WriteEvent(pEventThread, event, pData, length, pStack);
279+
allocNewBuffer = !pBuffer->WriteEvent(pEventThread, event, pData, length, pActivityId, pRelatedActivityId, pStack);
280280
}
281281
}
282282

@@ -294,7 +294,7 @@ bool EventPipeBufferManager::WriteEvent(Thread *pThread, EventPipeEvent &event,
294294
// This is the second time if this thread did have one or more buffers, but they were full.
295295
if(allocNewBuffer && pBuffer != NULL)
296296
{
297-
allocNewBuffer = !pBuffer->WriteEvent(pEventThread, event, pData, length, pStack);
297+
allocNewBuffer = !pBuffer->WriteEvent(pEventThread, event, pData, length, pActivityId, pRelatedActivityId, pStack);
298298
}
299299

300300
// Mark that the thread is no longer writing an event.

src/vm/eventpipebuffermanager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class EventPipeBufferManager
6767
// This is because the thread that writes the events is not the same as the "event thread".
6868
// An optional stack trace can be provided for sample profiler events.
6969
// Otherwise, if a stack trace is needed, one will be automatically collected.
70-
bool WriteEvent(Thread *pThread, EventPipeEvent &event, BYTE *pData, unsigned int length, Thread *pEventThread = NULL, StackContents *pStack = NULL);
70+
bool WriteEvent(Thread *pThread, EventPipeEvent &event, BYTE *pData, unsigned int length, LPCGUID pActivityId, LPCGUID pRelatedActivityId, Thread *pEventThread = NULL, StackContents *pStack = NULL);
7171

7272
// Write the contents of the managed buffers to the specified file.
7373
// The stopTimeStamp is used to determine when tracing was stopped to ensure that we

src/vm/eventpipeconfiguration.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,9 @@ EventPipeEventInstance* EventPipeConfiguration::BuildEventMetadataEvent(EventPip
370370
*m_pMetadataEvent,
371371
GetCurrentThreadId(),
372372
pInstancePayload,
373-
instancePayloadSize);
373+
instancePayloadSize,
374+
NULL /* pActivityId */,
375+
NULL /* pRelatedActivityId */);
374376

375377
// Set the timestamp to match the source event, because the metadata event
376378
// will be emitted right before the source event.

0 commit comments

Comments
 (0)