From a222ac399c5458a8772e8c4b3ddffd61e85e0774 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Mon, 17 Oct 2022 12:58:07 -0700 Subject: [PATCH] Avoid race condition and performance trap in EventCountersMetrics --- .../EventCountersMetrics.cs | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/OpenTelemetry.Instrumentation.EventCounters/EventCountersMetrics.cs b/src/OpenTelemetry.Instrumentation.EventCounters/EventCountersMetrics.cs index e01ce8b968..b7797eeb97 100644 --- a/src/OpenTelemetry.Instrumentation.EventCounters/EventCountersMetrics.cs +++ b/src/OpenTelemetry.Instrumentation.EventCounters/EventCountersMetrics.cs @@ -30,7 +30,7 @@ internal sealed class EventCountersMetrics : EventListener internal static readonly Meter MeterInstance = new(typeof(EventCountersMetrics).Assembly.GetName().Name, typeof(EventCountersMetrics).Assembly.GetName().Version.ToString()); private readonly EventCountersInstrumentationOptions options; - private readonly ConcurrentQueue preInitEventSources = new(); + private readonly List preInitEventSources = new(); private readonly ConcurrentDictionary<(string, string), Instrument> instruments = new(); private readonly ConcurrentDictionary<(string, string), double> values = new(); @@ -40,29 +40,42 @@ internal sealed class EventCountersMetrics : EventListener /// The options to define the metrics. public EventCountersMetrics(EventCountersInstrumentationOptions options) { - this.options = options; - - while (this.preInitEventSources.TryDequeue(out EventSource eventSource)) + lock (this.preInitEventSources) { - if (this.options.ShouldListenToSource(eventSource.Name)) + this.options = options; + + foreach (EventSource eventSource in this.preInitEventSources) { - this.EnableEvents(eventSource, EventLevel.LogAlways, EventKeywords.None, GetEnableEventsArguments(this.options)); + if (this.options.ShouldListenToSource(eventSource.Name)) + { + this.EnableEvents(eventSource); + } } + + this.preInitEventSources.Clear(); } } /// - protected override void OnEventSourceCreated(EventSource source) + protected override void OnEventSourceCreated(EventSource eventSource) { - if (this.options == null) - { - this.preInitEventSources.Enqueue(source); - } - else if (this.options.ShouldListenToSource(source.Name)) + lock (this.preInitEventSources) { - this.EnableEvents(source, EventLevel.LogAlways, EventKeywords.None, GetEnableEventsArguments(this.options)); + if (this.options == null) + { + this.preInitEventSources.Add(eventSource); + } + else if (this.options.ShouldListenToSource(eventSource.Name)) + { + this.EnableEvents(eventSource); + } } } + + private void EnableEvents(EventSource eventSource) + { + this.EnableEvents(eventSource, EventLevel.Critical, EventKeywords.None, GetEnableEventsArguments(this.options)); + } /// protected override void OnEventWritten(EventWrittenEventArgs eventData)