diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 21df876c68..a75b508e3b 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -988,17 +988,29 @@ public override bool CanConvert(Type objectType) return objectType == typeof(DateTime); } } - + /// /// Distributed Tracing Options. /// + /// Applicable only when Operation level distributed tracing is enabled through internal DistributedTracingOptions DistributedTracingOptions { get; set; } /// - /// Gets or sets value indicating whether distributed tracing activities () are going to be created for the SDK methods calls and HTTP calls. - /// By default true for Preview package + /// Gets or sets the flag to generate operation level for methods calls using the Source Name "Azure.Cosmos.Operation". /// - internal bool EnableDistributedTracing { get; set; } + /// + /// The default value is true (for preview package). + /// + /// This flag is there to disable it from source. Please Refer https://opentelemetry.io/docs/instrumentation/net/exporters/ to know more about open telemetry exporters +#if PREVIEW + public +#else + internal +#endif + bool IsDistributedTracingEnabled { get; set; } +#if PREVIEW + = true; +#endif } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index d47f168764..44c38ec51b 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -424,12 +424,30 @@ public CosmosClientBuilder WithConsistencyLevel(Cosmos.ConsistencyLevel consiste } /// - /// If Open Telemetry listener is subscribed for Azure.Cosmos namespace, There are you can leverage to control it.

+ /// Sets whether Distributed Tracing for "Azure.Cosmos.Operation" source is enabled. ///
- /// Tracing Options + /// Whether is enabled. /// The current . - internal CosmosClientBuilder WithDistributingTracing(DistributedTracingOptions options) +#if PREVIEW + public +#else + internal +#endif + CosmosClientBuilder WithDistributedTracing(bool isEnabled = true) + { + this.clientOptions.IsDistributedTracingEnabled = isEnabled; + return this; + } + + /// + /// Enables Distributed Tracing with a Configuration ref. + /// + /// . + /// The current .] + /// Refer https://opentelemetry.io/docs/instrumentation/net/exporters/ to know more about open telemetry exporters + internal CosmosClientBuilder WithDistributedTracingOptions(DistributedTracingOptions options) { + this.clientOptions.IsDistributedTracingEnabled = true; this.clientOptions.DistributedTracingOptions = options; return this; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs index 652b6b9e3f..6c44f06bf2 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs @@ -7,8 +7,7 @@ namespace Microsoft.Azure.Cosmos using System; /// - /// Open Telemetry Configuration - /// It needs to be public once AppInsight is ready + /// Options for configuring the distributed tracing and event tracing /// internal sealed class DistributedTracingOptions { @@ -23,9 +22,9 @@ internal sealed class DistributedTracingOptions internal static readonly TimeSpan DefaultQueryTimeoutThreshold = TimeSpan.FromMilliseconds(500); /// - /// Latency Threshold to generate () with Request diagnostics in distributing Tracing.

