diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index 851f4416dd6d8..d9fa4d943bf2a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -2864,10 +2864,7 @@ private void EnsureDescriptorsInitialized() // Today, we only send the manifest to ETW, custom listeners don't get it. private unsafe void SendManifest(byte[]? rawManifest) { - if (rawManifest == null - // Don't send the manifest for NativeRuntimeEventSource, it is conceptually - // an extension of the native coreclr provider - || m_name.Equals("Microsoft-Windows-DotNETRuntime")) + if (rawManifest == null) { return; } @@ -3129,15 +3126,19 @@ private static bool AttributeTypeNamesMatch(Type attributeType, Type reflectedAt if (eventSourceAttrib != null && eventSourceAttrib.LocalizationResources != null) resources = new ResourceManager(eventSourceAttrib.LocalizationResources, eventSourceType.Assembly); - if (source is not null) + if (source?.GetType() == typeof(NativeRuntimeEventSource)) { - // We have the source so don't need to use reflection to get the Name and Guid - manifest = new ManifestBuilder(source.Name, source.Guid, eventSourceDllName, resources, flags); + // Don't emit nor generate the manifest for NativeRuntimeEventSource i.e., Microsoft-Windows-DotNETRuntime. + manifest = new ManifestBuilder(resources, flags); + bNeedsManifest = false; } else { - manifest = new ManifestBuilder(GetName(eventSourceType, flags), GetGuid(eventSourceType), eventSourceDllName, - resources, flags); + // Try to get name and GUID directly from the source. Otherwise get it from the Type's attribute. + string providerName = source?.Name ?? GetName(eventSourceType, flags); + Guid providerGuid = source?.Guid ?? GetGuid(eventSourceType); + + manifest = new ManifestBuilder(providerName, providerGuid, eventSourceDllName, resources, flags); } // Add an entry unconditionally for event ID 0 which will be for a string message. @@ -3381,6 +3382,7 @@ private static bool AttributeTypeNamesMatch(Type attributeType, Type reflectedAt return null; res = manifest.CreateManifest(); + res = (res.Length > 0) ? res : null; } } catch (Exception e) @@ -5258,22 +5260,15 @@ internal sealed class ManifestBuilder /// 'resources, is a resource manager. If specified all messages are localized using that manager. /// public ManifestBuilder(string providerName, Guid providerGuid, string? dllName, ResourceManager? resources, - EventManifestOptions flags) + EventManifestOptions flags) : this(resources, flags) { #if FEATURE_MANAGED_ETW_CHANNELS this.providerName = providerName; #endif - this.flags = flags; - this.resources = resources; sb = new StringBuilder(); events = new StringBuilder(); templates = new StringBuilder(); - opcodeTab = new Dictionary(); - stringTab = new Dictionary(); - errors = new List(); - perEventByteArrayArgIndices = new Dictionary>(); - sb.AppendLine(""); sb.AppendLine(" "); sb.AppendLine(" "); @@ -5285,6 +5280,26 @@ public ManifestBuilder(string providerName, Guid providerGuid, string? dllName, sb.AppendLine($" symbol=\"{symbolsName}\">"); } + /// + /// Will NOT build a manifest! If the intention is to build a manifest don’t use this constructor. + ///'resources, is a resource manager. If specified all messages are localized using that manager. + /// + internal ManifestBuilder(ResourceManager? resources, EventManifestOptions flags) + { + providerName = ""; + + this.flags = flags; + + this.resources = resources; + sb = null; + events = null; + templates = null; + opcodeTab = new Dictionary(); + stringTab = new Dictionary(); + errors = new List(); + perEventByteArrayArgIndices = new Dictionary>(); + } + public void AddOpcode(string name, int value) { if ((flags & EventManifestOptions.Strict) != 0) @@ -5422,11 +5437,11 @@ public void StartEvent(string eventName, EventAttribute eventAttribute) numParams = 0; byteArrArgIndices = null; - events.Append(" "); + templates?.Append(" "); - events.Append(" template=\"").Append(eventName).Append("Args\""); + templates?.AppendLine(" "); + events?.Append(" template=\"").Append(eventName).Append("Args\""); } - events.AppendLine("/>"); + events?.AppendLine("/>"); if (byteArrArgIndices != null) perEventByteArrayArgIndices[eventName] = byteArrArgIndices; @@ -5562,7 +5580,7 @@ public ulong GetChannelKeyword(EventChannel channel, ulong channelKeyword = 0) public byte[] CreateManifest() { string str = CreateManifestString(); - return Encoding.UTF8.GetBytes(str); + return (str != "") ? Encoding.UTF8.GetBytes(str) : Array.Empty(); } public IList Errors => errors; @@ -5592,10 +5610,11 @@ private string CreateManifestString() // Write out the channels if (channelTab != null) { - sb.AppendLine(" "); + sb?.AppendLine(" "); var sortedChannels = new List>(); foreach (KeyValuePair p in channelTab) { sortedChannels.Add(p); } sortedChannels.Sort((p1, p2) => -Comparer.Default.Compare(p1.Value.Keywords, p2.Value.Keywords)); + foreach (KeyValuePair kvpair in sortedChannels) { int channel = kvpair.Key; @@ -5628,39 +5647,39 @@ private string CreateManifestString() fullName ??= providerName + "/" + channelInfo.Name; - sb.Append(" "); + sb?.AppendLine("/>"); } - sb.AppendLine(" "); + sb?.AppendLine(" "); } #endif // Write out the tasks if (taskTab != null) { - sb.AppendLine(" "); + sb?.AppendLine(" "); var sortedTasks = new List(taskTab.Keys); sortedTasks.Sort(); + foreach (int task in sortedTasks) { - sb.Append(" "); + sb?.Append(" value=\"").Append(task).AppendLine("\"/>"); } - sb.AppendLine(" "); + sb?.AppendLine(" "); } // Write out the maps @@ -5676,12 +5695,12 @@ static FieldInfo[] GetEnumFields(Type localEnumType) if (mapsTab != null) { - sb.AppendLine(" "); + sb?.AppendLine(" "); foreach (Type enumType in mapsTab.Values) { bool isbitmap = EventSource.IsCustomAttributeDefinedHelper(enumType, typeof(FlagsAttribute), flags); string mapKind = isbitmap ? "bitMap" : "valueMap"; - sb.Append(" <").Append(mapKind).Append(" name=\"").Append(enumType.Name).AppendLine("\">"); + sb?.Append(" <").Append(mapKind).Append(" name=\"").Append(enumType.Name).AppendLine("\">"); // write out each enum value FieldInfo[] staticFields = GetEnumFields(enumType); @@ -5705,9 +5724,10 @@ static FieldInfo[] GetEnumFields(Type localEnumType) hexValue.TryFormat(ulongHexScratch, out int charsWritten, "x"); Span hexValueFormatted = ulongHexScratch.Slice(0, charsWritten); - sb.Append(" "); + sb?.AppendLine("/>"); anyValuesWritten = true; } } @@ -5716,95 +5736,97 @@ static FieldInfo[] GetEnumFields(Type localEnumType) // To avoid that put a 'None' entry if there are no other values. if (!anyValuesWritten) { - sb.Append(" "); + sb?.AppendLine("/>"); } - sb.Append(" "); + sb?.Append(" "); } - sb.AppendLine(" "); + sb?.AppendLine(" "); } // Write out the opcodes - sb.AppendLine(" "); + sb?.AppendLine(" "); var sortedOpcodes = new List(opcodeTab.Keys); sortedOpcodes.Sort(); + foreach (int opcode in sortedOpcodes) { - sb.Append(" "); + sb?.Append(" value=\"").Append(opcode).AppendLine("\"/>"); } - sb.AppendLine(" "); + sb?.AppendLine(" "); // Write out the keywords if (keywordTab != null) { - sb.AppendLine(" "); + sb?.AppendLine(" "); var sortedKeywords = new List(keywordTab.Keys); sortedKeywords.Sort(); + foreach (ulong keyword in sortedKeywords) { - sb.Append(" keywordFormatted = ulongHexScratch.Slice(0, charsWritten); - sb.Append(" mask=\"0x").Append(keywordFormatted).AppendLine("\"/>"); + sb?.Append(" mask=\"0x").Append(keywordFormatted).AppendLine("\"/>"); } - sb.AppendLine(" "); + sb?.AppendLine(" "); } - sb.AppendLine(" "); - sb.Append(events); - sb.AppendLine(" "); + sb?.AppendLine(" "); + sb?.Append(events); + sb?.AppendLine(" "); - sb.AppendLine(" "); - if (templates.Length > 0) + sb?.AppendLine(" "); + if (templates?.Length > 0) { - sb.Append(templates); + sb?.Append(templates); } else { // Work around a corner-case ETW issue where a manifest with no templates causes // ETW events to not get sent to their associated channel. - sb.AppendLine(" "); + sb?.AppendLine(" "); } - sb.AppendLine(" "); + sb?.AppendLine(" "); - sb.AppendLine(""); - sb.AppendLine(""); - sb.AppendLine(""); + sb?.AppendLine(""); + sb?.AppendLine(""); + sb?.AppendLine(""); // Output the localization information. - sb.AppendLine(""); + sb?.AppendLine(""); var sortedStrings = new string[stringTab.Keys.Count]; stringTab.Keys.CopyTo(sortedStrings, 0); Array.Sort(sortedStrings, StringComparer.Ordinal); CultureInfo ci = CultureInfo.CurrentUICulture; - sb.Append(" "); - sb.AppendLine(" "); + sb?.Append(" "); + sb?.AppendLine(" "); foreach (string stringKey in sortedStrings) { string? val = GetLocalizedMessage(stringKey, ci, etwFormat: true); - sb.Append(" "); + sb?.Append(" "); } - sb.AppendLine(" "); - sb.AppendLine(" "); + sb?.AppendLine(" "); + sb?.AppendLine(" "); - sb.AppendLine(""); - sb.AppendLine(""); - return sb.ToString(); + sb?.AppendLine(""); + sb?.AppendLine(""); + return sb?.ToString() ?? ""; } #region private - private void WriteNameAndMessageAttribs(StringBuilder stringBuilder, string elementName, string name) + private void WriteNameAndMessageAttribs(StringBuilder? stringBuilder, string elementName, string name) { - stringBuilder.Append(" name=\"").Append(name).Append('"'); + stringBuilder?.Append(" name=\"").Append(name).Append('"'); WriteMessageAttrib(sb, elementName, name, name); } - private void WriteMessageAttrib(StringBuilder stringBuilder, string elementName, string name, string? value) + private void WriteMessageAttrib(StringBuilder? stringBuilder, string elementName, string name, string? value) { string? key = null; @@ -5821,7 +5843,7 @@ private void WriteMessageAttrib(StringBuilder stringBuilder, string elementName, return; key ??= elementName + "_" + name; - stringBuilder.Append(" message=\"$(string.").Append(key).Append(")\""); + stringBuilder?.Append(" message=\"$(string.").Append(key).Append(")\""); if (stringTab.TryGetValue(key, out string? prevValue) && !prevValue.Equals(value)) { @@ -5853,14 +5875,14 @@ private void WriteMessageAttrib(StringBuilder stringBuilder, string elementName, return value; } - private static void AppendLevelName(StringBuilder sb, EventLevel level) + private static void AppendLevelName(StringBuilder? sb, EventLevel level) { if ((int)level < 16) { - sb.Append("win:"); + sb?.Append("win:"); } - sb.Append(level switch // avoid boxing that comes from level.ToString() + sb?.Append(level switch // avoid boxing that comes from level.ToString() { EventLevel.LogAlways => nameof(EventLevel.LogAlways), EventLevel.Critical => nameof(EventLevel.Critical), @@ -5950,7 +5972,7 @@ private string GetTaskName(EventTask task, string eventName) return ret; } - private void AppendKeywords(StringBuilder sb, ulong keywords, string eventName) + private void AppendKeywords(StringBuilder? sb, ulong keywords, string eventName) { #if FEATURE_MANAGED_ETW_CHANNELS // ignore keywords associate with channels @@ -5981,10 +6003,10 @@ private void AppendKeywords(StringBuilder sb, ulong keywords, string eventName) { if (appended) { - sb.Append(' '); + sb?.Append(' '); } - sb.Append(keyword); + sb?.Append(keyword); appended = true; } } @@ -6176,9 +6198,9 @@ private sealed class ChannelInfo private const int MaxCountChannels = 8; // a manifest can defined at most 8 ETW channels #endif - private readonly StringBuilder sb; // Holds the provider information. - private readonly StringBuilder events; // Holds the events. - private readonly StringBuilder templates; + private readonly StringBuilder? sb; // Holds the provider information. + private readonly StringBuilder? events; // Holds the events. + private readonly StringBuilder? templates; #if FEATURE_MANAGED_ETW_CHANNELS private readonly string providerName;