From c8a8913152eb4a983df485f583a22ed706c0cbf4 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Tue, 24 Sep 2024 14:47:16 -0700 Subject: [PATCH] [repo] Take advantage of System.Threading.Lock when compiling against .NET9 (#5861) --- OpenTelemetry.sln | 1 + src/OpenTelemetry.Api/OpenTelemetry.Api.csproj | 1 + .../ConsoleLogRecordExporter.cs | 2 +- ...try.Exporter.Prometheus.HttpListener.csproj | 1 + .../PrometheusHttpListener.cs | 2 +- .../Internal/SelfDiagnosticsEventListener.cs | 2 +- src/OpenTelemetry/Metrics/AggregatorStore.cs | 4 ++-- src/OpenTelemetry/Metrics/MeterProviderSdk.cs | 2 +- .../Metrics/Reader/MetricReader.cs | 4 ++-- .../Metrics/Reader/MetricReaderExt.cs | 2 +- src/OpenTelemetry/SimpleExportProcessor.cs | 2 +- src/Shared/Shims/Lock.cs | 18 ++++++++++++++++++ 12 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 src/Shared/Shims/Lock.cs diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln index 5ca42dd0962..f9bde54e00a 100644 --- a/OpenTelemetry.sln +++ b/OpenTelemetry.sln @@ -281,6 +281,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shims", "Shims", "{A0CB9A10-F22D-4E66-A449-74B3D0361A9C}" ProjectSection(SolutionItems) = preProject src\Shared\Shims\IsExternalInit.cs = src\Shared\Shims\IsExternalInit.cs + src\Shared\Shims\Lock.cs = src\Shared\Shims\Lock.cs src\Shared\Shims\NullableAttributes.cs = src\Shared\Shims\NullableAttributes.cs EndProjectSection EndProject diff --git a/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj b/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj index 403ed430bfc..0e6d270b408 100644 --- a/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj +++ b/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj @@ -16,6 +16,7 @@ + diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs b/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs index 9818b17f4b0..0dfe396b30e 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs @@ -10,7 +10,7 @@ namespace OpenTelemetry.Exporter; public class ConsoleLogRecordExporter : ConsoleExporter { private const int RightPaddingLength = 35; - private readonly object syncObject = new(); + private readonly Lock syncObject = new(); private bool disposed; private string? disposedStackTrace; private bool isDisposeMessageSent; diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj index 91fb3f461cf..4e087919be2 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj @@ -19,6 +19,7 @@ + diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs index 284a99acc87..cecda73f7c9 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs @@ -11,7 +11,7 @@ internal sealed class PrometheusHttpListener : IDisposable { private readonly PrometheusExporter exporter; private readonly HttpListener httpListener = new(); - private readonly object syncObject = new(); + private readonly Lock syncObject = new(); private CancellationTokenSource? tokenSource; private Task? workerThread; diff --git a/src/OpenTelemetry/Internal/SelfDiagnosticsEventListener.cs b/src/OpenTelemetry/Internal/SelfDiagnosticsEventListener.cs index cdfe233fd66..2ace3eb5526 100644 --- a/src/OpenTelemetry/Internal/SelfDiagnosticsEventListener.cs +++ b/src/OpenTelemetry/Internal/SelfDiagnosticsEventListener.cs @@ -16,7 +16,7 @@ internal sealed class SelfDiagnosticsEventListener : EventListener // Buffer size of the log line. A UTF-16 encoded character in C# can take up to 4 bytes if encoded in UTF-8. private const int BUFFERSIZE = 4 * 5120; private const string EventSourceNamePrefix = "OpenTelemetry-"; - private readonly object lockObj = new(); + private readonly Lock lockObj = new(); private readonly EventLevel logLevel; private readonly SelfDiagnosticsConfigRefresher configRefresher; private readonly ThreadLocal writeBuffer = new(() => null); diff --git a/src/OpenTelemetry/Metrics/AggregatorStore.cs b/src/OpenTelemetry/Metrics/AggregatorStore.cs index 5dc4f92dee9..fbbd598a67a 100644 --- a/src/OpenTelemetry/Metrics/AggregatorStore.cs +++ b/src/OpenTelemetry/Metrics/AggregatorStore.cs @@ -31,8 +31,8 @@ internal sealed class AggregatorStore private static readonly string MetricPointCapHitFixMessage = "Consider opting in for the experimental SDK feature to emit all the throttled metrics under the overflow attribute by setting env variable OTEL_DOTNET_EXPERIMENTAL_METRICS_EMIT_OVERFLOW_ATTRIBUTE = true. You could also modify instrumentation to reduce the number of unique key/value pair combinations. Or use Views to drop unwanted tags. Or use MeterProviderBuilder.SetMaxMetricPointsPerMetricStream to set higher limit."; private static readonly Comparison> DimensionComparisonDelegate = (x, y) => x.Key.CompareTo(y.Key); - private readonly object lockZeroTags = new(); - private readonly object lockOverflowTag = new(); + private readonly Lock lockZeroTags = new(); + private readonly Lock lockOverflowTag = new(); private readonly int tagsKeysInterestingCount; // This holds the reclaimed MetricPoints that are available for reuse. diff --git a/src/OpenTelemetry/Metrics/MeterProviderSdk.cs b/src/OpenTelemetry/Metrics/MeterProviderSdk.cs index 467da3f538b..0ec16a9c20a 100644 --- a/src/OpenTelemetry/Metrics/MeterProviderSdk.cs +++ b/src/OpenTelemetry/Metrics/MeterProviderSdk.cs @@ -30,7 +30,7 @@ internal sealed class MeterProviderSdk : MeterProvider private readonly List instrumentations = new(); private readonly List> viewConfigs; - private readonly object collectLock = new(); + private readonly Lock collectLock = new(); private readonly MeterListener listener; private readonly MetricReader? reader; private readonly CompositeMetricReader? compositeMetricReader; diff --git a/src/OpenTelemetry/Metrics/Reader/MetricReader.cs b/src/OpenTelemetry/Metrics/Reader/MetricReader.cs index decbf8ad70d..fce60c50f3a 100644 --- a/src/OpenTelemetry/Metrics/Reader/MetricReader.cs +++ b/src/OpenTelemetry/Metrics/Reader/MetricReader.cs @@ -36,8 +36,8 @@ public abstract partial class MetricReader : IDisposable }; }; - private readonly object newTaskLock = new(); - private readonly object onCollectLock = new(); + private readonly Lock newTaskLock = new(); + private readonly Lock onCollectLock = new(); private readonly TaskCompletionSource shutdownTcs = new(); private MetricReaderTemporalityPreference temporalityPreference = MetricReaderTemporalityPreferenceUnspecified; private Func temporalityFunc = CumulativeTemporalityPreferenceFunc; diff --git a/src/OpenTelemetry/Metrics/Reader/MetricReaderExt.cs b/src/OpenTelemetry/Metrics/Reader/MetricReaderExt.cs index a6a0a642d46..def0591d0d4 100644 --- a/src/OpenTelemetry/Metrics/Reader/MetricReaderExt.cs +++ b/src/OpenTelemetry/Metrics/Reader/MetricReaderExt.cs @@ -16,7 +16,7 @@ public abstract partial class MetricReader { private readonly HashSet metricStreamNames = new(StringComparer.OrdinalIgnoreCase); private readonly ConcurrentDictionary instrumentIdentityToMetric = new(); - private readonly object instrumentCreationLock = new(); + private readonly Lock instrumentCreationLock = new(); private int metricLimit; private int cardinalityLimit; private Metric?[]? metrics; diff --git a/src/OpenTelemetry/SimpleExportProcessor.cs b/src/OpenTelemetry/SimpleExportProcessor.cs index 10951cd8533..95387ef997f 100644 --- a/src/OpenTelemetry/SimpleExportProcessor.cs +++ b/src/OpenTelemetry/SimpleExportProcessor.cs @@ -12,7 +12,7 @@ namespace OpenTelemetry; public abstract class SimpleExportProcessor : BaseExportProcessor where T : class { - private readonly object syncObject = new(); + private readonly Lock syncObject = new(); /// /// Initializes a new instance of the class. diff --git a/src/Shared/Shims/Lock.cs b/src/Shared/Shims/Lock.cs new file mode 100644 index 00000000000..8b82deb4d5c --- /dev/null +++ b/src/Shared/Shims/Lock.cs @@ -0,0 +1,18 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#if !NET9_0_OR_GREATER +namespace OpenTelemetry; + +// Note: .NET9 added the System.Threading.Lock class. The goal here is when +// compiling against .NET9+ code should use System.Threading.Lock class for +// better perf. Legacy code can use this class which will perform a classic +// monitor-based lock against a reference of this class. This type is not in the +// System.Threading namespace so that the compiler doesn't get confused when it +// sees it used. It is in OpenTelemetry namespace and not OpenTelemetry.Internal +// namespace so that code should be able to use it without the presence of a +// dedicated "using OpenTelemetry.Internal" just for the shim. +internal sealed class Lock +{ +} +#endif