public TraceEvent( IVariantEventWriter variantEventWriter, EventTask taskId, ushort eventId, string eventName, EventLevel level, EventOpcode opcode, EventChannel channel, EventKeywords keywords, string format, bool hasId, ProvisionalMetadataAttribute provisionalAttribute, int typeFieldIndex, EventExtendedMetadataAttribute extendedMetadataAttribute = null) { if (string.IsNullOrEmpty(eventName)) { throw new ArgumentException( StringResources.Error_EventNameNullOrEmpty, "eventName"); } // We need to apply a keyword mask to the keyword in order for it to show up // in the Windows Event Log. The mask that is applied depends on the channel // in which we want the event to show up. // // TODO: We are currently hard-coding the mask values, but this is not ideal // because we have reverse-engineered these values by looking at the header // file generated by mc.exe. The algorithm to determine these values is an // internal implementation detail of mc.exe. A better alternative would be // to get the mask value from the source file generated by mc.exe, instead // of hard-coding it as a constant here. ulong keywordMask = 0; switch (channel) { case EventChannel.Admin: keywordMask = AdminChannelKeywordMask; break; case EventChannel.Debug: keywordMask = DebugChannelKeywordMask; break; case EventChannel.Operational: keywordMask = OperationalChannelKeywordMask; break; } long keywordWithMask; unchecked { keywordWithMask = (long)((ulong)keywords | keywordMask | TestKeyword); } // We ignore the opcode field for now. Manifest generation does the same. this.descriptor = new GenericEventDescriptor( eventId, version, (byte)channel, (byte)level, 0, (int)taskId, keywordWithMask); this.eventName = eventName; this.taskId = taskId; this.level = level; this.filterStates = new bool[(int)TraceSinkType.Max]; this.samplingRatio = 0; this.hasId = hasId; this.typeFieldIndex = typeFieldIndex; this.format = format; this.taskName = typeof(FabricEvents.Tasks).GetFields().Single(f => (EventTask)f.GetRawConstantValue() == taskId).Name; this.variantEventWriter = variantEventWriter; // By default, provisional feature is disabled during object initialization. This needs to be enabled // by calling the Update function. this.isProvisionalFeatureEnabled = false; this.provisionalData = provisionalAttribute; if (this.provisionalData != null) { this.isProvisionalEvent = true; this.provisionalCache = AgeBasedCache <VariantId, Variant[]> .DefaultInstance; this.PopulatePositions(); } for (TraceSinkType sink = 0; sink < TraceSinkType.Max; sink++) { var status = TraceConfig.GetEventEnabledStatus(sink, this.level, this.taskId, this.eventName); var sampling = TraceConfig.GetEventSamplingRatio(sink, this.level, this.taskId, this.eventName); this.UpdateProvisionalFeatureStatus(sink, TraceConfig.GetEventProvisionalFeatureStatus(sink)); this.UpdateSinkEnabledStatus(sink, status); this.UpdateSinkSamplingRatio(sink, sampling); } #if DotNetCoreClrLinux // TODO - Following code will be removed once fully transitioned to structured traces in Linux this.linuxStructuredTracesEnabled = TraceConfig.GetLinuxStructuredTracesEnabled(); TraceConfig.OnLinuxStructuredTracesEnabledUpdate += this.UpdateLinuxStructuredTracesEnabled; #endif this.ExtendedMetadata = extendedMetadataAttribute; }
protected ReadOnlyDictionary <int, TraceEvent> GenerateEventDescriptors(IVariantEventWriter variantEventWriter) { var eventDescriptors = new Dictionary <int, TraceEvent>(); foreach (var eventMethod in this.GetType().GetMethods()) { EventAttribute eventAttribute = (EventAttribute)eventMethod.GetCustomAttributes(typeof(EventAttribute), false).SingleOrDefault(); if (eventAttribute == null) { continue; } var hasId = false; int typeFieldIndex = -1; var methodParams = eventMethod.GetParameters().ToList(); if (methodParams.Any()) { typeFieldIndex = methodParams.FindIndex(e => e.Name == "type"); hasId = methodParams[0].Name == "id"; } var eventId = (ushort)eventAttribute.EventId; ProvisionalMetadataAttribute provisional = (ProvisionalMetadataAttribute)CustomAttributeExtensions.GetCustomAttributes(eventMethod, typeof(ProvisionalMetadataAttribute), false).SingleOrDefault(); EventExtendedMetadataAttribute extended = (EventExtendedMetadataAttribute)CustomAttributeExtensions.GetCustomAttributes(eventMethod, typeof(EventExtendedMetadataAttribute), false).SingleOrDefault(); string eventName = eventMethod.Name; if (extended != null && extended.TableEntityKind != TableEntityKind.Unknown) { eventName = string.Format(FabricEventSourceConstants.OperationalChannelEventNameFormat, extended.TableEntityKind, FabricEventSourceConstants.OperationalChannelTableNameSuffix, eventName); } eventDescriptors[eventId] = new TraceEvent( variantEventWriter, eventAttribute.Task, eventId, eventName, eventAttribute.Level, eventAttribute.Opcode, ChannelToUse(eventAttribute, extended), eventAttribute.Keywords, FormatStringToUse(eventAttribute, extended), hasId, provisional, typeFieldIndex, extended); // Wire up TraceConfig filtering to event enabled status TraceConfig.OnFilterUpdate += sinkType => { eventDescriptors[eventId].UpdateSinkEnabledStatus(sinkType, TraceConfig.GetEventEnabledStatus( sinkType, eventDescriptors[eventId].Level, eventDescriptors[eventId].TaskId, eventDescriptors[eventId].EventName)); eventDescriptors[eventId].UpdateSinkSamplingRatio(sinkType, TraceConfig.GetEventSamplingRatio( sinkType, eventDescriptors[eventId].Level, eventDescriptors[eventId].TaskId, eventDescriptors[eventId].EventName)); eventDescriptors[eventId].UpdateProvisionalFeatureStatus(sinkType, TraceConfig.GetEventProvisionalFeatureStatus(sinkType)); }; } return(new ReadOnlyDictionary <int, TraceEvent>(eventDescriptors)); }