- /// If it is not set then by default it will generate () for query operation which are taking more than 500 ms and non-query operations taking more than 100 ms. + /// SDK generates (Event Source Name is "Azure-Cosmos-Operation-Request-Diagnostics") with Request Diagnostics String, If Operation level distributed tracing is not disabled i.e. ///
- public TimeSpan? DiagnosticsLatencyThreshold { get; set; } + /// If it is not set then, by default, it will generate for query operation which are taking more than 500 ms and non-query operations taking more than 100 ms. + public TimeSpan? LatencyThresholdForDiagnosticEvent { get; set; } } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs index e4db97bc3f..7649977fa0 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs @@ -22,9 +22,9 @@ public static bool IsTracingNeeded( { TimeSpan latencyThreshold; - if (config?.DiagnosticsLatencyThreshold != null) + if (config?.LatencyThresholdForDiagnosticEvent != null) { - latencyThreshold = config.DiagnosticsLatencyThreshold.Value; + latencyThreshold = config.LatencyThresholdForDiagnosticEvent.Value; } else { diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index 2cd6e3a481..6c88b3d5db 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -4,6 +4,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry { + using System; using global::Azure.Core.Pipeline; /// @@ -15,7 +16,7 @@ internal static class OpenTelemetryRecorderFactory /// Singleton to make sure we only have one instance of the DiagnosticScopeFactory and pattern matching of listener happens only once /// private static DiagnosticScopeFactory ScopeFactory { get; set; } - + public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, string containerName, string databaseName, @@ -23,11 +24,11 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, RequestOptions requestOptions, CosmosClientContext clientContext) { - if (clientContext is { ClientOptions.EnableDistributedTracing: true }) + if (clientContext is { ClientOptions.IsDistributedTracingEnabled: true }) { - ScopeFactory = new DiagnosticScopeFactory(clientNamespace: OpenTelemetryAttributeKeys.DiagnosticNamespace, - resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, - isActivityEnabled: true); + OpenTelemetryRecorderFactory.ScopeFactory ??= new DiagnosticScopeFactory(clientNamespace: OpenTelemetryAttributeKeys.DiagnosticNamespace, + resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, + isActivityEnabled: true); // If there is no source then it will return default otherwise a valid diagnostic scope DiagnosticScope scope = OpenTelemetryRecorderFactory diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index 6fd72499bb..e79fa6d301 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -1590,6 +1590,10 @@ maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), maxRetryAttemptsOnThrottledRequests: 3) .WithBulkExecution(true) + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( transportClient, (uri, resourceOperation, request) => TransportClientHelper.ReturnThrottledStoreResponseOnItemOperation( @@ -1599,12 +1603,6 @@ exceptionActivityId, errorMessage)))); - throttleClient.ClientOptions.EnableDistributedTracing = true; - throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; - ItemRequestOptions requestOptions = new ItemRequestOptions(); Container containerWithThrottleException = throttleClient.GetContainer( database.Id, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 7d6a68adca..2a3b1439ae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -160,7 +160,12 @@ string errorMessage = "Mock throttle exception" + Guid.NewGuid().ToString(); Guid exceptionActivityId = Guid.NewGuid(); using CosmosClient throttleClient = TestCommon.CreateCosmosClient(builder => - builder.WithThrottlingRetryOptions( + builder + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }) + .WithThrottlingRetryOptions( maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), maxRetryAttemptsOnThrottledRequests: 3) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( @@ -171,13 +176,7 @@ request, exceptionActivityId, errorMessage)))); - - throttleClient.ClientOptions.EnableDistributedTracing = true; - throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; - + ItemRequestOptions requestOptions = new ItemRequestOptions(); Container containerWithThrottleException = throttleClient.GetContainer( database.Id, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs index b0c605839e..d19b330d98 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -1,4 +1,8 @@ -namespace Microsoft.Azure.Cosmos.Tracing +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tracing { using System.Collections.Generic; using System.Diagnostics; @@ -13,14 +17,16 @@ internal static class AssertActivity public static void IsValid(Activity activity) { Assert.IsTrue(activity.OperationName == activity.DisplayName); - Assert.IsNotNull(activity.GetTagItem("db.cosmosdb.connection_mode")); + + Assert.IsFalse(string.IsNullOrEmpty(activity.GetTagItem("db.cosmosdb.connection_mode").ToString()), $"connection mode is emtpy for {activity.OperationName}"); + if (activity.GetTagItem("db.cosmosdb.connection_mode").ToString() == ConnectionMode.Gateway.ToString()) { - Assert.AreEqual(ActivityKind.Internal, activity.Kind); + Assert.AreEqual(ActivityKind.Internal, activity.Kind, $" Actual Kind is {activity.Kind} but expected is {ActivityKind.Internal} for {activity.OperationName}"); } - else + else if (activity.GetTagItem("db.cosmosdb.connection_mode").ToString() == ConnectionMode.Direct.ToString()) { - Assert.AreEqual(ActivityKind.Client, activity.Kind); + Assert.AreEqual(ActivityKind.Client, activity.Kind, $" Actual Kind is {activity.Kind} but expected is {ActivityKind.Client} for {activity.OperationName}"); } IList expectedTags = new List @@ -73,8 +79,10 @@ private static void AssertDatabaseAndContainerName(string name, KeyValuePair exceptionsForContainerAttribute = new List { "Operation.CreateDatabaseAsync", + "Operation.CreateDatabaseIfNotExistsAsync", "Operation.ReadAsync", - "Operation.DeleteAsync" + "Operation.DeleteAsync", + "Operation.DeleteStreamAsync" }; if ((tag.Key == OpenTelemetryAttributeKeys.ContainerName && !exceptionsForContainerAttribute.Contains(name)) || diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs index c46d8578b0..410843f3d2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs @@ -18,7 +18,7 @@ namespace Microsoft.Azure.Cosmos.Tests /// /// It is a custom listener for Activities and Event. It is used to validate the Activities generated by cosmosDb SDK. /// - public class CustomListener : + internal class CustomListener : EventListener, // Override Event Listener to capture Event source events IObserver>, // Override IObserver to capture Activity events IObserver, @@ -27,8 +27,8 @@ public class CustomListener : private readonly Func sourceNameFilter; private readonly string eventName; - private List subscriptions = new(); - private List Scopes { get; } = new(); + private ConcurrentBag subscriptions = new(); + private ConcurrentBag Scopes { get; } = new(); public static ConcurrentBag CollectedActivities { private set; get; } = new(); private static ConcurrentBag CollectedEvents { set; get; } = new(); @@ -75,7 +75,7 @@ public void OnNext(KeyValuePair value) string startSuffix = ".Start"; string stopSuffix = ".Stop"; string exceptionSuffix = ".Exception"; - + if (value.Key.EndsWith(startSuffix)) { string name = value.Key[..^startSuffix.Length]; @@ -181,7 +181,7 @@ public override void Dispose() return; } - List subscriptions; + ConcurrentBag subscriptions; lock (this.Scopes) { subscriptions = this.subscriptions; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index b91fc76b8b..22b4be1814 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -1,4 +1,8 @@ -namespace Microsoft.Azure.Cosmos.EmulatorTests.Tracing +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.EmulatorTests.Tracing { using System; using System.Collections.Generic; @@ -19,10 +23,7 @@ using Microsoft.Azure.Cosmos.Tracing; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; - using OpenTelemetry; - using Telemetry; using static Microsoft.Azure.Cosmos.SDK.EmulatorTests.TransportClientHelper; - using OpenTelemetry.Trace; [VisualStudio.TestTools.UnitTesting.TestClass] [TestCategory("UpdateContract")] @@ -34,55 +35,35 @@ public sealed class EndToEndTraceWriterBaselineTests : BaselineTests builder - .WithBulkExecution(true)); + .WithBulkExecution(true) + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + })); // Set a small retry count to reduce test time miscCosmosClient = TestCommon.CreateCosmosClient(builder => builder - .AddCustomHandlers(requestHandler)); - - client.ClientOptions.EnableDistributedTracing = true; - bulkClient.ClientOptions.EnableDistributedTracing = true; - miscCosmosClient.ClientOptions.EnableDistributedTracing = true; - - client.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; - - bulkClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; + .AddCustomHandlers(requestHandler) + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + })); - miscCosmosClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; - EndToEndTraceWriterBaselineTests.database = await client.CreateDatabaseAsync( Guid.NewGuid().ToString(), cancellationToken: default); @@ -114,8 +95,7 @@ public static async Task ClassCleanupAsync() await EndToEndTraceWriterBaselineTests.database.DeleteStreamAsync(); } - oTelTracerProvider?.Dispose(); - testListener?.Dispose(); + Util.DisposeOpenTelemetryAndCustomListeners(); await Task.Delay(5000); } @@ -994,7 +974,12 @@ public async Task PointOperationsExceptionsAsync() string errorMessage = "Mock throttle exception" + Guid.NewGuid().ToString(); Guid exceptionActivityId = Guid.NewGuid(); using CosmosClient throttleClient = TestCommon.CreateCosmosClient(builder => - builder.WithThrottlingRetryOptions( + builder + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }) + .WithThrottlingRetryOptions( maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), maxRetryAttemptsOnThrottledRequests: 3) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( @@ -1005,13 +990,7 @@ public async Task PointOperationsExceptionsAsync() request, exceptionActivityId, errorMessage)))); - - throttleClient.ClientOptions.EnableDistributedTracing = true; - throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; - + ItemRequestOptions requestOptions = new ItemRequestOptions(); Container containerWithThrottleException = throttleClient.GetContainer( database.Id, @@ -1284,6 +1263,10 @@ public async Task BulkOperationsAsync() maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), maxRetryAttemptsOnThrottledRequests: 3) .WithBulkExecution(true) + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( transportClient, (uri, resourceOperation, request) => TransportClientHelper.ReturnThrottledStoreResponseOnItemOperation( @@ -1293,12 +1276,6 @@ public async Task BulkOperationsAsync() exceptionActivityId, errorMessage)))); - throttleClient.ClientOptions.EnableDistributedTracing = true; - throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; - ItemRequestOptions requestOptions = new ItemRequestOptions(); Container containerWithThrottleException = throttleClient.GetContainer( database.Id, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs index 265e9542ef..8cfa5be33b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs @@ -130,7 +130,8 @@ internal static CosmosClient CreateCosmosClient( internal static CosmosClient CreateCosmosClient( bool useGateway, - Action customizeClientBuilder = null) + Action customizeClientBuilder = null, + bool enableDistributingTracing = false) { CosmosClientBuilder cosmosClientBuilder = GetDefaultConfiguration(); @@ -140,6 +141,14 @@ internal static CosmosClient CreateCosmosClient( { cosmosClientBuilder.WithConnectionModeGateway(); } + + if(enableDistributingTracing) + { + cosmosClientBuilder.WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }); + } return cosmosClientBuilder.Build(); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TransportClientHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TransportClientHelper.cs index d701c069c0..f34135b695 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TransportClientHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TransportClientHelper.cs @@ -81,21 +81,20 @@ internal static Container GetContainerWithIntercepter( builder.WithSessionContainer(sessionContainer); } + if (enableDistributingTracing) + { + builder.WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(.0001) + }); + } + builder.WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( transportClient, interceptor, interceptorWithStoreResult)); }); - - if(enableDistributingTracing) - { - clientWithIntercepter.ClientOptions.EnableDistributedTracing = true; - clientWithIntercepter.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(.0001) - }; - } - + return clientWithIntercepter.GetContainer(databaseId, containerId); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs index 4533b2b562..bdb688673d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs @@ -14,10 +14,14 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Services.Management.Tests; using Microsoft.Azure.Cosmos.Telemetry; + using Microsoft.Azure.Cosmos.Tests; + using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Client; using Microsoft.Azure.Documents.Collections; using Microsoft.VisualStudio.TestTools.UnitTesting; + using OpenTelemetry; + using OpenTelemetry.Trace; internal enum DocumentClientType { @@ -533,6 +537,40 @@ internal static void DisableClientTelemetryEnvironmentVariables() Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, null); } + private static TracerProvider OTelTracerProvider; + private static CustomListener TestListener; + + internal static CustomListener ConfigureOpenTelemetryAndCustomListeners() + { + AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", true); + + // Open Telemetry Listener + Util.OTelTracerProvider = Sdk.CreateTracerProviderBuilder() + .AddCustomOtelExporter() // use any exporter here + .AddSource($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*") // Right now, it will capture only "Azure.Cosmos.Operation" + .Build(); + + // Custom Listener + Util.TestListener = new CustomListener($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*", "Azure-Cosmos-Operation-Request-Diagnostics"); + + return Util.TestListener; + + } + + internal static void DisposeOpenTelemetryAndCustomListeners() + { + // Open Telemetry Listener + Util.OTelTracerProvider?.Dispose(); + + // Custom Listener + Util.TestListener?.Dispose(); + + Util.OTelTracerProvider = null; + Util.TestListener = null; + + AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", false); + } + /// /// Enables traces for local debugging /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index add1fce30e..c5bb91849b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -314,6 +314,31 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.CosmosClientOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Boolean get_IsDistributedTracingEnabled()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_IsDistributedTracingEnabled();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean IsDistributedTracingEnabled": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean IsDistributedTracingEnabled;CanRead:True;CanWrite:True;Boolean get_IsDistributedTracingEnabled();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_IsDistributedTracingEnabled(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_IsDistributedTracingEnabled(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_IsDistributedTracingEnabled(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.Fluent.ChangeFeedPolicyDefinition;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { @@ -336,6 +361,17 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithDistributedTracing(Boolean)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithDistributedTracing(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.Linq.CosmosLinqExtensions;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index e39bb8d0f3..986b9cc997 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -159,9 +159,9 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() portReuseMode, enableTcpConnectionEndpointRediscovery) .WithApplicationPreferredRegions(preferredLocations) - .WithDistributingTracing(new DistributedTracingOptions + .WithDistributedTracingOptions(new DistributedTracingOptions { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(100) + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(100) }); cosmosClient = cosmosClientBuilder.Build(new MockDocumentClient()); @@ -174,8 +174,8 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.AreEqual(portReuseMode, clientOptions.PortReuseMode); Assert.IsTrue(clientOptions.EnableTcpConnectionEndpointRediscovery); CollectionAssert.AreEqual(preferredLocations.ToArray(), clientOptions.ApplicationPreferredRegions.ToArray()); - Assert.AreEqual(TimeSpan.FromMilliseconds(100), clientOptions.DistributedTracingOptions.DiagnosticsLatencyThreshold); - Assert.IsFalse(clientOptions.EnableDistributedTracing); + Assert.AreEqual(TimeSpan.FromMilliseconds(100), clientOptions.DistributedTracingOptions.LatencyThresholdForDiagnosticEvent); + Assert.IsTrue(clientOptions.IsDistributedTracingEnabled); //Verify GetConnectionPolicy returns the correct values policy = clientOptions.GetConnectionPolicy(clientId: 0); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs index 98f4d62954..698b99524e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs @@ -38,7 +38,7 @@ public void CheckReturnFalseOnSuccessAndLowerLatencyThanConfiguredConfig() DistributedTracingOptions distributedTracingOptions = new DistributedTracingOptions { - DiagnosticsLatencyThreshold = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) + LatencyThresholdForDiagnosticEvent = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) }; OpenTelemetryAttributes response = new OpenTelemetryAttributes @@ -51,7 +51,7 @@ public void CheckReturnFalseOnSuccessAndLowerLatencyThanConfiguredConfig() DiagnosticsFilterHelper .IsTracingNeeded(distributedTracingOptions, OperationType.Read, response), $" Response time is {response.Diagnostics.GetClientElapsedTime().Milliseconds}ms " + - $"and Configured threshold value is {distributedTracingOptions.DiagnosticsLatencyThreshold.Value.Milliseconds}ms " + + $"and Configured threshold value is {distributedTracingOptions.LatencyThresholdForDiagnosticEvent.Value.Milliseconds}ms " + $"and Is response Success : {response.StatusCode.IsSuccess()}" ); } @@ -63,7 +63,7 @@ public void CheckReturnTrueOnFailedStatusCode() DistributedTracingOptions distributedTracingOptions = new DistributedTracingOptions { - DiagnosticsLatencyThreshold = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) + LatencyThresholdForDiagnosticEvent = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) }; OpenTelemetryAttributes response = new OpenTelemetryAttributes @@ -76,7 +76,7 @@ public void CheckReturnTrueOnFailedStatusCode() DiagnosticsFilterHelper .IsTracingNeeded(distributedTracingOptions, OperationType.Read, response), $" Response time is {response.Diagnostics.GetClientElapsedTime().Milliseconds}ms " + - $"and Configured threshold value is {distributedTracingOptions.DiagnosticsLatencyThreshold.Value.Milliseconds}ms " + + $"and Configured threshold value is {distributedTracingOptions.LatencyThresholdForDiagnosticEvent.Value.Milliseconds}ms " + $"and Is response Success : {response.StatusCode.IsSuccess()}"); }