| File: TraceSourceLoggerProvider.cs | Web Access |
| Project: src\runtime\src\libraries\Microsoft.Extensions.Logging.TraceSource\src\Microsoft.Extensions.Logging.TraceSource.csproj (Microsoft.Extensions.Logging.TraceSource) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Concurrent; using System.Diagnostics; using DiagnosticsTraceSource = System.Diagnostics.TraceSource; namespace Microsoft.Extensions.Logging.TraceSource { /// <summary> /// Provides an ILoggerFactory based on System.Diagnostics.TraceSource. /// </summary> [ProviderAlias("TraceSource")] public class TraceSourceLoggerProvider : ILoggerProvider { private readonly SourceSwitch _rootSourceSwitch; private readonly TraceListener? _rootTraceListener; private readonly ConcurrentDictionary<string, DiagnosticsTraceSource> _sources = new ConcurrentDictionary<string, DiagnosticsTraceSource>(StringComparer.OrdinalIgnoreCase); private bool _disposed; /// <summary> /// Initializes a new instance of the <see cref="TraceSourceLoggerProvider"/> class. /// </summary> /// <param name="rootSourceSwitch">The <see cref="SourceSwitch"/> to use.</param> public TraceSourceLoggerProvider(SourceSwitch rootSourceSwitch) : this(rootSourceSwitch, null) { } /// <summary> /// Initializes a new instance of the <see cref="TraceSourceLoggerProvider"/> class. /// </summary> /// <param name="rootSourceSwitch">The <see cref="SourceSwitch"/> to use.</param> /// <param name="rootTraceListener">The <see cref="TraceListener"/> to use.</param> public TraceSourceLoggerProvider(SourceSwitch rootSourceSwitch, TraceListener? rootTraceListener) { ArgumentNullException.ThrowIfNull(rootSourceSwitch); _rootSourceSwitch = rootSourceSwitch; _rootTraceListener = rootTraceListener; } /// <summary> /// Creates a new <see cref="ILogger"/> for the given component name. /// </summary> /// <param name="name">The name of the <see cref="TraceSource"/> to add.</param> /// <returns>The <see cref="TraceSourceLogger"/> that was created.</returns> public ILogger CreateLogger(string name) { return new TraceSourceLogger(GetOrAddTraceSource(name)); } private DiagnosticsTraceSource GetOrAddTraceSource(string name) => _sources.TryGetValue(name, out DiagnosticsTraceSource? source) ? source : _sources.GetOrAdd(name, InitializeTraceSource(name)); private DiagnosticsTraceSource InitializeTraceSource(string traceSourceName) { var traceSource = new DiagnosticsTraceSource(traceSourceName); string? parentSourceName = ParentSourceName(traceSourceName); if (string.IsNullOrEmpty(parentSourceName)) { if (HasDefaultSwitch(traceSource)) { traceSource.Switch = _rootSourceSwitch; } if (_rootTraceListener != null) { traceSource.Listeners.Add(_rootTraceListener); } } else { if (HasDefaultListeners(traceSource)) { DiagnosticsTraceSource parentTraceSource = GetOrAddTraceSource(parentSourceName); traceSource.Listeners.Clear(); traceSource.Listeners.AddRange(parentTraceSource.Listeners); } if (HasDefaultSwitch(traceSource)) { DiagnosticsTraceSource parentTraceSource = GetOrAddTraceSource(parentSourceName); traceSource.Switch = parentTraceSource.Switch; } } return traceSource; } private static string? ParentSourceName(string traceSourceName) { int indexOfLastDot = traceSourceName.LastIndexOf('.'); return indexOfLastDot == -1 ? null : traceSourceName.Substring(0, indexOfLastDot); } private static bool HasDefaultListeners(DiagnosticsTraceSource traceSource) { return traceSource.Listeners.Count == 1 && traceSource.Listeners[0] is DefaultTraceListener; } private static bool HasDefaultSwitch(DiagnosticsTraceSource traceSource) { return string.IsNullOrEmpty(traceSource.Switch.DisplayName) == string.IsNullOrEmpty(traceSource.Name) && traceSource.Switch.Level == SourceLevels.Off; } /// <inheritdoc /> public void Dispose() { if (!_disposed) { _disposed = true; if (_rootTraceListener != null) { _rootTraceListener.Flush(); _rootTraceListener.Dispose(); } } } } }