private unsafe void WriteMultiMergeInner( string eventName, ref EventSourceOptions options, TraceLoggingEventTypes eventTypes, Guid *activityID, Guid *childActivityID, params object[] values) { int identity = 0; byte level = (options.valuesSet & EventSourceOptions.levelSet) != 0 ? options.level : eventTypes.level; byte opcode = (options.valuesSet & EventSourceOptions.opcodeSet) != 0 ? options.opcode : eventTypes.opcode; EventTags tags = (options.valuesSet & EventSourceOptions.tagsSet) != 0 ? options.tags : eventTypes.Tags; EventKeywords keywords = (options.valuesSet & EventSourceOptions.keywordsSet) != 0 ? options.keywords : eventTypes.keywords; var nameInfo = eventTypes.GetNameInfo(eventName ?? eventTypes.Name, tags); if (nameInfo == null) { return; } identity = nameInfo.identity; EventDescriptor descriptor = new EventDescriptor(identity, level, opcode, (long)keywords); var pinCount = eventTypes.pinCount; var scratch = stackalloc byte[eventTypes.scratchSize]; var descriptors = stackalloc EventData[eventTypes.dataCount + 3]; var pins = stackalloc GCHandle[pinCount]; fixed(byte * pMetadata0 = this.providerMetadata, pMetadata1 = nameInfo.nameMetadata, pMetadata2 = eventTypes.typeMetadata) { descriptors[0].SetMetadata(pMetadata0, this.providerMetadata.Length, 2); descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1); descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1); #if !ES_BUILD_PCL System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); #endif try { DataCollector.ThreadInstance.Enable( scratch, eventTypes.scratchSize, descriptors + 3, eventTypes.dataCount, pins, pinCount); for (int i = 0; i < eventTypes.typeInfos.Length; i++) { eventTypes.typeInfos[i].WriteObjectData(TraceLoggingDataCollector.Instance, values[i]); } this.WriteEventRaw( ref descriptor, activityID, childActivityID, (int)(DataCollector.ThreadInstance.Finish() - descriptors), (IntPtr)descriptors); } finally { this.WriteCleanup(pins, pinCount); } } }
/// <summary> /// Writes an extended event, where the values of the event have already /// been serialized in "data". /// </summary> /// <param name="eventName"> /// The name for the event. If null, the name from eventTypes is used. /// (Note that providing the event name via the name parameter is slightly /// less efficient than using the name from eventTypes.) /// </param> /// <param name="options"> /// Optional overrides for the event, such as the level, keyword, opcode, /// activityId, and relatedActivityId. Any settings not specified by options /// are obtained from eventTypes. /// </param> /// <param name="eventTypes"> /// Information about the event and the types of the values in the event. /// Must not be null. Note that the eventTypes object should be created once and /// saved. It should not be recreated for each event. /// </param> /// <param name="activityID"> /// A pointer to the activity ID GUID to log /// </param> /// <param name="childActivityID"> /// A pointer to the child activity ID to log (can be null) /// </param> /// <param name="data"> /// The previously serialized values to include in the event. Must not be null. /// The number and types of the values must match the number and types of the /// fields described by the eventTypes parameter. /// </param> internal unsafe void WriteMultiMerge( string eventName, ref EventSourceOptions options, TraceLoggingEventTypes eventTypes, Guid *activityID, Guid *childActivityID, EventData *data) { #if FEATURE_MANAGED_ETW if (!this.IsEnabled()) { return; } fixed(EventSourceOptions *pOptions = &options) { EventDescriptor descriptor; var nameInfo = this.UpdateDescriptor(eventName, eventTypes, ref options, out descriptor); if (nameInfo == null) { return; } // We make a descriptor for each EventData, and because we morph strings to counted strings // we may have 2 for each arg, so we allocate enough for this. var descriptors = stackalloc EventData[eventTypes.dataCount + eventTypes.typeInfos.Length * 2 + 3]; fixed(byte * pMetadata0 = this.providerMetadata, pMetadata1 = nameInfo.nameMetadata, pMetadata2 = eventTypes.typeMetadata) { descriptors[0].SetMetadata(pMetadata0, this.providerMetadata.Length, 2); descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1); descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1); int numDescrs = 3; for (int i = 0; i < eventTypes.typeInfos.Length; i++) { // Until M3, we need to morph strings to a counted representation // When TDH supports null terminated strings, we can remove this. if (eventTypes.typeInfos[i].DataType == typeof(string)) { // Write out the size of the string descriptors[numDescrs].m_Ptr = (long)&descriptors[numDescrs + 1].m_Size; descriptors[numDescrs].m_Size = 2; numDescrs++; descriptors[numDescrs].m_Ptr = data[i].m_Ptr; descriptors[numDescrs].m_Size = data[i].m_Size - 2; // Remove the null terminator numDescrs++; } else { descriptors[numDescrs].m_Ptr = data[i].m_Ptr; descriptors[numDescrs].m_Size = data[i].m_Size; // old conventions for bool is 4 bytes, but meta-data assumes 1. if (data[i].m_Size == 4 && eventTypes.typeInfos[i].DataType == typeof(bool)) { descriptors[numDescrs].m_Size = 1; } numDescrs++; } } this.WriteEventRaw( eventName, ref descriptor, activityID, childActivityID, numDescrs, (IntPtr)descriptors); } } #endif // FEATURE_MANAGED_ETW }
private unsafe void WriteImpl( string eventName, ref EventSourceOptions options, object data, Guid *pActivityId, Guid *pRelatedActivityId, TraceLoggingEventTypes eventTypes) { try { fixed(EventSourceOptions *pOptions = &options) { EventDescriptor descriptor; options.Opcode = options.IsOpcodeSet ? options.Opcode : GetOpcodeWithDefault(options.Opcode, eventName); var nameInfo = this.UpdateDescriptor(eventName, eventTypes, ref options, out descriptor); if (nameInfo == null) { return; } #if FEATURE_MANAGED_ETW var pinCount = eventTypes.pinCount; var scratch = stackalloc byte[eventTypes.scratchSize]; var descriptors = stackalloc EventData[eventTypes.dataCount + 3]; var pins = stackalloc GCHandle[pinCount]; fixed(byte * pMetadata0 = this.providerMetadata, pMetadata1 = nameInfo.nameMetadata, pMetadata2 = eventTypes.typeMetadata) { descriptors[0].SetMetadata(pMetadata0, this.providerMetadata.Length, 2); descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1); descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1); #endif // FEATURE_MANAGED_ETW #if (!ES_BUILD_PCL && !ES_BUILD_PN) System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); #endif EventOpcode opcode = (EventOpcode)descriptor.Opcode; Guid activityId = Guid.Empty; Guid relatedActivityId = Guid.Empty; if (pActivityId == null && pRelatedActivityId == null && ((options.ActivityOptions & EventActivityOptions.Disable) == 0)) { if (opcode == EventOpcode.Start) { m_activityTracker.OnStart(m_name, eventName, 0, ref activityId, ref relatedActivityId, options.ActivityOptions); } else if (opcode == EventOpcode.Stop) { m_activityTracker.OnStop(m_name, eventName, 0, ref activityId); } if (activityId != Guid.Empty) { pActivityId = &activityId; } if (relatedActivityId != Guid.Empty) { pRelatedActivityId = &relatedActivityId; } } try { #if FEATURE_MANAGED_ETW DataCollector.ThreadInstance.Enable( scratch, eventTypes.scratchSize, descriptors + 3, eventTypes.dataCount, pins, pinCount); var info = eventTypes.typeInfos[0]; info.WriteData(TraceLoggingDataCollector.Instance, info.PropertyValueFactory(data)); this.WriteEventRaw( eventName, ref descriptor, pActivityId, pRelatedActivityId, (int)(DataCollector.ThreadInstance.Finish() - descriptors), (IntPtr)descriptors); #endif // FEATURE_MANAGED_ETW // TODO enable filtering for listeners. if (m_Dispatchers != null) { var eventData = (EventPayload)(eventTypes.typeInfos[0].GetData(data)); WriteToAllListeners(eventName, ref descriptor, nameInfo.tags, pActivityId, eventData); } } catch (Exception ex) { if (ex is EventSourceException) { throw; } else { ThrowEventSourceException(eventName, ex); } } #if FEATURE_MANAGED_ETW finally { this.WriteCleanup(pins, pinCount); } } #endif // FEATURE_MANAGED_ETW } } catch (Exception ex) { if (ex is EventSourceException) { throw; } else { ThrowEventSourceException(eventName, ex); } } }
public IntPtr GetOrCreateEventHandle(EventProvider provider, TraceLoggingEventHandleTable eventHandleTable, EventDescriptor descriptor, TraceLoggingEventTypes eventTypes) { IntPtr eventHandle; if ((eventHandle = eventHandleTable[descriptor.EventId]) == IntPtr.Zero) { lock (eventHandleTable) { if ((eventHandle = eventHandleTable[descriptor.EventId]) == IntPtr.Zero) { byte[]? metadataBlob = EventPipeMetadataGenerator.Instance.GenerateEventMetadata( descriptor.EventId, name, (EventKeywords)descriptor.Keywords, (EventLevel)descriptor.Level, descriptor.Version, eventTypes); uint metadataLength = (metadataBlob != null) ? (uint)metadataBlob.Length : 0; unsafe { fixed(byte *pMetadataBlob = metadataBlob) { // Define the event. eventHandle = provider.m_eventProvider.DefineEventHandle( (uint)descriptor.EventId, name, descriptor.Keywords, descriptor.Version, descriptor.Level, pMetadataBlob, metadataLength); } } // Cache the event handle. eventHandleTable.SetEventHandle(descriptor.EventId, eventHandle); } } } return(eventHandle); }
public IntPtr GetOrCreateEventHandle(EventProvider provider, EventDescriptor descriptor, TraceLoggingEventTypes eventTypes) { if (eventHandle == IntPtr.Zero) { lock (eventHandleCreationLock) { if (eventHandle == IntPtr.Zero) { byte[] metadataBlob = EventPipeMetadataGenerator.Instance.GenerateEventMetadata( descriptor.EventId, name, (EventKeywords)descriptor.Keywords, (EventLevel)descriptor.Level, descriptor.Version, eventTypes); unsafe { fixed(byte *pMetadataBlob = metadataBlob) { // Define the event. eventHandle = provider.m_eventProvider.DefineEventHandle( (uint)descriptor.EventId, name, descriptor.Keywords, descriptor.Version, descriptor.Level, pMetadataBlob, (uint)metadataBlob.Length); } } } } } return(eventHandle); }
/// <summary> /// Writes an extended event, where the values of the event have already /// been serialized in "data". /// </summary> /// <param name="eventName"> /// The name for the event. If null, the name from eventTypes is used. /// (Note that providing the event name via the name parameter is slightly /// less efficient than using the name from eventTypes.) /// </param> /// <param name="options"> /// Optional overrides for the event, such as the level, keyword, opcode, /// activityId, and relatedActivityId. Any settings not specified by options /// are obtained from eventTypes. /// </param> /// <param name="eventTypes"> /// Information about the event and the types of the values in the event. /// Must not be null. Note that the eventTypes object should be created once and /// saved. It should not be recreated for each event. /// </param> /// <param name="activityID"> /// A pointer to the activity ID GUID to log /// </param> /// <param name="childActivityID"> /// A pointer to the child activity ID to log (can be null) /// </param> /// <param name="data"> /// The previously serialized values to include in the event. Must not be null. /// The number and types of the values must match the number and types of the /// fields described by the eventTypes parameter. /// </param> internal unsafe void WriteMultiMerge( string eventName, ref EventSourceOptions options, TraceLoggingEventTypes eventTypes, Guid *activityID, Guid *childActivityID, EventData *data) { #if FEATURE_MANAGED_ETW if (!this.IsEnabled()) { return; } fixed(EventSourceOptions *pOptions = &options) { EventDescriptor descriptor; var nameInfo = this.UpdateDescriptor(eventName, eventTypes, ref options, out descriptor); if (nameInfo == null) { return; } #if FEATURE_PERFTRACING IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleTable, descriptor, eventTypes); Debug.Assert(eventHandle != IntPtr.Zero); #else IntPtr eventHandle = IntPtr.Zero; #endif // We make a descriptor for each EventData, and because we morph strings to counted strings // we may have 2 for each arg, so we allocate enough for this. var descriptorsLength = eventTypes.dataCount + eventTypes.typeInfos.Length * 2 + 3; var descriptors = stackalloc EventData[descriptorsLength]; for (int i = 0; i < descriptorsLength; i++) { descriptors[i] = default; fixed(byte * pMetadata0 = this.providerMetadata, pMetadata1 = nameInfo.nameMetadata, pMetadata2 = eventTypes.typeMetadata) { descriptors[0].SetMetadata(pMetadata0, this.providerMetadata.Length, 2); descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1); descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1); int numDescrs = 3; for (int i = 0; i < eventTypes.typeInfos.Length; i++) { descriptors[numDescrs].m_Ptr = data[i].m_Ptr; descriptors[numDescrs].m_Size = data[i].m_Size; // old conventions for bool is 4 bytes, but meta-data assumes 1. if (data[i].m_Size == 4 && eventTypes.typeInfos[i].DataType == typeof(bool)) { descriptors[numDescrs].m_Size = 1; } numDescrs++; } this.WriteEventRaw( eventName, ref descriptor, eventHandle, activityID, childActivityID, numDescrs, (IntPtr)descriptors); } } #endif // FEATURE_MANAGED_ETW }
/// <summary> /// Writes an extended event, where the values of the event are the /// combined properties of any number of values. This method is /// intended for use in advanced logging scenarios that support a /// dynamic set of event context providers. /// Attention: This API does not check whether the event is enabled or not. /// Please use WriteMultiMerge to avoid spending CPU cycles for events that are /// not enabled. /// </summary> /// <param name="eventName"> /// The name for the event. If null, the name from eventTypes is used. /// (Note that providing the event name via the name parameter is slightly /// less efficient than using the name from eventTypes.) /// </param> /// <param name="options"> /// Optional overrides for the event, such as the level, keyword, opcode, /// activityId, and relatedActivityId. Any settings not specified by options /// are obtained from eventTypes. /// </param> /// <param name="eventTypes"> /// Information about the event and the types of the values in the event. /// Must not be null. Note that the eventTypes object should be created once and /// saved. It should not be recreated for each event. /// </param> /// <param name="activityID"> /// A pointer to the activity ID GUID to log /// </param> /// <param name="childActivityID"> /// A pointer to the child activity ID to log (can be null) /// </param> /// <param name="values"> /// The values to include in the event. Must not be null. The number and types of /// the values must match the number and types of the fields described by the /// eventTypes parameter. /// </param> private unsafe void WriteMultiMergeInner( string eventName, ref EventSourceOptions options, TraceLoggingEventTypes eventTypes, Guid *activityID, Guid *childActivityID, params object[] values) { #if FEATURE_MANAGED_ETW int identity = 0; byte level = (options.valuesSet & EventSourceOptions.levelSet) != 0 ? options.level : eventTypes.level; byte opcode = (options.valuesSet & EventSourceOptions.opcodeSet) != 0 ? options.opcode : eventTypes.opcode; EventTags tags = (options.valuesSet & EventSourceOptions.tagsSet) != 0 ? options.tags : eventTypes.Tags; EventKeywords keywords = (options.valuesSet & EventSourceOptions.keywordsSet) != 0 ? options.keywords : eventTypes.keywords; var nameInfo = eventTypes.GetNameInfo(eventName ?? eventTypes.Name, tags); if (nameInfo == null) { return; } identity = nameInfo.identity; EventDescriptor descriptor = new EventDescriptor(identity, level, opcode, (long)keywords); #if FEATURE_PERFTRACING IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleTable, descriptor, eventTypes); Debug.Assert(eventHandle != IntPtr.Zero); #else IntPtr eventHandle = IntPtr.Zero; #endif var pinCount = eventTypes.pinCount; var scratch = stackalloc byte[eventTypes.scratchSize]; var descriptors = stackalloc EventData[eventTypes.dataCount + 3]; for (int i = 0; i < eventTypes.dataCount + 3; i++) { descriptors[i] = default; } var pins = stackalloc GCHandle[pinCount]; for (int i = 0; i < pinCount; i++) pins[i] = default; fixed(byte * pMetadata0 = this.providerMetadata, pMetadata1 = nameInfo.nameMetadata, pMetadata2 = eventTypes.typeMetadata) { descriptors[0].SetMetadata(pMetadata0, this.providerMetadata.Length, 2); descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1); descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1); #if (!ES_BUILD_PCL && !ES_BUILD_PN) System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); #endif try { DataCollector.ThreadInstance.Enable( scratch, eventTypes.scratchSize, descriptors + 3, eventTypes.dataCount, pins, pinCount); for (int i = 0; i < eventTypes.typeInfos.Length; i++) { var info = eventTypes.typeInfos[i]; info.WriteData(TraceLoggingDataCollector.Instance, info.PropertyValueFactory(values[i])); } this.WriteEventRaw( eventName, ref descriptor, eventHandle, activityID, childActivityID, (int)(DataCollector.ThreadInstance.Finish() - descriptors), (IntPtr)descriptors); } finally { this.WriteCleanup(pins, pinCount); } } #endif // FEATURE_MANAGED_ETW }
public IntPtr GetOrCreateEventHandle(EventProvider provider, ConcurrentDictionary <int, IntPtr> eventHandleMap, EventDescriptor descriptor, TraceLoggingEventTypes eventTypes) { IntPtr eventHandle = IntPtr.Zero; if (!eventHandleMap.TryGetValue(descriptor.EventId, out eventHandle)) { lock (eventHandleCreationLock) { if (!eventHandleMap.TryGetValue(descriptor.EventId, out eventHandle)) { byte[] metadataBlob = EventPipeMetadataGenerator.Instance.GenerateEventMetadata( descriptor.EventId, name, (EventKeywords)descriptor.Keywords, (EventLevel)descriptor.Level, descriptor.Version, eventTypes); uint metadataLength = (metadataBlob != null) ? (uint)metadataBlob.Length : 0; unsafe { fixed(byte *pMetadataBlob = metadataBlob) { // Define the event. eventHandle = provider.m_eventProvider.DefineEventHandle( (uint)descriptor.EventId, name, descriptor.Keywords, descriptor.Version, descriptor.Level, pMetadataBlob, metadataLength); } } } } } return(eventHandle); }