Skip to content

Commit

Permalink
Open Telemetry: Adds open telemetry based versioning (#4854)
Browse files Browse the repository at this point in the history
## Description

Introducing versioning for open telemetry attributes, to make we are
always backward compatible.

Environment Variable `OTEL_SEMCONV_STABILITY_OPT_IN` value supported :
`database` => Otel supported attributes. (right now, same as default, in
future can be used to put any attribute change)
`database/dup` => Otel and appinsights attributes ( for those, who are
moving from appinsightclassic to otel)
`default` => Otel Attributes **_(Breaking change, needs to be
documented)_**
`appinsightssdk` => backward compatibility to appinsights.

Other minor changes,
1. Fix connection mode casing
  ```
{
                ConnectionMode.Direct => "direct",
                ConnectionMode.Gateway => "gateway",
                _ => throw new NotImplementedException()
            };
```
2. rename `db.cosmosdb.item_count` => `db.cosmosdb.row_count`

### Code changes Overview
1. Introduced, `TracesStabilityFactory.cs` : Responsible to take care of version based attributes.
2. Updated Baseline Tests to have old and new both attributes in contract file.

## Type of change

Please delete options that are not relevant.

- [] Bug fix (non-breaking change which fixes an issue)
- [] New feature (non-breaking change which adds functionality)
- [] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [] This change requires a documentation update
  • Loading branch information
sourabh1007 authored Nov 14, 2024
1 parent 80ea40a commit 925cebe
Show file tree
Hide file tree
Showing 23 changed files with 2,363 additions and 506 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

namespace Microsoft.Azure.Cosmos.Telemetry
{
internal sealed class AppInsightClassicAttributeKeys
using System;
using global::Azure.Core;

internal sealed class AppInsightClassicAttributeKeys : IActivityAttributePopulator
{
/// <summary>
/// Represents the diagnostic namespace for Azure Cosmos.
Expand Down Expand Up @@ -90,5 +93,72 @@ internal sealed class AppInsightClassicAttributeKeys
/// Represents the item count in the operation.
/// </summary>
public const string ItemCount = "db.cosmosdb.item_count";

/// <summary>
/// Represents the type of exception.
/// </summary>
public const string ExceptionType = "exception.type";

/// <summary>
/// Represents the message of the exception.
/// </summary>
public const string ExceptionMessage = "exception.message";

/// <summary>
/// Represents the stack trace of the exception.
/// </summary>
public const string ExceptionStacktrace = "exception.stacktrace";

public void PopulateAttributes(DiagnosticScope scope,
string operationName,
string databaseName,
string containerName,
Uri accountName,
string userAgent,
string machineId,
string clientId,
string connectionMode)
{
scope.AddAttribute(AppInsightClassicAttributeKeys.DbOperation, operationName);
scope.AddAttribute(AppInsightClassicAttributeKeys.DbName, databaseName);
scope.AddAttribute(AppInsightClassicAttributeKeys.ContainerName, containerName);
scope.AddAttribute(AppInsightClassicAttributeKeys.ServerAddress, accountName?.Host);
scope.AddAttribute(AppInsightClassicAttributeKeys.UserAgent, userAgent);
scope.AddAttribute(AppInsightClassicAttributeKeys.MachineId, machineId);
scope.AddAttribute(AppInsightClassicAttributeKeys.ClientId, clientId);
scope.AddAttribute(AppInsightClassicAttributeKeys.ConnectionMode, connectionMode);
}

public void PopulateAttributes(DiagnosticScope scope, Exception exception)
{
scope.AddAttribute(AppInsightClassicAttributeKeys.ExceptionStacktrace, exception.StackTrace);
scope.AddAttribute(AppInsightClassicAttributeKeys.ExceptionType, exception.GetType().Name);

// If Exception is not registered with open Telemetry
if (!OpenTelemetryCoreRecorder.IsExceptionRegistered(exception, scope))
{
scope.AddAttribute(AppInsightClassicAttributeKeys.ExceptionMessage, exception.Message);
}
}

public void PopulateAttributes(DiagnosticScope scope, QueryTextMode? queryTextMode, string operationType, OpenTelemetryAttributes response)
{
scope.AddAttribute(AppInsightClassicAttributeKeys.OperationType, operationType);
if (response != null)
{
scope.AddAttribute(AppInsightClassicAttributeKeys.RequestContentLength, response.RequestContentLength);
scope.AddAttribute(AppInsightClassicAttributeKeys.ResponseContentLength, response.ResponseContentLength);
scope.AddIntegerAttribute(AppInsightClassicAttributeKeys.StatusCode, Convert.ToInt32(response.StatusCode));
scope.AddIntegerAttribute(AppInsightClassicAttributeKeys.SubStatusCode, response.SubStatusCode);
scope.AddIntegerAttribute(AppInsightClassicAttributeKeys.RequestCharge, Convert.ToInt32(response.RequestCharge));
scope.AddAttribute(AppInsightClassicAttributeKeys.ItemCount, response.ItemCount);
scope.AddAttribute(AppInsightClassicAttributeKeys.ActivityId, response.ActivityId);

if (response.Diagnostics != null)
{
scope.AddAttribute(AppInsightClassicAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(response.Diagnostics.GetContactedRegions()));
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ public static void RecordDiagnosticsForRequests(
Documents.OperationType operationType,
OpenTelemetryAttributes response)
{
if (response.Diagnostics == null)
{
return;
}

if (CosmosDbEventSource.IsEnabled(EventLevel.Warning))
{
if (!DiagnosticsFilterHelper.IsSuccessfulResponse(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Telemetry
{
using System;
using global::Azure.Core;

internal class DatabaseDupAttributeKeys : IActivityAttributePopulator
{
private readonly IActivityAttributePopulator appInsightPopulator;
private readonly IActivityAttributePopulator otelPopulator;

public DatabaseDupAttributeKeys()
{
this.otelPopulator = new OpenTelemetryAttributeKeys();
this.appInsightPopulator = new AppInsightClassicAttributeKeys();
}

public void PopulateAttributes(DiagnosticScope scope, string operationName, string databaseName, string containerName, Uri accountName, string userAgent, string machineId, string clientId, string connectionMode)
{
this.appInsightPopulator.PopulateAttributes(scope, operationName, databaseName, containerName, accountName, userAgent, machineId, clientId, connectionMode);
this.otelPopulator.PopulateAttributes(scope, operationName, databaseName, containerName, accountName, userAgent, machineId, clientId, connectionMode);
}

public void PopulateAttributes(DiagnosticScope scope, Exception exception)
{
this.appInsightPopulator.PopulateAttributes(scope, exception);
this.otelPopulator.PopulateAttributes(scope, exception);
}

public void PopulateAttributes(DiagnosticScope scope, QueryTextMode? queryTextMode, string operationType, OpenTelemetryAttributes response)
{
this.appInsightPopulator.PopulateAttributes(scope, queryTextMode, operationType, response);
this.otelPopulator.PopulateAttributes(scope, queryTextMode, operationType, response);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Telemetry
{
using System;
using global::Azure.Core;

internal interface IActivityAttributePopulator
{
public void PopulateAttributes(DiagnosticScope scope,
string operationName,
string databaseName,
string containerName,
Uri accountName,
string userAgent,
string machineId,
string clientId,
string connectionMode);

public void PopulateAttributes(DiagnosticScope scope, Exception exception);

public void PopulateAttributes(DiagnosticScope scope,
QueryTextMode? queryTextMode,
string operationType,
OpenTelemetryAttributes response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@

namespace Microsoft.Azure.Cosmos.Telemetry
{
using System;
using global::Azure.Core;

/// <summary>
/// Contains constant string values representing OpenTelemetry attribute keys for monitoring and tracing Cosmos DB operations.
/// These keys follow the OpenTelemetry conventions and the Cosmos DB semantic conventions as outlined in the OpenTelemetry specification.
/// </summary>
/// <remarks>
/// For more details on the semantic conventions, refer to the OpenTelemetry documentation at:
/// <see href="https://opentelemetry.io/docs/specs/semconv/database/cosmosdb/"/>
/// <see href="https://opentelemetry.io/docs/specs/semconv/database/cosmosdb/"/> OpenTelemetry Semantic Conventions 1.28.0 conventions are followed.
/// </remarks>
internal sealed class OpenTelemetryAttributeKeys
internal sealed class OpenTelemetryAttributeKeys : IActivityAttributePopulator
{
// Azure defaults

Expand Down Expand Up @@ -58,6 +61,11 @@ internal sealed class OpenTelemetryAttributeKeys
/// </summary>
public const string ServerAddress = "server.address";

/// <summary>
/// Represents the server address.
/// </summary>
public const string ServerPort = "server.port";

// Cosmos DB specific attributes

/// <summary>
Expand Down Expand Up @@ -115,7 +123,7 @@ internal sealed class OpenTelemetryAttributeKeys
/// <summary>
/// Represents the item count in the operation.
/// </summary>
public const string ItemCount = "db.cosmosdb.item_count";
public const string ItemCount = "db.cosmosdb.row_count";

/// <summary>
/// Represents the activity ID for the operation.
Expand All @@ -135,7 +143,7 @@ internal sealed class OpenTelemetryAttributeKeys
/// <summary>
/// Represents the size of the batch operation.
/// </summary>
public const string BatchSize = "db.operation.batch_size";
public const string BatchSize = "db.operation.batch.size";

/// <summary>
/// Consistency Level
Expand All @@ -158,5 +166,78 @@ internal sealed class OpenTelemetryAttributeKeys
/// Represents the stack trace of the exception.
/// </summary>
public const string ExceptionStacktrace = "exception.stacktrace";

public void PopulateAttributes(DiagnosticScope scope,
string operationName,
string databaseName,
string containerName,
Uri accountName,
string userAgent,
string machineId,
string clientId,
string connectionMode)
{
scope.AddAttribute(OpenTelemetryAttributeKeys.DbOperation, operationName);
scope.AddAttribute(OpenTelemetryAttributeKeys.DbName, databaseName);
scope.AddAttribute(OpenTelemetryAttributeKeys.ContainerName, containerName);
if (accountName != null)
{
scope.AddAttribute(OpenTelemetryAttributeKeys.ServerAddress, accountName.Host);
scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.ServerPort, accountName.Port);
}
scope.AddAttribute(OpenTelemetryAttributeKeys.UserAgent, userAgent);
scope.AddAttribute(OpenTelemetryAttributeKeys.ClientId, clientId);
scope.AddAttribute(OpenTelemetryAttributeKeys.ConnectionMode, connectionMode);
}

public void PopulateAttributes(DiagnosticScope scope, Exception exception)
{
scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionStacktrace, exception.StackTrace);
scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionType, exception.GetType().Name);

// If Exception is not registered with open Telemetry
if (!OpenTelemetryCoreRecorder.IsExceptionRegistered(exception, scope))
{
scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionMessage, exception.Message);
}
}

public void PopulateAttributes(DiagnosticScope scope, QueryTextMode? queryTextMode, string operationType, OpenTelemetryAttributes response)
{
if (response == null)
{
return;
}

if (response.BatchSize is not null)
{
scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.BatchSize, Convert.ToInt32(response.BatchSize));
}

scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.StatusCode, Convert.ToInt32(response.StatusCode));
scope.AddAttribute(OpenTelemetryAttributeKeys.RequestContentLength, response.RequestContentLength);
scope.AddAttribute(OpenTelemetryAttributeKeys.ResponseContentLength, response.ResponseContentLength);
scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.SubStatusCode, response.SubStatusCode);
scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.RequestCharge, Convert.ToInt32(response.RequestCharge));
scope.AddAttribute(OpenTelemetryAttributeKeys.ItemCount, response.ItemCount);
scope.AddAttribute(OpenTelemetryAttributeKeys.ActivityId, response.ActivityId);
scope.AddAttribute(OpenTelemetryAttributeKeys.CorrelatedActivityId, response.CorrelatedActivityId);
scope.AddAttribute(OpenTelemetryAttributeKeys.ConsistencyLevel, response.ConsistencyLevel);

if (response.QuerySpec is not null)
{
if (queryTextMode == QueryTextMode.All ||
(queryTextMode == QueryTextMode.ParameterizedOnly && response.QuerySpec.ShouldSerializeParameters()))
{
scope.AddAttribute(OpenTelemetryAttributeKeys.QueryText, response.QuerySpec?.QueryText);
}
}

if (response.Diagnostics != null)
{
scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(response.Diagnostics.GetContactedRegions()));
}

}
}
}
Loading

0 comments on commit 925cebe

Please sign in to comment.