// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; using Interlocked = System.Threading.Interlocked; #if !ES_BUILD_AGAINST_DOTNET_V35 using Contract = System.Diagnostics.Contracts.Contract; #else using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract; #endif #if ES_BUILD_STANDALONE namespace Microsoft.Diagnostics.Tracing #else namespace System.Diagnostics.Tracing #endif { /// /// TraceLogging: Used when calling EventSource.WriteMultiMerge. /// Stores the type information to use when writing the event fields. /// public class TraceLoggingEventTypes { internal readonly TraceLoggingTypeInfo[] typeInfos; #if FEATURE_PERFTRACING internal readonly string[] paramNames; #endif internal readonly string name; internal readonly EventTags tags; internal readonly byte level; internal readonly byte opcode; internal readonly EventKeywords keywords; internal readonly byte[] typeMetadata; internal readonly int scratchSize; internal readonly int dataCount; internal readonly int pinCount; private ConcurrentSet, NameInfo> nameInfos; /// /// Initializes a new instance of TraceLoggingEventTypes corresponding /// to the name, flags, and types provided. Always uses the default /// TypeInfo for each Type. /// /// /// The name to use when the name parameter passed to /// EventSource.Write is null. This value must not be null. /// /// /// Tags to add to the event if the tags are not set via options. /// /// /// The types of the fields in the event. This value must not be null. /// internal TraceLoggingEventTypes( string name, EventTags tags, params Type[] types) : this(tags, name, MakeArray(types)) { return; } /// /// Returns a new instance of TraceLoggingEventInfo corresponding to the name, /// flags, and typeInfos provided. /// /// /// The name to use when the name parameter passed to /// EventSource.Write is null. This value must not be null. /// /// /// Tags to add to the event if the tags are not set via options. /// /// /// The types of the fields in the event. This value must not be null. /// /// /// An instance of TraceLoggingEventInfo with DefaultName set to the specified name /// and with the specified typeInfos. /// internal TraceLoggingEventTypes( string name, EventTags tags, params TraceLoggingTypeInfo[] typeInfos) : this(tags, name, MakeArray(typeInfos)) { return; } internal TraceLoggingEventTypes( string name, EventTags tags, System.Reflection.ParameterInfo[] paramInfos) { if (name == null) { throw new ArgumentNullException(nameof(name)); } this.typeInfos = MakeArray(paramInfos); #if FEATURE_PERFTRACING this.paramNames = MakeParamNameArray(paramInfos); #endif this.name = name; this.tags = tags; this.level = Statics.DefaultLevel; var collector = new TraceLoggingMetadataCollector(); for (int i = 0; i < typeInfos.Length; ++i) { var typeInfo = typeInfos[i]; this.level = Statics.Combine((int)typeInfo.Level, this.level); this.opcode = Statics.Combine((int)typeInfo.Opcode, this.opcode); this.keywords |= typeInfo.Keywords; var paramName = paramInfos[i].Name; if (Statics.ShouldOverrideFieldName(paramName)) { paramName = typeInfo.Name; } typeInfo.WriteMetadata(collector, paramName, EventFieldFormat.Default); } this.typeMetadata = collector.GetMetadata(); this.scratchSize = collector.ScratchSize; this.dataCount = collector.DataCount; this.pinCount = collector.PinCount; } private TraceLoggingEventTypes( EventTags tags, string defaultName, TraceLoggingTypeInfo[] typeInfos) { if (defaultName == null) { throw new ArgumentNullException(nameof(defaultName)); } this.typeInfos = typeInfos; this.name = defaultName; this.tags = tags; this.level = Statics.DefaultLevel; var collector = new TraceLoggingMetadataCollector(); foreach (var typeInfo in typeInfos) { this.level = Statics.Combine((int)typeInfo.Level, this.level); this.opcode = Statics.Combine((int)typeInfo.Opcode, this.opcode); this.keywords |= typeInfo.Keywords; typeInfo.WriteMetadata(collector, null, EventFieldFormat.Default); } this.typeMetadata = collector.GetMetadata(); this.scratchSize = collector.ScratchSize; this.dataCount = collector.DataCount; this.pinCount = collector.PinCount; } /// /// Gets the default name that will be used for events with this descriptor. /// internal string Name { get { return this.name; } } /// /// Gets the default level that will be used for events with this descriptor. /// internal EventLevel Level { get { return (EventLevel)this.level; } } /// /// Gets the default opcode that will be used for events with this descriptor. /// internal EventOpcode Opcode { get { return (EventOpcode)this.opcode; } } /// /// Gets the default set of keywords that will added to events with this descriptor. /// internal EventKeywords Keywords { get { return (EventKeywords)this.keywords; } } /// /// Gets the default tags that will be added events with this descriptor. /// internal EventTags Tags { get { return this.tags; } } internal NameInfo GetNameInfo(string name, EventTags tags) { var ret = this.nameInfos.TryGet(new KeyValuePair(name, tags)); if (ret == null) { ret = this.nameInfos.GetOrAdd(new NameInfo(name, tags, this.typeMetadata.Length)); } return ret; } private TraceLoggingTypeInfo[] MakeArray(System.Reflection.ParameterInfo[] paramInfos) { if (paramInfos == null) { throw new ArgumentNullException(nameof(paramInfos)); } var recursionCheck = new List(paramInfos.Length); var result = new TraceLoggingTypeInfo[paramInfos.Length]; for (int i = 0; i < paramInfos.Length; ++i) { result[i] = TraceLoggingTypeInfo.GetInstance(paramInfos[i].ParameterType, recursionCheck); } return result; } private static TraceLoggingTypeInfo[] MakeArray(Type[] types) { if (types == null) { throw new ArgumentNullException(nameof(types)); } var recursionCheck = new List(types.Length); var result = new TraceLoggingTypeInfo[types.Length]; for (int i = 0; i < types.Length; i++) { result[i] = TraceLoggingTypeInfo.GetInstance(types[i], recursionCheck); } return result; } private static TraceLoggingTypeInfo[] MakeArray( TraceLoggingTypeInfo[] typeInfos) { if (typeInfos == null) { throw new ArgumentNullException(nameof(typeInfos)); } return (TraceLoggingTypeInfo[])typeInfos.Clone(); ; } #if FEATURE_PERFTRACING private static string[] MakeParamNameArray( System.Reflection.ParameterInfo[] paramInfos) { string[] paramNames = new string[paramInfos.Length]; for (int i = 0; i < paramNames.Length; i++) { paramNames[i] = paramInfos[i].Name; } return paramNames; } #endif } }