diff --git a/Microsoft.Azure.Cosmos/src/CosmosClient.cs b/Microsoft.Azure.Cosmos/src/CosmosClient.cs
index f054de3838..3f9770ac64 100644
--- a/Microsoft.Azure.Cosmos/src/CosmosClient.cs
+++ b/Microsoft.Azure.Cosmos/src/CosmosClient.cs
@@ -1438,6 +1438,8 @@ private int DecrementNumberOfActiveClients()
// In case dispose is called multiple times. Check if at least 1 active client is there
if (NumberOfActiveClients > 0)
{
+ CosmosOperationMeter.RemoveInstanceCount(this.Endpoint);
+
return Interlocked.Decrement(ref NumberOfActiveClients);
}
diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs
index d05a840f0e..5fd942dff8 100644
--- a/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs
+++ b/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs
@@ -53,5 +53,13 @@ public class CosmosClientTelemetryOptions
/// but has to beware that customer data may be shown when the later option is chosen. It's the user's responsibility to sanitize the queries if necessary.
///
public QueryTextMode QueryTextMode { get; set; } = QueryTextMode.None;
+
+ ///
+ /// Indicates whether client-side metrics collection is enabled or disabled.
+ /// When set to true, the application will capture and report client metrics such as request counts, latencies, errors, and other key performance indicators.
+ /// If false, no metrics related to the client will be gathered or reported.
+ /// Metrics data can be published to a monitoring system like Prometheus or Azure Monitor, depending on the configured metrics provider.
+ ///
+ public bool IsClientMetricsEnabled { get; set; }
}
}
\ No newline at end of file
diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs
index 1a064d0024..144957de21 100644
--- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs
+++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs
@@ -955,6 +955,13 @@ internal virtual void Initialize(Uri serviceEndpoint,
// Loading VM Information (non blocking call and initialization won't fail if this call fails)
VmMetadataApiHandler.TryInitialize(this.httpClient);
+ if (this.cosmosClientTelemetryOptions.IsClientMetricsEnabled)
+ {
+ CosmosOperationMeter.Initialize();
+
+ CosmosOperationMeter.AddInstanceCount(this.ServiceEndpoint);
+ }
+
// Starting ClientTelemetry Job
this.telemetryToServiceHelper = TelemetryToServiceHelper.CreateAndInitializeClientConfigAndTelemetryJob(this.clientId,
this.ConnectionPolicy,
diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs
index 37fe60f89e..79a47158e9 100644
--- a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs
+++ b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs
@@ -13,6 +13,7 @@ namespace Microsoft.Azure.Cosmos
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+ using global::Azure;
using Microsoft.Azure.Cosmos.Handlers;
using Microsoft.Azure.Cosmos.Resource.CosmosExceptions;
using Microsoft.Azure.Cosmos.Routing;
@@ -498,22 +499,24 @@ private async Task RunWithDiagnosticsHelperAsync(
RequestOptions requestOptions,
ResourceType? resourceType = null)
{
+ Func getOperationName = () =>
+ {
+ // If opentelemetry is not enabled then return null operation name, so that no activity is created.
+ if (openTelemetry == null)
+ {
+ return null;
+ }
+
+ if (resourceType is not null && this.IsBulkOperationSupported(resourceType.Value, operationType))
+ {
+ return OpenTelemetryConstants.Operations.ExecuteBulkPrefix + openTelemetry.Item1;
+ }
+ return openTelemetry.Item1;
+ };
+
using (OpenTelemetryCoreRecorder recorder =
OpenTelemetryRecorderFactory.CreateRecorder(
- getOperationName: () =>
- {
- // If opentelemetry is not enabled then return null operation name, so that no activity is created.
- if (openTelemetry == null)
- {
- return null;
- }
-
- if (resourceType is not null && this.IsBulkOperationSupported(resourceType.Value, operationType))
- {
- return OpenTelemetryConstants.Operations.ExecuteBulkPrefix + openTelemetry.Item1;
- }
- return openTelemetry.Item1;
- },
+ getOperationName: getOperationName,
containerName: containerName,
databaseName: databaseName,
operationType: operationType,
@@ -525,20 +528,30 @@ private async Task RunWithDiagnosticsHelperAsync(
try
{
TResult result = await task(trace).ConfigureAwait(false);
- if (openTelemetry != null && recorder.IsEnabled)
+ // Checks if OpenTelemetry is configured for this operation and either Trace or Metrics are enabled by customer
+ if (openTelemetry != null
+ && (!this.ClientOptions.CosmosClientTelemetryOptions.DisableDistributedTracing || this.ClientOptions.CosmosClientTelemetryOptions.IsClientMetricsEnabled))
{
- // Record request response information
+ // Extracts and records telemetry data from the result of the operation.
OpenTelemetryAttributes response = openTelemetry?.Item2(result);
+
+ // Records the telemetry attributes for Distributed Tracing (if enabled)
recorder.Record(response);
- }
+ // Records metrics such as request units, latency, and item count for the operation.
+ CosmosOperationMeter.RecordTelemetry(getOperationName: getOperationName,
+ accountName: this.client.Endpoint,
+ containerName: containerName,
+ databaseName: databaseName,
+ attributes: response);
+ }
return result;
}
catch (OperationCanceledException oe) when (!(oe is CosmosOperationCanceledException))
{
CosmosOperationCanceledException operationCancelledException = new CosmosOperationCanceledException(oe, trace);
recorder.MarkFailed(operationCancelledException);
-
+
throw operationCancelledException;
}
catch (ObjectDisposedException objectDisposed) when (!(objectDisposed is CosmosObjectDisposedException))
@@ -563,7 +576,16 @@ private async Task RunWithDiagnosticsHelperAsync(
catch (Exception ex)
{
recorder.MarkFailed(ex);
-
+ if (openTelemetry != null && ex is CosmosException cosmosException)
+ {
+ // Records telemetry data related to the exception.
+ CosmosOperationMeter.RecordTelemetry(getOperationName: getOperationName,
+ accountName: this.client.Endpoint,
+ containerName: containerName,
+ databaseName: databaseName,
+ ex: cosmosException);
+ }
+
throw;
}
}
diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbClientMetrics.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbClientMetrics.cs
new file mode 100644
index 0000000000..f295022504
--- /dev/null
+++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbClientMetrics.cs
@@ -0,0 +1,143 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ------------------------------------------------------------
+
+namespace Microsoft.Azure.Cosmos
+{
+ ///
+ /// The CosmosDbClientMetrics class provides constants related to OpenTelemetry metrics for Azure Cosmos DB.
+ /// These metrics are useful for tracking various aspects of Cosmos DB client operations and compliant with Open Telemetry Semantic Conventions
+ /// It defines standardized names, units, descriptions, and histogram buckets for measuring and monitoring performance through OpenTelemetry.
+ ///
+ public sealed class CosmosDbClientMetrics
+ {
+ ///
+ /// OperationMetrics
+ ///
+ public static class OperationMetrics
+ {
+ ///
+ /// the name of the operation meter
+ ///
+ public const string MeterName = "Azure.Cosmos.Client.Operation";
+
+ ///
+ /// Version of the operation meter
+ ///
+ public const string Version = "1.0.0";
+
+ ///
+ /// Metric Names
+ ///
+ public static class Name
+ {
+ ///
+ /// Total request units per operation (sum of RUs for all requested needed when processing an operation)
+ ///
+ public const string RequestCharge = "db.client.cosmosdb.operation.request_charge";
+
+ ///
+ /// Total end-to-end duration of the operation
+ ///
+ public const string Latency = "db.client.operation.duration";
+
+ ///
+ /// For feed operations (query, readAll, readMany, change feed) batch operations this meter capture the actual item count in responses from the service.
+ ///
+ public const string RowCount = "db.client.response.row_count";
+
+ ///
+ /// Number of active SDK client instances.
+ ///
+ public const string ActiveInstances = "db.client.cosmosdb.active_instance.count";
+ }
+
+ ///
+ /// Unit for metrics
+ ///
+ public static class Unit
+ {
+ ///
+ /// Unit representing a simple count
+ ///
+ public const string Count = "#";
+
+ ///
+ /// Unit representing time in seconds
+ ///
+ public const string Sec = "s";
+
+ ///
+ /// Unit representing request units
+ ///
+ public const string RequestUnit = "# RU";
+
+ }
+
+ ///
+ /// Provides descriptions for metrics.
+ ///
+ public static class Description
+ {
+ ///
+ /// Description for operation duration
+ ///
+ public const string Latency = "Total end-to-end duration of the operation";
+
+ ///
+ /// Description for total request units per operation
+ ///
+ public const string RequestCharge = "Total request units per operation (sum of RUs for all requested needed when processing an operation)";
+
+ ///
+ /// Description for the item count metric in responses
+ ///
+ public const string RowCount = "For feed operations (query, readAll, readMany, change feed) batch operations this meter capture the actual item count in responses from the service";
+
+ ///
+ /// Description for the active SDK client instances metric
+ ///
+ public const string ActiveInstances = "Number of active SDK client instances.";
+ }
+ }
+
+ ///
+ /// Buckets
+ ///
+ public static class HistogramBuckets
+ {
+ ///
+ /// ExplicitBucketBoundaries for "db.cosmosdb.operation.request_charge" Metrics
+ ///
+ ///
+ /// 1, 5, 10: Low Usage Levels, These smaller buckets allow for precise tracking of operations that consume a minimal number of Request Units. This is important for lightweight operations, such as basic read requests or small queries, where resource utilization should be optimized. Monitoring these low usage levels can help ensure that the application is not inadvertently using more resources than necessary.
+ /// 25, 50: Moderate Usage Levels, These ranges capture more moderate operations, which are typical in many applications. For example, queries that return a reasonable amount of data or perform standard CRUD operations may fall within these limits. Identifying usage patterns in these buckets can help detect efficiency issues in routine operations.
+ /// 100, 250: Higher Usage Levels, These boundaries represent operations that may require significant resources, such as complex queries or larger transactions. Monitoring RUs in these ranges can help identify performance bottlenecks or costly queries that might lead to throttling.
+ /// 500, 1000: Very High Usage Levels, These buckets capture operations that consume a substantial number of Request Units, which may indicate potentially expensive queries or batch processes. Understanding the frequency and patterns of such high RU usage can be critical in optimizing performance and ensuring the application remains within provisioned throughput limits.
+ ///
+ public static readonly double[] RequestUnitBuckets = new double[] { 1, 5, 10, 25, 50, 100, 250, 500, 1000};
+
+ ///
+ /// ExplicitBucketBoundaries for "db.client.operation.duration" Metrics.
+ ///
+ ///
+ /// 0.001, 0.005, 0.010 seconds: Higher Precision at Sub-Millisecond Levels, For high-performance workloads, especially when dealing with microservices or low-latency queries.
+ /// 0.050, 0.100, 0.200 seconds: Granularity for Standard Web Applications, These values allow detailed tracking for latencies between 50ms and 200ms, which are common in web applications. Fine-grained buckets in this range help in identifying performance issues before they grow critical, while covering the typical response times expected in Cosmos DB.
+ /// 0.500, 1.000 seconds: Wider Range for Intermediate Latencies, Operations that take longer, in the range of 500ms to 1 second, are still important for performance monitoring. By capturing these values, you maintain awareness of potential bottlenecks or slower requests that may need optimization.
+ /// 2.000, 5.000 seconds: Capturing Outliers and Slow Queries, It’s important to track outliers that might go beyond 1 second. Having buckets for 2 and 5 seconds enables identification of rare, long-running operations that may require further investigation.
+ ///
+ public static readonly double[] RequestLatencyBuckets = new double[] { 0.001, 0.005, 0.010, 0.050, 0.100, 0.200, 0.500, 1.000, 2.000, 5.000 };
+
+ ///
+ /// ExplicitBucketBoundaries for "db.client.response.row_count" Metrics
+ ///
+ ///
+ /// 10, 50, 100: Small Response Sizes, These buckets are useful for capturing scenarios where only a small number of items are returned. Such small queries are common in real-time or interactive applications where performance and quick responses are critical. They also help in tracking the efficiency of operations that should return minimal data, minimizing resource usage.
+ /// 250, 500, 1000: Moderate Response Sizes, These values represent typical workloads where moderate amounts of data are returned in each query. This is useful for applications that need to return more information, such as data analytics or reporting systems. Tracking these ranges helps identify whether the system is optimized for these relatively larger data sets and if they lead to any performance degradation.
+ /// 2000, 5000: Larger Response Sizes, These boundaries capture scenarios where the query returns large datasets, often used in batch processing or in-depth analytical queries. These larger page sizes can potentially increase memory or CPU usage and may lead to longer query execution times, making it important to track performance in these ranges.
+ /// 10000: Very Large Response Sizes (Outliers), This boundary is included to capture rare, very large response sizes. Such queries can put significant strain on system resources, including memory, CPU, and network bandwidth, and can often lead to performance issues such as high latency or even network drops.
+ ///
+ public static readonly double[] RowCountBuckets = new double[] { 1, 10, 50, 100, 250, 500, 1000, 2000, 5000, 10000 };
+ }
+ }
+}
diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosOperationMeter.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosOperationMeter.cs
new file mode 100644
index 0000000000..fbdcd1ee33
--- /dev/null
+++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosOperationMeter.cs
@@ -0,0 +1,211 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ------------------------------------------------------------
+
+namespace Microsoft.Azure.Cosmos.Telemetry
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Metrics;
+
+ ///
+ /// CosmosOperationMeter is a utility class responsible for collecting and recording telemetry metrics related to Cosmos DB operations.
+ /// It includes histograms and counters that capture metrics like request latency, request units, item count, and active instances.
+ ///
+ internal static class CosmosOperationMeter
+ {
+ ///
+ /// Meter instance for capturing various metrics related to Cosmos DB operations.
+ ///
+ internal static Meter OperationMeter = new Meter(CosmosDbClientMetrics.OperationMetrics.MeterName, CosmosDbClientMetrics.OperationMetrics.Version);
+
+ ///
+ /// Histogram to record request latency (in seconds) for Cosmos DB operations.
+ ///
+ internal static Histogram RequestLatencyHistogram = null;
+
+ ///
+ /// Histogram to record request units consumed during Cosmos DB operations.
+ ///
+ internal static Histogram RequestUnitsHistogram = null;
+
+ ///
+ /// Histogram to record the actual number of items involved in the operation.
+ ///
+ internal static Histogram ActualItemHistogram = null;
+
+ ///
+ /// UpDownCounter to track the number of active instances interacting with Cosmos DB.
+ ///
+ internal static UpDownCounter ActiveInstanceCounter = null;
+
+ ///
+ /// Flag to check if metrics is enabled
+ ///
+ private static bool IsEnabled = false;
+
+ ///
+ /// Initializes the histograms and counters for capturing Cosmos DB metrics.
+ ///
+ internal static void Initialize()
+ {
+ // If already initialized, do not initialize again
+ if (IsEnabled)
+ {
+ return;
+ }
+
+ CosmosOperationMeter.RequestLatencyHistogram ??= OperationMeter.CreateHistogram(name: CosmosDbClientMetrics.OperationMetrics.Name.Latency,
+ unit: CosmosDbClientMetrics.OperationMetrics.Unit.Sec,
+ description: CosmosDbClientMetrics.OperationMetrics.Description.Latency);
+
+ CosmosOperationMeter.RequestUnitsHistogram ??= OperationMeter.CreateHistogram(name: CosmosDbClientMetrics.OperationMetrics.Name.RequestCharge,
+ unit: CosmosDbClientMetrics.OperationMetrics.Unit.RequestUnit,
+ description: CosmosDbClientMetrics.OperationMetrics.Description.RequestCharge);
+
+ CosmosOperationMeter.ActualItemHistogram ??= OperationMeter.CreateHistogram(name: CosmosDbClientMetrics.OperationMetrics.Name.RowCount,
+ unit: CosmosDbClientMetrics.OperationMetrics.Unit.Count,
+ description: CosmosDbClientMetrics.OperationMetrics.Description.RowCount);
+
+ CosmosOperationMeter.ActiveInstanceCounter ??= OperationMeter.CreateUpDownCounter(name: CosmosDbClientMetrics.OperationMetrics.Name.ActiveInstances,
+ unit: CosmosDbClientMetrics.OperationMetrics.Unit.Count,
+ description: CosmosDbClientMetrics.OperationMetrics.Description.ActiveInstances);
+
+ IsEnabled = true;
+ }
+
+ ///
+ /// Records telemetry data related to Cosmos DB operations. This includes request latency, request units, and item counts.
+ ///
+ /// Generate operation name
+ /// The URI of the Cosmos DB account.
+ /// The name of the container involved in the operation.
+ /// The name of the database involved in the operation.
+ /// Optional OpenTelemetry attributes related to the operation.
+ /// Optional exception object to capture error details.
+ internal static void RecordTelemetry(Func getOperationName,
+ Uri accountName,
+ string containerName,
+ string databaseName,
+ OpenTelemetryAttributes attributes = null,
+ CosmosException ex = null)
+ {
+ if (!IsEnabled)
+ {
+ return;
+ }
+
+ Func[]> dimensionsFunc = () => new KeyValuePair[]
+ {
+ new KeyValuePair(OpenTelemetryAttributeKeys.DbSystemName, OpenTelemetryCoreRecorder.CosmosDb),
+ new KeyValuePair(OpenTelemetryAttributeKeys.ContainerName, containerName),
+ new KeyValuePair(OpenTelemetryAttributeKeys.DbName, databaseName),
+ new KeyValuePair(OpenTelemetryAttributeKeys.ServerAddress, accountName.Host),
+ new KeyValuePair(OpenTelemetryAttributeKeys.ServerPort, accountName.Port),
+ new KeyValuePair(OpenTelemetryAttributeKeys.DbOperation, getOperationName()),
+ new KeyValuePair(OpenTelemetryAttributeKeys.StatusCode, (int)(attributes?.StatusCode ?? ex?.StatusCode)),
+ new KeyValuePair(OpenTelemetryAttributeKeys.SubStatusCode, attributes?.SubStatusCode ?? ex?.SubStatusCode),
+ new KeyValuePair(OpenTelemetryAttributeKeys.ConsistencyLevel, attributes?.ConsistencyLevel ?? ex?.Headers?.ConsistencyLevel),
+ new KeyValuePair(OpenTelemetryAttributeKeys.Region, string.Join(",", attributes.Diagnostics.GetContactedRegions())),
+ new KeyValuePair(OpenTelemetryAttributeKeys.ErrorType, ex?.Message)
+ };
+
+ CosmosOperationMeter.RecordActualItemCount(attributes?.ItemCount ?? ex?.Headers?.ItemCount, dimensionsFunc);
+ CosmosOperationMeter.RecordRequestUnit(attributes?.RequestCharge ?? ex?.Headers?.RequestCharge, dimensionsFunc);
+ CosmosOperationMeter.RecordRequestLatency(attributes?.Diagnostics?.GetClientElapsedTime() ?? ex?.Diagnostics?.GetClientElapsedTime(), dimensionsFunc);
+ }
+
+ ///
+ /// Records the actual item count metric for a Cosmos DB operation.
+ ///
+ /// The number of items returned or affected by the operation.
+ /// A function providing telemetry dimensions for the metric.
+ internal static void RecordActualItemCount(string actualItemCount, Func[]> dimensionsFunc)
+ {
+ if (!IsEnabled || CosmosOperationMeter.ActualItemHistogram == null ||
+ !CosmosOperationMeter.ActualItemHistogram.Enabled || string.IsNullOrEmpty(actualItemCount))
+ {
+ return;
+ }
+
+ CosmosOperationMeter.ActualItemHistogram.Record(Convert.ToInt32(actualItemCount), dimensionsFunc());
+ }
+
+ ///
+ /// Records the request units (RU/s) consumed by the operation.
+ ///
+ /// The RU/s value for the operation.
+ /// A function providing telemetry dimensions for the metric.
+ internal static void RecordRequestUnit(double? requestCharge, Func[]> dimensionsFunc)
+ {
+ if (!IsEnabled || CosmosOperationMeter.RequestUnitsHistogram == null ||
+ !CosmosOperationMeter.RequestUnitsHistogram.Enabled || !requestCharge.HasValue)
+ {
+ return;
+ }
+
+ CosmosOperationMeter.RequestUnitsHistogram.Record(requestCharge.Value, dimensionsFunc());
+ }
+
+ ///
+ /// Records the latency (in seconds) for a Cosmos DB operation.
+ ///
+ /// The latency of the operation.
+ /// A function providing telemetry dimensions for the metric.
+ internal static void RecordRequestLatency(TimeSpan? requestLatency, Func[]> dimensionsFunc)
+ {
+ if (!IsEnabled || CosmosOperationMeter.ActiveInstanceCounter == null ||
+ !CosmosOperationMeter.ActiveInstanceCounter.Enabled || !requestLatency.HasValue)
+ {
+ return;
+ }
+
+ CosmosOperationMeter.RequestLatencyHistogram.Record(requestLatency.Value.TotalMilliseconds / 1000, dimensionsFunc());
+ }
+
+ ///
+ /// Increases the count of active Cosmos DB instances.
+ ///
+ /// The URI of the account endpoint.
+ internal static void AddInstanceCount(Uri accountEndpoint)
+ {
+ if (!IsEnabled || CosmosOperationMeter.ActiveInstanceCounter == null ||
+ !CosmosOperationMeter.ActiveInstanceCounter.Enabled)
+ {
+ return;
+ }
+
+ KeyValuePair[] dimensions = new[]
+ {
+ new KeyValuePair(OpenTelemetryAttributeKeys.DbSystemName, OpenTelemetryCoreRecorder.CosmosDb),
+ new KeyValuePair(OpenTelemetryAttributeKeys.ServerAddress, accountEndpoint.Host),
+ new KeyValuePair(OpenTelemetryAttributeKeys.ServerPort, accountEndpoint.Port)
+ };
+
+ Console.WriteLine("active instance metriuc collected");
+ CosmosOperationMeter.ActiveInstanceCounter.Add(1, dimensions);
+ }
+
+ ///
+ /// Decreases the count of active Cosmos DB instances.
+ ///
+ /// The URI of the account endpoint.
+ internal static void RemoveInstanceCount(Uri accountEndpoint)
+ {
+ if (!IsEnabled || CosmosOperationMeter.ActiveInstanceCounter == null ||
+ !CosmosOperationMeter.ActiveInstanceCounter.Enabled)
+ {
+ return;
+ }
+
+ KeyValuePair[] dimensions = new[]
+ {
+ new KeyValuePair(OpenTelemetryAttributeKeys.DbSystemName, OpenTelemetryCoreRecorder.CosmosDb),
+ new KeyValuePair(OpenTelemetryAttributeKeys.ServerAddress, accountEndpoint.Host),
+ new KeyValuePair(OpenTelemetryAttributeKeys.ServerPort, accountEndpoint.Port)
+ };
+
+ CosmosOperationMeter.ActiveInstanceCounter.Add(-1, dimensions);
+ }
+ }
+}
diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs
index 2d01b8864d..a179374314 100644
--- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs
+++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs
@@ -58,6 +58,11 @@ internal sealed class OpenTelemetryAttributeKeys
///
public const string ServerAddress = "server.address";
+ ///
+ /// Represents the server port.
+ ///
+ public const string ServerPort = "server.port";
+
// Cosmos DB specific attributes
///
@@ -158,5 +163,10 @@ internal sealed class OpenTelemetryAttributeKeys
/// Represents the stack trace of the exception.
///
public const string ExceptionStacktrace = "exception.stacktrace";
+
+ ///
+ /// Represents the type of error.
+ ///
+ public const string ErrorType = "error.type";
}
}
diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs
index f606fef57e..85b5d58352 100644
--- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs
+++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs
@@ -17,7 +17,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry
///
internal struct OpenTelemetryCoreRecorder : IDisposable
{
- private const string CosmosDb = "cosmosdb";
+ internal const string CosmosDb = "cosmosdb";
private static readonly string otelStabilityMode = Environment.GetEnvironmentVariable("OTEL_SEMCONV_STABILITY_OPT_IN");
@@ -157,6 +157,7 @@ public void Record(
this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbName, databaseName);
this.scope.AddAttribute(OpenTelemetryAttributeKeys.ContainerName, containerName);
this.scope.AddAttribute(OpenTelemetryAttributeKeys.ServerAddress, clientContext.Client?.Endpoint?.Host);
+ this.scope.AddAttribute(OpenTelemetryAttributeKeys.ServerPort, clientContext.Client?.Endpoint?.Port.ToString());
this.scope.AddAttribute(OpenTelemetryAttributeKeys.UserAgent, clientContext.UserAgent);
}
else
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs
index 1813700e05..e9111e6327 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs
@@ -15,7 +15,7 @@
using Moq.Protected;
[TestClass]
- public class ClientCreateAndInitializeTest : BaseCosmosClientHelper
+ public class OpenTelemetryMetricsTest : BaseCosmosClientHelper
{
private ContainerInternal Container = null;
private const string PartitionKey = "/pk";
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Metrics/CustomMetricExporter.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Metrics/CustomMetricExporter.cs
new file mode 100644
index 0000000000..c8b2dc0d21
--- /dev/null
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Metrics/CustomMetricExporter.cs
@@ -0,0 +1,39 @@
+//------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------
+
+namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests.Metrics
+{
+ using OpenTelemetry.Metrics;
+ using OpenTelemetry;
+ using System.Collections.Generic;
+ using System.Threading;
+
+ public class CustomMetricExporter : BaseExporter
+ {
+ private readonly ManualResetEventSlim manualResetEventSlim = null;
+
+ public static Dictionary ActualMetrics = new Dictionary();
+
+ public CustomMetricExporter(ManualResetEventSlim manualResetEventSlim)
+ {
+ this.manualResetEventSlim = manualResetEventSlim;
+ }
+
+ // This method will be called periodically by OpenTelemetry SDK
+ public override ExportResult Export(in Batch batch)
+ {
+ foreach (Metric metric in batch)
+ {
+ ActualMetrics.TryAdd(metric.Name, metric.MetricType);
+ }
+
+ if (ActualMetrics.Count > 0)
+ {
+ this.manualResetEventSlim.Set();
+ }
+
+ return ExportResult.Success;
+ }
+ }
+}
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Metrics/OpenTelemetryMetricsTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Metrics/OpenTelemetryMetricsTest.cs
new file mode 100644
index 0000000000..4c614ddc47
--- /dev/null
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Metrics/OpenTelemetryMetricsTest.cs
@@ -0,0 +1,118 @@
+//------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------
+
+namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests.Metrics
+{
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using OpenTelemetry.Metrics;
+ using OpenTelemetry;
+ using OpenTelemetry.Resources;
+ using System.Threading;
+ using System.Collections.Generic;
+ using System.Linq;
+
+ [TestClass]
+ public class OpenTelemetryMetricsTest : BaseCosmosClientHelper
+ {
+ private const int AggregatingInterval = 1000;
+ private readonly ManualResetEventSlim manualResetEventSlim = new ManualResetEventSlim(false);
+ private static readonly Dictionary expectedMetrics = new Dictionary()
+ {
+ { "db.client.operation.duration", MetricType.Histogram },
+ { "db.client.response.row_count", MetricType.Histogram},
+ { "db.client.cosmosdb.operation.request_charge", MetricType.Histogram },
+ { "db.client.cosmosdb.active_instance.count", MetricType.LongSumNonMonotonic }
+ };
+
+ private MeterProvider meterProvider;
+ [TestInitialize]
+ public async Task Init()
+ {
+ // Initialize OpenTelemetry MeterProvider
+ this.meterProvider = Sdk
+ .CreateMeterProviderBuilder()
+ .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("Azure Cosmos DB Operation Level Metrics"))
+ .AddMeter(CosmosDbClientMetrics.OperationMetrics.MeterName)
+ .AddView(
+ instrumentName: CosmosDbClientMetrics.OperationMetrics.Name.RequestCharge,
+ metricStreamConfiguration: new ExplicitBucketHistogramConfiguration
+ {
+ Boundaries = CosmosDbClientMetrics.HistogramBuckets.RequestUnitBuckets
+ })
+ .AddView(
+ instrumentName: CosmosDbClientMetrics.OperationMetrics.Name.Latency,
+ metricStreamConfiguration: new ExplicitBucketHistogramConfiguration
+ {
+ Boundaries = CosmosDbClientMetrics.HistogramBuckets.RequestLatencyBuckets
+ })
+ .AddView(
+ instrumentName: CosmosDbClientMetrics.OperationMetrics.Name.RowCount,
+ metricStreamConfiguration: new ExplicitBucketHistogramConfiguration
+ {
+ Boundaries = CosmosDbClientMetrics.HistogramBuckets.RowCountBuckets
+ })
+ .AddReader(new PeriodicExportingMetricReader(exporter: new CustomMetricExporter(this.manualResetEventSlim), exportIntervalMilliseconds: AggregatingInterval))
+ .Build();
+
+ await base.TestInit((builder) => builder.WithClientTelemetryOptions(new CosmosClientTelemetryOptions()
+ {
+ IsClientMetricsEnabled = true
+ }));
+ }
+
+ [TestCleanup]
+ public async Task Cleanup()
+ {
+ this.meterProvider.Dispose();
+
+ await base.TestCleanup();
+ }
+
+ [TestMethod]
+ public async Task OperationLevelMetricsGenerationTest()
+ {
+ Container container = await this.database.CreateContainerIfNotExistsAsync(Guid.NewGuid().ToString(), "/pk", throughput: 10000);
+ for (int count = 0; count < 10; count++)
+ {
+ string randomId = Guid.NewGuid().ToString();
+ string pk = "Status1";
+ await container.CreateItemAsync(ToDoActivity.CreateRandomToDoActivity(id: randomId, pk: pk));
+ await container.ReadItemAsync(randomId, new PartitionKey(pk));
+
+ QueryRequestOptions queryRequestOptions = new QueryRequestOptions()
+ {
+ MaxItemCount = Random.Shared.Next(1, 100)
+ };
+ FeedIterator feedIterator = container.GetItemQueryIterator(queryText: "SELECT * FROM c", requestOptions: queryRequestOptions);
+ while (feedIterator.HasMoreResults)
+ {
+ await feedIterator.ReadNextAsync();
+ }
+ }
+
+ while (!this.manualResetEventSlim.IsSet)
+ {
+ }
+
+ Assert.IsTrue(IsEqual(expectedMetrics, CustomMetricExporter.ActualMetrics), string.Join(", ", CustomMetricExporter.ActualMetrics.Select(kv => $"{kv.Key}: {kv.Value}")));
+ }
+
+ public static bool IsEqual(Dictionary expected, Dictionary actual)
+ {
+ if (expected.Count != actual.Count)
+ return false;
+
+ // Compare both keys and values
+ foreach (KeyValuePair pair in expected)
+ {
+ if (!actual.TryGetValue(pair.Key, out TValue value) || !EqualityComparer.Default.Equals(pair.Value, value))
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs
index f035711d77..237702f2c9 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs
@@ -47,6 +47,12 @@ public async Task TestInit(
customizeClientBuilder: customizeClientBuilder,
accountEndpointOverride: accountEndpointOverride);
await this.BaseInit(this.cosmosClient);
+ }
+
+ public async Task TestInit(Action customizeClientBuilder = null)
+ {
+ this.cosmosClient = TestCommon.CreateCosmosClient(customizeClientBuilder: customizeClientBuilder);
+ await this.BaseInit(this.cosmosClient);
}
public async Task TestCleanup()
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/MockedItemBenchmark.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/MockedItemBenchmark.cs
index f660ed930d..51070253d6 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/MockedItemBenchmark.cs
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/MockedItemBenchmark.cs
@@ -15,7 +15,8 @@ public enum ScenarioType
OfT = 1,
OfTCustom = 2,
OfTWithDiagnosticsToString = 3,
- OfTWithClientTelemetryEnabled = 4
+ OfTWithDistributedTracingEnabled = 4,
+ OfTWithClientMetricsEnabled = 5
}
[Config(typeof(SdkBenchmarkConfiguration))]
@@ -32,11 +33,16 @@ public class MockedItemBenchmark : IItemBenchmark
BenchmarkHelper = new MockedItemBenchmarkHelper(
useCustomSerializer: false,
includeDiagnosticsToString: true) },
- new MockedItemOfTBenchmark() {
+ new MockedItemOfTBenchmark() {
BenchmarkHelper = new MockedItemBenchmarkHelper(
- useCustomSerializer: false,
+ useCustomSerializer: false,
+ includeDiagnosticsToString: false,
+ isDistributedTracingEnabled: true) },
+ new MockedItemOfTBenchmark() {
+ BenchmarkHelper = new MockedItemBenchmarkHelper(
+ useCustomSerializer: false,
includeDiagnosticsToString: false,
- isClientTelemetryEnabled: true) }
+ isClientMetricsEnabled: true) }
};
[Params(
@@ -44,7 +50,8 @@ public class MockedItemBenchmark : IItemBenchmark
ScenarioType.OfT,
ScenarioType.OfTWithDiagnosticsToString,
ScenarioType.OfTCustom,
- ScenarioType.OfTWithClientTelemetryEnabled)]
+ ScenarioType.OfTWithDistributedTracingEnabled,
+ ScenarioType.OfTWithClientMetricsEnabled)]
public ScenarioType Type
{
get;
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/MockedItemBenchmarkHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/MockedItemBenchmarkHelper.cs
index f50d082b53..c3d473f079 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/MockedItemBenchmarkHelper.cs
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/MockedItemBenchmarkHelper.cs
@@ -34,9 +34,18 @@ public MockedItemBenchmarkHelper(
bool useCustomSerializer = false,
bool includeDiagnosticsToString = false,
bool useBulk = false,
- bool? isClientTelemetryEnabled = null)
+ bool isDistributedTracingEnabled = false,
+ bool isClientMetricsEnabled = false)
{
- this.TestClient = MockDocumentClient.CreateMockCosmosClient(useCustomSerializer, isClientTelemetryEnabled, (builder) => builder.WithBulkExecution(useBulk));
+ this.TestClient = MockDocumentClient.CreateMockCosmosClient(useCustomSerializer,
+ (builder) => builder
+ .WithBulkExecution(useBulk)
+ .WithClientTelemetryOptions(new CosmosClientTelemetryOptions()
+ {
+ DisableDistributedTracing = !isDistributedTracingEnabled,
+ IsClientMetricsEnabled = isClientMetricsEnabled
+ }));
+
this.TestContainer = this.TestClient.GetDatabase("myDB").GetContainer("myColl");
this.IncludeDiagnosticsToString = includeDiagnosticsToString;
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Bulk/MockedItemBulkBenchmark.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Bulk/MockedItemBulkBenchmark.cs
index 72a7e5ef24..068da40280 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Bulk/MockedItemBulkBenchmark.cs
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Bulk/MockedItemBulkBenchmark.cs
@@ -16,14 +16,16 @@ public class MockedItemBulkBenchmark : IItemBulkBenchmark
new MockedItemOfTBulkBenchmark() { BenchmarkHelper = new MockedItemBenchmarkHelper(useBulk: true) },
new MockedItemOfTBulkBenchmark() { BenchmarkHelper = new MockedItemBenchmarkHelper(useCustomSerializer: true, useBulk: true) },
new MockedItemOfTBulkBenchmark() { BenchmarkHelper = new MockedItemBenchmarkHelper(useCustomSerializer: false, includeDiagnosticsToString: true, useBulk: true) },
- new MockedItemOfTBulkBenchmark() { BenchmarkHelper = new MockedItemBenchmarkHelper(useCustomSerializer: false, includeDiagnosticsToString: true, isClientTelemetryEnabled:true, useBulk: true) }
+ new MockedItemOfTBulkBenchmark() { BenchmarkHelper = new MockedItemBenchmarkHelper(useCustomSerializer: false, includeDiagnosticsToString: true, isDistributedTracingEnabled:true, useBulk: true) },
+ new MockedItemOfTBulkBenchmark() { BenchmarkHelper = new MockedItemBenchmarkHelper(useCustomSerializer: false, includeDiagnosticsToString: true, isClientMetricsEnabled:true, useBulk: true) }
};
[Params(ScenarioType.Stream,
ScenarioType.OfT,
ScenarioType.OfTWithDiagnosticsToString,
ScenarioType.OfTCustom,
- ScenarioType.OfTWithClientTelemetryEnabled)]
+ ScenarioType.OfTWithDistributedTracingEnabled,
+ ScenarioType.OfTWithClientMetricsEnabled)]
public ScenarioType Type
{
get;
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json
index e11a346aff..9f26553a93 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json
@@ -1,79 +1,62 @@
{
- "MasterKeyAuthorizationBenchmark.CreateSignatureGeneration;": 554,
- "MasterKeyAuthorizationBenchmark.ReadSignatureGeneration;": 544,
- "MockedItemBenchmark.CreateItem;[Type=OfT]": 37261.25,
- "MockedItemBenchmark.CreateItem;[Type=OfTCustom]": 37285,
- "MockedItemBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 37280.25,
- "MockedItemBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": 58900.5,
- "MockedItemBenchmark.CreateItem;[Type=Stream]": 25212.75,
- "MockedItemBenchmark.DeleteItemExists;[Type=OfT]": 33015.25,
- "MockedItemBenchmark.DeleteItemExists;[Type=OfTCustom]": 33007.75,
- "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithClientTelemetryEnabled]": 33015.75,
- "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithDiagnosticsToString]": 54402.75,
- "MockedItemBenchmark.DeleteItemExists;[Type=Stream]": 25229.25,
- "MockedItemBenchmark.DeleteItemNotExists;[Type=OfT]": 43035,
- "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTCustom]": 43030.5,
- "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 43034.25,
- "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithDiagnosticsToString]": 63338,
- "MockedItemBenchmark.DeleteItemNotExists;[Type=Stream]": 38373.5,
- "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfT]": 13293777.25,
- "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTCustom]": 13298034.75,
- "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithClientTelemetryEnabled]": 13298733.75,
- "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithDiagnosticsToString]": 13517039.75,
- "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=Stream]": 5920952,
- "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfT]": 2241814,
- "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTCustom]": 2241810,
- "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithClientTelemetryEnabled]": 2244658,
- "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithDiagnosticsToString]": 2251235.75,
- "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=Stream]": 978459.25,
- "MockedItemBenchmark.ReadFeed;[Type=OfT]": 560692,
- "MockedItemBenchmark.ReadFeed;[Type=OfTCustom]": 555716,
- "MockedItemBenchmark.ReadFeed;[Type=OfTWithClientTelemetryEnabled]": 550898.25,
- "MockedItemBenchmark.ReadFeed;[Type=OfTWithDiagnosticsToString]": 573734.5,
- "MockedItemBenchmark.ReadFeed;[Type=Stream]": 34192,
- "MockedItemBenchmark.ReadItemExists;[Type=OfT]": 34509.75,
- "MockedItemBenchmark.ReadItemExists;[Type=OfTCustom]": 34516,
- "MockedItemBenchmark.ReadItemExists;[Type=OfTWithClientTelemetryEnabled]": 34515.5,
- "MockedItemBenchmark.ReadItemExists;[Type=OfTWithDiagnosticsToString]": 56524.5,
- "MockedItemBenchmark.ReadItemExists;[Type=Stream]": 26752.5,
- "MockedItemBenchmark.ReadItemNotExists;[Type=OfT]": 43489.25,
- "MockedItemBenchmark.ReadItemNotExists;[Type=OfTCustom]": 43490,
- "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 43489.25,
- "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithDiagnosticsToString]": 64764.75,
- "MockedItemBenchmark.ReadItemNotExists;[Type=Stream]": 39876,
- "MockedItemBenchmark.UpdateItem;[Type=OfT]": 37505.5,
- "MockedItemBenchmark.UpdateItem;[Type=OfTCustom]": 37496.25,
- "MockedItemBenchmark.UpdateItem;[Type=OfTWithClientTelemetryEnabled]": 37516.5,
- "MockedItemBenchmark.UpdateItem;[Type=OfTWithDiagnosticsToString]": 59152,
- "MockedItemBenchmark.UpdateItem;[Type=Stream]": 25428,
- "MockedItemBenchmark.UpsertItem;[Type=OfT]": 37487.5,
- "MockedItemBenchmark.UpsertItem;[Type=OfTCustom]": 37486,
- "MockedItemBenchmark.UpsertItem;[Type=OfTWithClientTelemetryEnabled]": 37490,
- "MockedItemBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": 59613,
- "MockedItemBenchmark.UpsertItem;[Type=Stream]": 25445.5,
- "MockedItemBulkBenchmark.CreateItem;[Type=OfT]": 1196168,
- "MockedItemBulkBenchmark.CreateItem;[Type=OfTCustom]": 1195808,
- "MockedItemBulkBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 1235418,
- "MockedItemBulkBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": 1231120,
- "MockedItemBulkBenchmark.CreateItem;[Type=Stream]": 772810,
- "MockedItemBulkBenchmark.DeleteItem;[Type=OfT]": 1187168,
- "MockedItemBulkBenchmark.DeleteItem;[Type=OfTCustom]": 1187224,
- "MockedItemBulkBenchmark.DeleteItem;[Type=OfTWithClientTelemetryEnabled]": 1226488,
- "MockedItemBulkBenchmark.DeleteItem;[Type=OfTWithDiagnosticsToString]": 1222124,
- "MockedItemBulkBenchmark.DeleteItem;[Type=Stream]": 771414,
- "MockedItemBulkBenchmark.ReadItem;[Type=OfT]": 1186594,
- "MockedItemBulkBenchmark.ReadItem;[Type=OfTCustom]": 1187192,
- "MockedItemBulkBenchmark.ReadItem;[Type=OfTWithClientTelemetryEnabled]": 1226502,
- "MockedItemBulkBenchmark.ReadItem;[Type=OfTWithDiagnosticsToString]": 1222342,
- "MockedItemBulkBenchmark.ReadItem;[Type=Stream]": 770894,
- "MockedItemBulkBenchmark.UpdateItem;[Type=OfT]": 1196464,
- "MockedItemBulkBenchmark.UpdateItem;[Type=OfTCustom]": 1195778,
- "MockedItemBulkBenchmark.UpdateItem;[Type=OfTWithClientTelemetryEnabled]": 1235738,
- "MockedItemBulkBenchmark.UpdateItem;[Type=OfTWithDiagnosticsToString]": 1231486,
- "MockedItemBulkBenchmark.UpdateItem;[Type=Stream]": 773284,
- "MockedItemBulkBenchmark.UpsertItem;[Type=OfT]": 1196210,
- "MockedItemBulkBenchmark.UpsertItem;[Type=OfTCustom]": 1195590,
- "MockedItemBulkBenchmark.UpsertItem;[Type=OfTWithClientTelemetryEnabled]": 1235596,
- "MockedItemBulkBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": 1231380,
- "MockedItemBulkBenchmark.UpsertItem;[Type=Stream]": 773312
+ "MockedItemBenchmark.CreateItem;[Type=OfT]": "37261.25",
+ "MockedItemBenchmark.CreateItem;[Type=OfTCustom]": "37285",
+ "MockedItemBenchmark.CreateItem;[Type=OfTWithClientMetricsEnabled]": "37751",
+ "MockedItemBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": "61599.25",
+ "MockedItemBenchmark.CreateItem;[Type=OfTWithDistributedTracingEnabled]": "38351.5",
+ "MockedItemBenchmark.CreateItem;[Type=Stream]": "25793.75",
+ "MockedItemBenchmark.DeleteItemExists;[Type=OfT]": "33015.25",
+ "MockedItemBenchmark.DeleteItemExists;[Type=OfTCustom]": "33007.75",
+ "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithClientMetricsEnabled]": "33730.5",
+ "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithDiagnosticsToString]": "57928.75",
+ "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithDistributedTracingEnabled]": "34352",
+ "MockedItemBenchmark.DeleteItemExists;[Type=Stream]": "25829.5",
+ "MockedItemBenchmark.DeleteItemNotExists;[Type=OfT]": "43035",
+ "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTCustom]": "43030.5",
+ "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithClientMetricsEnabled]": "43543.75",
+ "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithDiagnosticsToString]": "67387.5",
+ "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithDistributedTracingEnabled]": "44155.75",
+ "MockedItemBenchmark.DeleteItemNotExists;[Type=Stream]": "38373.5",
+ "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfT]": "13293777.25",
+ "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTCustom]": "13298034.75",
+ "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithClientMetricsEnabled]": "13198472.5",
+ "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithDiagnosticsToString]": "13517039.75",
+ "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithDistributedTracingEnabled]": "13201964",
+ "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=Stream]": "5920952",
+ "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfT]": "2241814",
+ "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTCustom]": "2241810",
+ "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithClientMetricsEnabled]": "2216526.75",
+ "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithDiagnosticsToString]": "2251235.75",
+ "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithDistributedTracingEnabled]": "2217249.25",
+ "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=Stream]": "978459.25",
+ "MockedItemBenchmark.ReadFeed;[Type=OfT]": "536077",
+ "MockedItemBenchmark.ReadFeed;[Type=OfTCustom]": "536082.75",
+ "MockedItemBenchmark.ReadFeed;[Type=OfTWithClientMetricsEnabled]": "536267.5",
+ "MockedItemBenchmark.ReadFeed;[Type=OfTWithDiagnosticsToString]": "557967.75",
+ "MockedItemBenchmark.ReadFeed;[Type=OfTWithDistributedTracingEnabled]": "536887.5",
+ "MockedItemBenchmark.ReadFeed;[Type=Stream]": "34192",
+ "MockedItemBenchmark.ReadItemExists;[Type=OfT]": "34509.75",
+ "MockedItemBenchmark.ReadItemExists;[Type=OfTCustom]": "34516",
+ "MockedItemBenchmark.ReadItemExists;[Type=OfTWithClientMetricsEnabled]": "35012.75",
+ "MockedItemBenchmark.ReadItemExists;[Type=OfTWithDiagnosticsToString]": "58859",
+ "MockedItemBenchmark.ReadItemExists;[Type=OfTWithDistributedTracingEnabled]": "35629.5",
+ "MockedItemBenchmark.ReadItemExists;[Type=Stream]": "26752.5",
+ "MockedItemBenchmark.ReadItemNotExists;[Type=OfT]": "44817.25",
+ "MockedItemBenchmark.ReadItemNotExists;[Type=OfTCustom]": "44810.75",
+ "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithClientMetricsEnabled]": "44819.5",
+ "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithDiagnosticsToString]": "66800",
+ "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithDistributedTracingEnabled]": "45423",
+ "MockedItemBenchmark.ReadItemNotExists;[Type=Stream]": "39876",
+ "MockedItemBenchmark.UpdateItem;[Type=OfT]": "37505.5",
+ "MockedItemBenchmark.UpdateItem;[Type=OfTCustom]": "37496.25",
+ "MockedItemBenchmark.UpdateItem;[Type=OfTWithClientMetricsEnabled]": "37965",
+ "MockedItemBenchmark.UpdateItem;[Type=OfTWithDiagnosticsToString]": "62701.5",
+ "MockedItemBenchmark.UpdateItem;[Type=OfTWithDistributedTracingEnabled]": "38580",
+ "MockedItemBenchmark.UpdateItem;[Type=Stream]": "26024",
+ "MockedItemBenchmark.UpsertItem;[Type=OfT]": "37487.5",
+ "MockedItemBenchmark.UpsertItem;[Type=OfTCustom]": "37486",
+ "MockedItemBenchmark.UpsertItem;[Type=OfTWithClientMetricsEnabled]": "37958.75",
+ "MockedItemBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": "62991.25",
+ "MockedItemBenchmark.UpsertItem;[Type=OfTWithDistributedTracingEnabled]": "38568",
+ "MockedItemBenchmark.UpsertItem;[Type=Stream]": "26017.25"
}
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Microsoft.Azure.Cosmos.Performance.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Microsoft.Azure.Cosmos.Performance.Tests.csproj
index b8d65cf141..0d12e1f397 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Microsoft.Azure.Cosmos.Performance.Tests.csproj
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Microsoft.Azure.Cosmos.Performance.Tests.csproj
@@ -17,12 +17,13 @@
-
+
+
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs
index c6b59b8cea..a383fb6bf5 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs
@@ -41,66 +41,18 @@ internal class MockDocumentClient : DocumentClient, ICosmosAuthorizationTokenPro
};
string[] dummyHeaderNames;
- private IComputeHash authKeyHashFunction;
+ private readonly IComputeHash authKeyHashFunction;
public static CosmosClient CreateMockCosmosClient(
bool useCustomSerializer = false,
- bool? isClientTelemetryEnabled = null,
Action < CosmosClientBuilder> customizeClientBuilder = null)
{
- ConnectionPolicy policy = new ConnectionPolicy();
-
- if (isClientTelemetryEnabled.HasValue)
- {
- policy = new ConnectionPolicy
- {
- CosmosClientTelemetryOptions = new CosmosClientTelemetryOptions
- {
- DisableSendingMetricsToService = !isClientTelemetryEnabled.Value
- }
- };
- }
-
- MockDocumentClient documentClient = new MockDocumentClient(policy);
+ MockDocumentClient documentClient = new MockDocumentClient(new ConnectionPolicy());
CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder("http://localhost", Convert.ToBase64String(Guid.NewGuid().ToByteArray()));
cosmosClientBuilder.WithConnectionModeDirect();
Uri telemetryServiceEndpoint = new Uri("https://dummy.endpoint.com/");
- if (isClientTelemetryEnabled.HasValue)
- {
- // mock external calls
- HttpClientHandlerHelper httpHandler = new HttpClientHandlerHelper
- {
- RequestCallBack = (request, cancellation) =>
- {
- if (request.RequestUri.AbsoluteUri.Equals(telemetryServiceEndpoint.AbsoluteUri))
- {
- return Task.FromResult(new HttpResponseMessage(HttpStatusCode.NoContent)); // In Emulator test, send hardcoded response status code as there is no real communication happens with client telemetry service
- }
- else if (request.RequestUri.AbsoluteUri.Contains(Paths.ClientConfigPathSegment))
- {
- HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
- AccountClientConfiguration clientConfigProperties = new AccountClientConfiguration
- {
- ClientTelemetryConfiguration = new ClientTelemetryConfiguration
- {
- IsEnabled = isClientTelemetryEnabled.Value,
- Endpoint = isClientTelemetryEnabled.Value?telemetryServiceEndpoint.AbsoluteUri: null
- }
- };
- string payload = JsonConvert.SerializeObject(clientConfigProperties);
- result.Content = new StringContent(payload, Encoding.UTF8, "application/json");
- return Task.FromResult(result);
- }
-
- return null;
- }
- };
-
- cosmosClientBuilder.WithHttpClientFactory(() => new HttpClient(httpHandler));
- }
-
customizeClientBuilder?.Invoke(cosmosClientBuilder);
if (useCustomSerializer)
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/OTelExporter/CustomMetricExporter.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/OTelExporter/CustomMetricExporter.cs
new file mode 100644
index 0000000000..a5daf11f6e
--- /dev/null
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/OTelExporter/CustomMetricExporter.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------
+//------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------
+
+namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests.Metrics
+{
+ using OpenTelemetry.Metrics;
+ using OpenTelemetry;
+
+ public class CustomMetricExporter : BaseExporter
+ {
+ public CustomMetricExporter()
+ {
+ }
+
+ // This method will be called periodically by OpenTelemetry SDK
+ public override ExportResult Export(in Batch batch)
+ {
+ //NoOP
+ return ExportResult.Success;
+ }
+ }
+}
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/OTelExporter/CustomTraceExporter.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/OTelExporter/CustomTraceExporter.cs
new file mode 100644
index 0000000000..95c27c0357
--- /dev/null
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/OTelExporter/CustomTraceExporter.cs
@@ -0,0 +1,43 @@
+//------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------
+
+namespace Microsoft.Azure.Cosmos.Tracing
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using OpenTelemetry;
+ using OpenTelemetry.Trace;
+
+ internal class CustomTraceExporter : BaseExporter
+ {
+ private readonly string _name;
+
+ public static List CollectedActivities;
+
+ public CustomTraceExporter()
+ {
+ }
+
+ public override ExportResult Export(in Batch batch)
+ {
+ // NoOp
+
+ return ExportResult.Success;
+ }
+ }
+
+ internal static class OTelExtensions
+ {
+ public static TracerProviderBuilder AddCustomOtelExporter(this TracerProviderBuilder builder)
+ {
+ if (builder == null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+
+ return builder.AddProcessor(new SimpleActivityExportProcessor(new CustomTraceExporter()));
+ }
+ }
+}
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Program.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Program.cs
index 9b109428b7..aa0bf561ba 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Program.cs
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Program.cs
@@ -7,6 +7,11 @@ namespace Microsoft.Azure.Cosmos.Performance.Tests
using System.Collections.Generic;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Running;
+ using Microsoft.Azure.Cosmos.SDK.EmulatorTests.Metrics;
+ using Microsoft.Azure.Cosmos.Tracing;
+ using OpenTelemetry;
+ using OpenTelemetry.Metrics;
+ using OpenTelemetry.Trace;
class Program
{
@@ -22,6 +27,16 @@ static int Main(string[] args)
bool validateBaseline = argsList.Remove("--BaselineValidation");
string[] updatedArgs = argsList.ToArray();
+ using TracerProvider tracebuilder = Sdk.CreateTracerProviderBuilder()
+ .AddSource("Azure.Cosmos.*")
+ .AddCustomOtelExporter()
+ .Build();
+
+ using MeterProvider metricsBuilder = Sdk.CreateMeterProviderBuilder()
+ .AddMeter("Azure.Cosmos.Client.*")
+ .AddReader(new PeriodicExportingMetricReader(exporter: new CustomMetricExporter(), 10000))
+ .Build();
+
if (validateBaseline)
{
SortedDictionary operationToAllocatedMemory = new SortedDictionary();
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json
index 385c1b9f47..76e5ba4b51 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json
@@ -3247,6 +3247,18 @@
],
"MethodInfo": "Boolean get_DisableSendingMetricsToService();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
+ "Boolean get_IsClientMetricsEnabled()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
+ "Type": "Method",
+ "Attributes": [
+ "CompilerGeneratedAttribute"
+ ],
+ "MethodInfo": "Boolean get_IsClientMetricsEnabled();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
+ },
+ "Boolean IsClientMetricsEnabled": {
+ "Type": "Property",
+ "Attributes": [],
+ "MethodInfo": "Boolean IsClientMetricsEnabled;CanRead:True;CanWrite:True;Boolean get_IsClientMetricsEnabled();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_IsClientMetricsEnabled(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
+ },
"Microsoft.Azure.Cosmos.CosmosThresholdOptions CosmosThresholdOptions": {
"Type": "Property",
"Attributes": [],
@@ -3297,6 +3309,13 @@
],
"MethodInfo": "Void set_DisableSendingMetricsToService(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
+ "Void set_IsClientMetricsEnabled(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
+ "Type": "Method",
+ "Attributes": [
+ "CompilerGeneratedAttribute"
+ ],
+ "MethodInfo": "Void set_IsClientMetricsEnabled(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
+ },
"Void set_QueryTextMode(Microsoft.Azure.Cosmos.QueryTextMode)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Type": "Method",
"Attributes": [
@@ -3307,6 +3326,353 @@
},
"NestedTypes": {}
},
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+HistogramBuckets": {
+ "Type": "NestedType",
+ "Attributes": [],
+ "MethodInfo": null
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics": {
+ "Type": "NestedType",
+ "Attributes": [],
+ "MethodInfo": null
+ },
+ "Void .ctor()": {
+ "Type": "Constructor",
+ "Attributes": [],
+ "MethodInfo": "[Void .ctor(), Void .ctor()]"
+ }
+ },
+ "NestedTypes": {
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+HistogramBuckets;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "Double[] RequestLatencyBuckets": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "Double[] RequestLatencyBuckets;IsInitOnly:True;IsStatic:True;"
+ },
+ "Double[] RequestUnitBuckets": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "Double[] RequestUnitBuckets;IsInitOnly:True;IsStatic:True;"
+ },
+ "Double[] RowCountBuckets": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "Double[] RowCountBuckets;IsInitOnly:True;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {}
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Description": {
+ "Type": "NestedType",
+ "Attributes": [],
+ "MethodInfo": null
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Name": {
+ "Type": "NestedType",
+ "Attributes": [],
+ "MethodInfo": null
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Unit": {
+ "Type": "NestedType",
+ "Attributes": [],
+ "MethodInfo": null
+ },
+ "System.String MeterName": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String MeterName;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String Version": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Version;IsInitOnly:False;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Description;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "System.String ActiveInstances": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String ActiveInstances;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String Latency": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Latency;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RequestCharge": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RequestCharge;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RowCount": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RowCount;IsInitOnly:False;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {}
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Name;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "System.String ActiveInstances": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String ActiveInstances;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String Latency": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Latency;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RequestCharge": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RequestCharge;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RowCount": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RowCount;IsInitOnly:False;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {}
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Unit;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "System.String Count": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Count;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RequestUnit": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RequestUnit;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String Sec": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Sec;IsInitOnly:False;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {}
+ }
+ }
+ }
+ }
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+HistogramBuckets;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "Double[] RequestLatencyBuckets": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "Double[] RequestLatencyBuckets;IsInitOnly:True;IsStatic:True;"
+ },
+ "Double[] RequestUnitBuckets": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "Double[] RequestUnitBuckets;IsInitOnly:True;IsStatic:True;"
+ },
+ "Double[] RowCountBuckets": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "Double[] RowCountBuckets;IsInitOnly:True;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {}
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Description": {
+ "Type": "NestedType",
+ "Attributes": [],
+ "MethodInfo": null
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Name": {
+ "Type": "NestedType",
+ "Attributes": [],
+ "MethodInfo": null
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Unit": {
+ "Type": "NestedType",
+ "Attributes": [],
+ "MethodInfo": null
+ },
+ "System.String MeterName": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String MeterName;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String Version": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Version;IsInitOnly:False;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Description;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "System.String ActiveInstances": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String ActiveInstances;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String Latency": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Latency;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RequestCharge": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RequestCharge;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RowCount": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RowCount;IsInitOnly:False;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {}
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Name;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "System.String ActiveInstances": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String ActiveInstances;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String Latency": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Latency;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RequestCharge": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RequestCharge;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RowCount": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RowCount;IsInitOnly:False;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {}
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Unit;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "System.String Count": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Count;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RequestUnit": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RequestUnit;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String Sec": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Sec;IsInitOnly:False;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {}
+ }
+ }
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Description;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "System.String ActiveInstances": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String ActiveInstances;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String Latency": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Latency;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RequestCharge": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RequestCharge;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RowCount": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RowCount;IsInitOnly:False;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {}
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Name;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "System.String ActiveInstances": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String ActiveInstances;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String Latency": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Latency;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RequestCharge": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RequestCharge;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RowCount": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RowCount;IsInitOnly:False;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {}
+ },
+ "Microsoft.Azure.Cosmos.CosmosDbClientMetrics+OperationMetrics+Unit;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": {
+ "Subclasses": {},
+ "Members": {
+ "System.String Count": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Count;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String RequestUnit": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String RequestUnit;IsInitOnly:False;IsStatic:True;"
+ },
+ "System.String Sec": {
+ "Type": "Field",
+ "Attributes": [],
+ "MethodInfo": "System.String Sec;IsInitOnly:False;IsStatic:True;"
+ }
+ },
+ "NestedTypes": {}
+ },
"Microsoft.Azure.Cosmos.CosmosDiagnostics;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": {
"Subclasses": {},
"Members": {