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; }