// subclasses of EventProvider use when creating efficient (but unsafe) version of
// EventWrite. We do make it a nested type because we really don't expect anyone to use
// it except subclasses (and then only rarely).
+ [StructLayout(LayoutKind.Sequential)]
public struct EventData
{
internal unsafe ulong Ptr;
private static bool m_setInformationMissing;
- private IEventProvider m_eventProvider; // The interface that implements the specific logging mechanism functions.
+ internal IEventProvider m_eventProvider; // The interface that implements the specific logging mechanism functions.
UnsafeNativeMethods.ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function
private long m_regHandle; // Trace Registration Handle
private byte m_level; // Tracing Level
// </SecurityKernel>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
- internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, params object[] eventPayload)
+ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, params object[] eventPayload)
{
int status = 0;
userDataPtr[refObjPosition[7]].Ptr = (ulong)v7;
}
- status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
+ status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
}
}
else
}
}
- status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
+ status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
for (int i = 0; i < refObjIndex; ++i)
{
// <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" />
// </SecurityKernel>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
- internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
+ internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
{
if (childActivityID != null)
{
(EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop);
}
- int status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, dataCount, (EventData*)data);
+ int status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, dataCount, (EventData*)data);
if (status != 0)
{
status = m_eventProvider.EventWriteTransferWrapper(
m_regHandle,
ref eventDescriptor,
+ IntPtr.Zero,
activityID,
relatedActivityID,
dataCount,
unsafe int IEventProvider.EventWriteTransferWrapper(
long registrationHandle,
ref EventDescriptor eventDescriptor,
+ IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
int userDataCount,
ControlCode,
ref ActivityId);
}
+
+ // Define an EventPipeEvent handle.
+ unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
+ {
+ throw new System.NotSupportedException();
+ }
}
#elif !FEATURE_PERFTRACING
unsafe int IEventProvider.EventWriteTransferWrapper(
long registrationHandle,
ref EventDescriptor eventDescriptor,
+ IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
int userDataCount,
{
return 0;
}
+
+ // Define an EventPipeEvent handle.
+ unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
+ {
+ throw new System.NotSupportedException();
+ }
}
#endif
Initialize(eventSourceGuid, eventSourceName, traits);
}
+#if FEATURE_PERFTRACING
+ // Generate the serialized blobs that describe events for all strongly typed events (that is events that define strongly
+ // typed event methods. Dynamically defined events (that use Write) hare defined on the fly and are handled elsewhere.
+ private unsafe void DefineEventPipeEvents()
+ {
+ Debug.Assert(m_eventData != null);
+ Debug.Assert(m_provider != null);
+ int cnt = m_eventData.Length;
+ for (int i = 0; i < cnt; i++)
+ {
+ uint eventID = (uint)m_eventData[i].Descriptor.EventId;
+ if (eventID == 0)
+ continue;
+
+ string eventName = m_eventData[i].Name;
+ Int64 keywords = m_eventData[i].Descriptor.Keywords;
+ uint eventVersion = m_eventData[i].Descriptor.Version;
+ uint level = m_eventData[i].Descriptor.Level;
+
+ // evnetID : 4 bytes
+ // eventName : (eventName.Length + 1) * 2 bytes
+ // keywords : 8 bytes
+ // eventVersion : 4 bytes
+ // level : 4 bytes
+ // parameterCount : 4 bytes
+ uint metadataLength = 24 + ((uint)eventName.Length + 1) * 2;
+
+ // Increase the metadataLength for the types of all parameters.
+ metadataLength += (uint)m_eventData[i].Parameters.Length * 4;
+
+ // Increase the metadataLength for the names of all parameters.
+ foreach (var parameter in m_eventData[i].Parameters)
+ {
+ string parameterName = parameter.Name;
+ metadataLength = metadataLength + ((uint)parameterName.Length + 1) * 2;
+ }
+
+ byte[] metadata = new byte[metadataLength];
+
+ // Write metadata: evnetID, eventName, keywords, eventVersion, level, parameterCount, param1 type, param1 name...
+ fixed (byte *pMetadata = metadata)
+ {
+ uint offset = 0;
+ WriteToBuffer(pMetadata, metadataLength, ref offset, eventID);
+ fixed(char *pEventName = eventName)
+ {
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pEventName, ((uint)eventName.Length + 1) * 2);
+ }
+ WriteToBuffer(pMetadata, metadataLength, ref offset, keywords);
+ WriteToBuffer(pMetadata, metadataLength, ref offset, eventVersion);
+ WriteToBuffer(pMetadata, metadataLength, ref offset, level);
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)m_eventData[i].Parameters.Length);
+ foreach (var parameter in m_eventData[i].Parameters)
+ {
+ // Write parameter type.
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)Type.GetTypeCode(parameter.ParameterType));
+
+ // Write parameter name.
+ string parameterName = parameter.Name;
+ fixed (char *pParameterName = parameterName)
+ {
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pParameterName, ((uint)parameterName.Length + 1) * 2);
+ }
+ }
+ Debug.Assert(metadataLength == offset);
+ IntPtr eventHandle = m_provider.m_eventProvider.DefineEventHandle(eventID, eventName, keywords, eventVersion, level, pMetadata, metadataLength);
+ m_eventData[i].EventHandle = eventHandle;
+ }
+ }
+ }
+
+ // Copy src to buffer and modify the offset.
+ // Note: We know the buffer size ahead of time to make sure no buffer overflow.
+ private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, byte *src, uint srcLength)
+ {
+ Debug.Assert(bufferLength >= (offset + srcLength));
+ for (int i = 0; i < srcLength; i++)
+ {
+ *(byte *)(buffer + offset + i) = *(byte *)(src + i);
+ }
+ offset += srcLength;
+ }
+
+ // Copy uint value to buffer.
+ private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, uint value)
+ {
+ Debug.Assert(bufferLength >= (offset + 4));
+ *(uint *)(buffer + offset) = value;
+ offset += 4;
+ }
+
+ // Copy long value to buffer.
+ private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, long value)
+ {
+ Debug.Assert(bufferLength >= (offset + 8));
+ *(long *)(buffer + offset) = value;
+ offset += 8;
+ }
+#endif
+
internal virtual void GetMetadata(out Guid eventSourceGuid, out string eventSourceName, out EventMetadata[] eventData, out byte[] manifestBytes)
{
//
// by default the Descriptor.Keyword will have the perEventSourceSessionId bit
// mask set to 0x0f so, when all ETW sessions want the event we don't need to
// synthesize a new one
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
ThrowEventSourceException(m_eventData[eventId].Name);
}
else
m_eventData[eventId].Descriptor.Task,
unchecked((long)etwSessions.ToEventKeywords() | origKwd));
- if (!m_provider.WriteEvent(ref desc, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ if (!m_provider.WriteEvent(ref desc, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
ThrowEventSourceException(m_eventData[eventId].Name);
}
}
#else
if (!SelfDescribingEvents)
{
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
ThrowEventSourceException(m_eventData[eventId].Name);
}
else
}
#endif // PLATFORM_WINDOWS
#endif // FEATURE_MANAGED_ETW
-
Debug.Assert(!m_eventSourceEnabled); // We can't be enabled until we are completely initted.
// We are logically completely initialized at this point.
m_completelyInited = true;
// by default the Descriptor.Keyword will have the perEventSourceSessionId bit
// mask set to 0x0f so, when all ETW sessions want the event we don't need to
// synthesize a new one
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
ThrowEventSourceException(m_eventData[eventId].Name);
}
else
m_eventData[eventId].Descriptor.Task,
unchecked((long)etwSessions.ToEventKeywords() | origKwd));
- if (!m_provider.WriteEvent(ref desc, pActivityId, childActivityID, args))
+ if (!m_provider.WriteEvent(ref desc, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
ThrowEventSourceException(m_eventData[eventId].Name);
}
}
#else
if (!SelfDescribingEvents)
{
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
ThrowEventSourceException(m_eventData[eventId].Name);
}
else
data.Ptr = (ulong)msgStringPtr;
data.Size = (uint)(2 * (msgString.Length + 1));
data.Reserved = 0;
- m_provider.WriteEvent(ref descr, null, null, 1, (IntPtr)((void*)&data));
+ m_provider.WriteEvent(ref descr, m_eventData[0].EventHandle, null, null, 1, (IntPtr)((void*)&data));
}
}
}
partial struct EventMetadata
{
public EventDescriptor Descriptor;
+ public IntPtr EventHandle; // EventPipeEvent handle.
public EventTags Tags;
public bool EnabledForAnyListener; // true if any dispatcher has this event turned on
public bool EnabledForETW; // is this event on for the OS ETW data dispatcher?
dispatcher.m_EventEnabled = new bool[m_eventData.Length];
dispatcher = dispatcher.m_Next;
}
+#if FEATURE_PERFTRACING
+ // Initialize the EventPipe event handles.
+ DefineEventPipeEvents();
+#endif
}
if (s_currentPid == 0)
{
dataDescrs[1].Size = (uint)Math.Min(dataLeft, chunkSize);
if (m_provider != null)
{
- if (!m_provider.WriteEvent(ref manifestDescr, null, null, 2, (IntPtr)dataDescrs))
+ if (!m_provider.WriteEvent(ref manifestDescr, IntPtr.Zero, null, null, 2, (IntPtr)dataDescrs))
{
// Turns out that if users set the BufferSize to something less than 64K then WriteEvent
// can fail. If we get this failure on the first chunk try again with something smaller
throw new ArgumentException(msg, exception);
}
+#if FEATURE_PERFTRACING
+ return null;
+#else
return bNeedsManifest ? res : null;
+#endif
}
private static bool RemoveFirstArgIfRelatedActivityId(ref ParameterInfo[] args)
eventData[eventAttribute.EventId].Message = eventAttribute.Message;
eventData[eventAttribute.EventId].ActivityOptions = eventAttribute.ActivityOptions;
eventData[eventAttribute.EventId].HasRelatedActivityID = hasRelatedActivityID;
+ eventData[eventAttribute.EventId].EventHandle = IntPtr.Zero;
}
// Helper used by code:CreateManifestAndDescriptors that trims the m_eventData array to the correct
unsafe int EventWriteTransferWrapper(
long registrationHandle,
ref EventDescriptor eventDescriptor,
+ IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
int userDataCount,
// Get or set the per-thread activity ID.
int EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId);
+
+ // Define an EventPipeEvent handle.
+ unsafe IntPtr DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength);
}
}
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
- internal static extern IntPtr AddEvent(IntPtr provHandle, Int64 keywords, uint eventID, uint eventVersion, uint level, bool needStack);
+ internal static extern unsafe IntPtr DefineEvent(IntPtr provHandle, uint eventID, Int64 keywords, uint eventVersion, uint level, void *pMetadata, uint metadataLength);
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
- internal static extern unsafe void WriteEvent(IntPtr eventHandle, void* data, uint length);
+ internal static extern unsafe void WriteEvent(IntPtr eventHandle, uint eventID, void* pData, uint length);
}
}
using System.Runtime.InteropServices;
using System.Security;
using Microsoft.Win32;
+using System.Diagnostics;
+using System.Collections.Generic;
namespace System.Diagnostics.Tracing
{
unsafe int IEventProvider.EventWriteTransferWrapper(
long registrationHandle,
ref EventDescriptor eventDescriptor,
+ IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
int userDataCount,
EventProvider.EventData* userData)
{
+ uint eventID = (uint)eventDescriptor.EventId;
+ if(eventID != 0 && eventHandle != IntPtr.Zero)
+ {
+ if (userDataCount == 0)
+ {
+ EventPipeInternal.WriteEvent(eventHandle, eventID, null, 0);
+ return 0;
+ }
+
+ uint length = 0;
+ for (int i = 0; i < userDataCount; i++)
+ {
+ length += userData[i].Size;
+ }
+
+ byte[] data = new byte[length];
+ fixed (byte *pData = data)
+ {
+ uint offset = 0;
+ for (int i = 0; i < userDataCount; i++)
+ {
+ byte * singleUserDataPtr = (byte *)(userData[i].Ptr);
+ uint singleUserDataSize = userData[i].Size;
+ WriteToBuffer(pData, length, ref offset, singleUserDataPtr, singleUserDataSize);
+ }
+ EventPipeInternal.WriteEvent(eventHandle, eventID, pData, length);
+ }
+ }
return 0;
}
{
return 0;
}
+
+ // Define an EventPipeEvent handle.
+ unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
+ {
+ IntPtr eventHandlePtr = EventPipeInternal.DefineEvent(m_provHandle, eventID, keywords, eventVersion, level, pMetadata, metadataLength);
+ return eventHandlePtr;
+ }
+
+ // Copy src to buffer and modify the offset.
+ // Note: We know the buffer size ahead of time to make sure no buffer overflow.
+ private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, byte *src, uint srcLength)
+ {
+ Debug.Assert(bufferLength >= (offset + srcLength));
+ for (int i = 0; i < srcLength; i++)
+ {
+ *(byte *)(buffer + offset + i) = *(byte *)(src + i);
+ }
+ offset += srcLength;
+ }
}
}
taskName = eventNode.getAttribute('task')
initEvent = """ EventPipeEvent%s = EventPipeProvider%s->AddEvent(%s,%s,%s,%s);
-""" % (eventName, providerPrettyName, eventKeywordsMask, eventValue, eventVersion, eventLevel)
+""" % (eventName, providerPrettyName, eventValue, eventKeywordsMask, eventVersion, eventLevel)
WriteEventImpl.append(initEvent)
WriteEventImpl.append("}")
QCFuncElement("Enable", EventPipeInternal::Enable)
QCFuncElement("Disable", EventPipeInternal::Disable)
QCFuncElement("CreateProvider", EventPipeInternal::CreateProvider)
- QCFuncElement("AddEvent", EventPipeInternal::AddEvent)
+ QCFuncElement("DefineEvent", EventPipeInternal::DefineEvent)
QCFuncElement("DeleteProvider", EventPipeInternal::DeleteProvider)
QCFuncElement("WriteEvent", EventPipeInternal::WriteEvent)
FCFuncEnd()
return reinterpret_cast<INT_PTR>(pProvider);
}
-INT_PTR QCALLTYPE EventPipeInternal::AddEvent(
+INT_PTR QCALLTYPE EventPipeInternal::DefineEvent(
INT_PTR provHandle,
- __int64 keywords,
unsigned int eventID,
+ __int64 keywords,
unsigned int eventVersion,
unsigned int level,
- bool needStack)
+ void *pMetadata,
+ unsigned int metadataLength)
{
QCALL_CONTRACT;
+
+ EventPipeEvent *pEvent = NULL;
+
BEGIN_QCALL;
- // TODO
+ _ASSERTE(provHandle != NULL);
+ _ASSERTE(pMetadata != NULL);
+ EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider *>(provHandle);
+ pEvent = pProvider->AddEvent(eventID, keywords, eventVersion, (EventPipeEventLevel)level, (BYTE *)pMetadata, metadataLength);
+ _ASSERTE(pEvent != NULL);
END_QCALL;
- return 0;
+ return reinterpret_cast<INT_PTR>(pEvent);
}
void QCALLTYPE EventPipeInternal::DeleteProvider(
void QCALLTYPE EventPipeInternal::WriteEvent(
INT_PTR eventHandle,
+ unsigned int eventID,
void *pData,
unsigned int length)
{
QCALL_CONTRACT;
BEGIN_QCALL;
- // TODO
+ _ASSERTE(eventHandle != NULL);
+ EventPipeEvent *pEvent = reinterpret_cast<EventPipeEvent *>(eventHandle);
+ EventPipe::WriteEvent(*pEvent, (BYTE *)pData, length);
END_QCALL;
}
GUID providerID,
EventPipeCallback pCallbackFunc);
- static INT_PTR QCALLTYPE AddEvent(
+ static INT_PTR QCALLTYPE DefineEvent(
INT_PTR provHandle,
- __int64 keywords,
unsigned int eventID,
+ __int64 keywords,
unsigned int eventVersion,
unsigned int level,
- bool needStack);
+ void *pMetadata,
+ unsigned int metadataLength);
static void QCALLTYPE DeleteProvider(
INT_PTR provHandle);
static void QCALLTYPE WriteEvent(
INT_PTR eventHandle,
+ unsigned int eventID,
void *pData,
unsigned int length);
};
// Create the metadata event.
m_pMetadataEvent = m_pConfigProvider->AddEvent(
- 0, /* keywords */
0, /* eventID */
+ 0, /* keywords */
0, /* eventVersion */
EventPipeEventLevel::LogAlways,
false); /* needStack */
Enable(1 /* circularBufferSizeInMB */, rundownProviders, numRundownProviders);
}
-EventPipeEventInstance* EventPipeConfiguration::BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance, BYTE *pPayloadData, unsigned int payloadLength)
+EventPipeEventInstance* EventPipeConfiguration::BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance)
{
CONTRACTL
{
const GUID &providerID = sourceEvent.GetProvider()->GetProviderID();
unsigned int eventID = sourceEvent.GetEventID();
unsigned int eventVersion = sourceEvent.GetEventVersion();
+ BYTE *pPayloadData = sourceEvent.GetMetadata();
+ unsigned int payloadLength = sourceEvent.GetMetadataLength();
unsigned int instancePayloadSize = sizeof(providerID) + sizeof(eventID) + sizeof(eventVersion) + sizeof(payloadLength) + payloadLength;
// Allocate the payload.
if((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_PerformanceTracing) & 1) == 1)
{
m_pCatchAllProvider = new EventPipeEnabledProvider();
- m_pCatchAllProvider->Set(NULL, 0xFFFFFFFF, EventPipeEventLevel::Verbose);
+ m_pCatchAllProvider->Set(NULL, 0xFFFFFFFFFFFFFFFF, EventPipeEventLevel::Verbose);
return;
}
void EnableRundown();
// Get the event used to write metadata to the event stream.
- EventPipeEventInstance* BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance, BYTE *pPayloadData = NULL, unsigned int payloadLength = 0);
+ EventPipeEventInstance* BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance);
private:
#ifdef FEATURE_PERFTRACING
-EventPipeEvent::EventPipeEvent(EventPipeProvider &provider, INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack)
+EventPipeEvent::EventPipeEvent(EventPipeProvider &provider, INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata, unsigned int metadataLength)
{
CONTRACTL
{
m_level = level;
m_needStack = needStack;
m_enabled = false;
+ if (pMetadata != NULL)
+ {
+ m_pMetadata = new BYTE[metadataLength];
+ memcpy(m_pMetadata, pMetadata, metadataLength);
+ m_metadataLength = metadataLength;
+ }
+ else
+ {
+ m_pMetadata = NULL;
+ m_metadataLength = 0;
+ }
+}
+
+EventPipeEvent::~EventPipeEvent()
+{
+ if (m_pMetadata != NULL)
+ {
+ delete[] m_pMetadata;
+ m_pMetadata = NULL;
+ }
}
EventPipeProvider* EventPipeEvent::GetProvider() const
return m_enabled;
}
+BYTE *EventPipeEvent::GetMetadata() const
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return m_pMetadata;
+}
+
+unsigned int EventPipeEvent::GetMetadataLength() const
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return m_metadataLength;
+}
+
void EventPipeEvent::RefreshState()
{
LIMITED_METHOD_CONTRACT;
// True if the event is current enabled.
Volatile<bool> m_enabled;
+ // Metadata
+ BYTE *m_pMetadata;
+
+ // Metadata length;
+ unsigned int m_metadataLength;
+
// Refreshes the runtime state for this event.
// Called by EventPipeProvider when the provider configuration changes.
void RefreshState();
// Only EventPipeProvider can create events.
// The provider is responsible for allocating and freeing events.
- EventPipeEvent(EventPipeProvider &provider, INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack);
+ EventPipeEvent(EventPipeProvider &provider, INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata = NULL, unsigned int metadataLength = 0);
-public:
+ public:
+ ~EventPipeEvent();
// Get the provider associated with this event.
EventPipeProvider* GetProvider() const;
// True if the event is currently enabled.
bool IsEnabled() const;
+
+ // Get metadata
+ BYTE *GetMetadata() const;
+
+ // Get metadata length
+ unsigned int GetMetadataLength() const;
};
#endif // FEATURE_PERFTRACING
InvokeCallback();
}
-EventPipeEvent* EventPipeProvider::AddEvent(INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level)
+EventPipeEvent* EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, BYTE *pMetadata, unsigned int metadataLength)
{
CONTRACTL
{
}
CONTRACTL_END;
- return AddEvent(keywords, eventID, eventVersion, level, true /* needStack */);
+ return AddEvent(eventID, keywords, eventVersion, level, true /* needStack */, pMetadata, metadataLength);
}
-EventPipeEvent* EventPipeProvider::AddEvent(INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack)
+EventPipeEvent* EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata, unsigned int metadataLength)
{
CONTRACTL
{
eventID,
eventVersion,
level,
- needStack);
+ needStack,
+ pMetadata,
+ metadataLength);
// Add it to the list of events.
AddEvent(*pEvent);
bool EventEnabled(INT64 keywords, EventPipeEventLevel eventLevel) const;
// Create a new event.
- EventPipeEvent* AddEvent(INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level);
+ EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, BYTE *pMetadata = NULL, unsigned int metadataLength = 0);
-private:
+ private:
// Create a new event, but allow needStack to be specified.
// In general, we want stack walking to be controlled by the consumer and not the producer of events.
// However, there are a couple of cases that we know we don't want to do a stackwalk that would affect performance significantly:
// 1. Sample profiler events: The sample profiler already does a stack walk of the target thread. Doing one of the sampler thread is a waste.
// 2. Metadata events: These aren't as painful but because we have to keep this functionality around, might as well use it.
- EventPipeEvent* AddEvent(INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack);
+ EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata = NULL, unsigned int metadataLength = 0);
// Add an event to the provider.
void AddEvent(EventPipeEvent &event);
{
s_pEventPipeProvider = new EventPipeProvider(s_providerID);
s_pThreadTimeEvent = s_pEventPipeProvider->AddEvent(
- 0, /* keywords */
0, /* eventID */
+ 0, /* keywords */
0, /* eventVersion */
EventPipeEventLevel::Informational,
false /* NeedStack */);