Skip to content

Commit

Permalink
refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
sourabh1007 committed Nov 20, 2024
1 parent 731951a commit 6a98f46
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 230 deletions.
2 changes: 1 addition & 1 deletion Microsoft.Azure.Cosmos/src/CosmosClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1438,7 +1438,7 @@ 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);
CosmosDbOperationMeter.RemoveInstanceCount(this.Endpoint);

return Interlocked.Decrement(ref NumberOfActiveClients);
}
Expand Down
4 changes: 2 additions & 2 deletions Microsoft.Azure.Cosmos/src/DocumentClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -958,9 +958,9 @@ internal virtual void Initialize(Uri serviceEndpoint,

if (this.cosmosClientTelemetryOptions.IsClientMetricsEnabled)
{
CosmosOperationMeter.Initialize();
CosmosDbOperationMeter.Initialize();

CosmosOperationMeter.AddInstanceCount(this.ServiceEndpoint);
CosmosDbOperationMeter.AddInstanceCount(this.ServiceEndpoint);
}

// Starting ClientTelemetry Job
Expand Down
4 changes: 2 additions & 2 deletions Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ private async Task<TResult> RunWithDiagnosticsHelperAsync<TResult>(
recorder.Record(response);

// Records metrics such as request units, latency, and item count for the operation.
CosmosOperationMeter.RecordTelemetry(getOperationName: getOperationName,
CosmosDbOperationMeter.RecordTelemetry(getOperationName: getOperationName,
accountName: this.client.Endpoint,
containerName: containerName,
databaseName: databaseName,
Expand Down Expand Up @@ -579,7 +579,7 @@ private async Task<TResult> RunWithDiagnosticsHelperAsync<TResult>(
if (openTelemetry != null && ex is CosmosException cosmosException)
{
// Records telemetry data related to the exception.
CosmosOperationMeter.RecordTelemetry(getOperationName: getOperationName,
CosmosDbOperationMeter.RecordTelemetry(getOperationName: getOperationName,
accountName: this.client.Endpoint,
containerName: containerName,
databaseName: databaseName,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Telemetry.OpenTelemetry
{
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using Microsoft.Azure.Cosmos.Core.Trace;

internal static class CosmosDbMeterUtil
{
internal static void RecordHistogramMetric<T>(
object value,
Func<KeyValuePair<string, object>[]> dimensionsFunc,
Histogram<T> histogram,
Func<object, T> converter = null)
where T : struct
{
if (histogram == null || !histogram.Enabled || value == null)
{
return;
}

try
{
T convertedValue = converter != null ? converter(value) : (T)value;
histogram.Record(convertedValue, dimensionsFunc());
}
catch (Exception ex)
{
DefaultTrace.TraceWarning($"Failed to record metric. {ex.StackTrace}");
}
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Telemetry
{
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using Microsoft.Azure.Cosmos.Core.Trace;
using Microsoft.Azure.Cosmos.Telemetry.OpenTelemetry;

/// <summary>
/// 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.
/// </summary>
internal static class CosmosDbOperationMeter
{
/// <summary>
/// Meter instance for capturing various metrics related to Cosmos DB operations.
/// </summary>
private static readonly Meter OperationMeter = new Meter(CosmosDbClientMetrics.OperationMetrics.MeterName, CosmosDbClientMetrics.OperationMetrics.Version);

/// <summary>
/// Populator Used for Dimension Attributes
/// </summary>
private static readonly IActivityAttributePopulator DimensionPopulator = TracesStabilityFactory.GetAttributePopulator();

/// <summary>
/// Histogram to record request latency (in seconds) for Cosmos DB operations.
/// </summary>
private static Histogram<double> RequestLatencyHistogram = null;

/// <summary>
/// Histogram to record request units consumed during Cosmos DB operations.
/// </summary>
private static Histogram<double> RequestUnitsHistogram = null;

/// <summary>
/// Histogram to record the actual number of items involved in the operation.
/// </summary>
private static Histogram<int> ActualItemHistogram = null;

/// <summary>
/// UpDownCounter to track the number of active instances interacting with Cosmos DB.
/// </summary>
private static UpDownCounter<int> ActiveInstanceCounter = null;

/// <summary>
/// Flag to check if metrics is enabled
/// </summary>
private static bool IsEnabled = false;

/// <summary>
/// Initializes the histograms and counters for capturing Cosmos DB metrics.
/// </summary>
internal static void Initialize()
{
// If already initialized, do not initialize again
if (IsEnabled)
{
return;
}

CosmosDbOperationMeter.RequestLatencyHistogram ??= OperationMeter.CreateHistogram<double>(name: CosmosDbClientMetrics.OperationMetrics.Name.Latency,
unit: CosmosDbClientMetrics.OperationMetrics.Unit.Sec,
description: CosmosDbClientMetrics.OperationMetrics.Description.Latency);

CosmosDbOperationMeter.RequestUnitsHistogram ??= OperationMeter.CreateHistogram<double>(name: CosmosDbClientMetrics.OperationMetrics.Name.RequestCharge,
unit: CosmosDbClientMetrics.OperationMetrics.Unit.RequestUnit,
description: CosmosDbClientMetrics.OperationMetrics.Description.RequestCharge);

CosmosDbOperationMeter.ActualItemHistogram ??= OperationMeter.CreateHistogram<int>(name: CosmosDbClientMetrics.OperationMetrics.Name.RowCount,
unit: CosmosDbClientMetrics.OperationMetrics.Unit.Count,
description: CosmosDbClientMetrics.OperationMetrics.Description.RowCount);

CosmosDbOperationMeter.ActiveInstanceCounter ??= OperationMeter.CreateUpDownCounter<int>(name: CosmosDbClientMetrics.OperationMetrics.Name.ActiveInstances,
unit: CosmosDbClientMetrics.OperationMetrics.Unit.Count,
description: CosmosDbClientMetrics.OperationMetrics.Description.ActiveInstances);

IsEnabled = true;
}

/// <summary>
/// Records telemetry data for Cosmos DB operations.
/// </summary>
internal static void RecordTelemetry(
Func<string> getOperationName,
Uri accountName,
string containerName,
string databaseName,
OpenTelemetryAttributes attributes = null,
CosmosException ex = null)
{
if (!IsEnabled)
{
return;
}

try
{
Func<KeyValuePair<string, object>[]> dimensionsFunc = () =>
DimensionPopulator.PopulateOperationMeterDimensions(
getOperationName(), containerName, databaseName, accountName, attributes, ex);

CosmosDbMeterUtil.RecordHistogramMetric<int>(value: attributes?.ItemCount ?? ex?.Headers?.ItemCount,
dimensionsFunc, ActualItemHistogram,
Convert.ToInt32);
CosmosDbMeterUtil.RecordHistogramMetric<double>(value: attributes?.RequestCharge ?? ex?.Headers?.RequestCharge,
dimensionsFunc, RequestUnitsHistogram);
CosmosDbMeterUtil.RecordHistogramMetric<double>(value: attributes?.Diagnostics?.GetClientElapsedTime() ?? ex?.Diagnostics?.GetClientElapsedTime(),
dimensionsFunc, RequestLatencyHistogram,
t => ((TimeSpan)t).TotalSeconds);
}
catch (Exception exception)
{
DefaultTrace.TraceWarning($"Failed to record telemetry data. {exception.StackTrace}");
}
}

/// <summary>
/// Adjusts the count of active Cosmos DB instances.
/// </summary>
internal static void AdjustInstanceCount(Uri accountEndpoint, int adjustment)
{
if (!IsEnabled || ActiveInstanceCounter == null || !ActiveInstanceCounter.Enabled)
{
return;
}

try
{
KeyValuePair<string, object>[] dimensions = new[]
{
new KeyValuePair<string, object>(OpenTelemetryAttributeKeys.DbSystemName, OpenTelemetryCoreRecorder.CosmosDb),
new KeyValuePair<string, object>(OpenTelemetryAttributeKeys.ServerAddress, accountEndpoint.Host),
new KeyValuePair<string, object>(OpenTelemetryAttributeKeys.ServerPort, accountEndpoint.Port)
};

ActiveInstanceCounter.Add(adjustment, dimensions);
}
catch (Exception ex)
{
DefaultTrace.TraceWarning($"Failed to adjust instance count. {ex.StackTrace}");
}
}

internal static void AddInstanceCount(Uri accountEndpoint)
{
AdjustInstanceCount(accountEndpoint, 1);
}

internal static void RemoveInstanceCount(Uri accountEndpoint)
{
AdjustInstanceCount(accountEndpoint, -1);
}
}
}
Loading

0 comments on commit 6a98f46

Please sign in to comment.