Skip to content

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions sdk/cosmos/azure-cosmos/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#### Breaking Changes

#### Bugs Fixed
* Fixed OpenTelemetry traces/spans to include the attributes defined in semantic convention for Azure Cosmos DB - [PR 45929](https://github.com/Azure/azure-sdk-for-java/pull/45929)

#### Other Changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package com.azure.cosmos.implementation;

import com.azure.cosmos.implementation.apachecommons.lang.StringUtils;
import com.azure.cosmos.implementation.clienttelemetry.AttributeNamingScheme;
import com.azure.cosmos.implementation.perPartitionCircuitBreaker.PartitionLevelCircuitBreakerConfig;
import com.azure.cosmos.implementation.directconnectivity.Protocol;
import io.netty.handler.ssl.ApplicationProtocolConfig;
Expand All @@ -16,6 +17,7 @@
import javax.net.ssl.SSLException;
import java.net.URI;
import java.time.Duration;
import java.util.EnumSet;
import java.util.Locale;

import static com.azure.cosmos.implementation.guava25.base.MoreObjects.firstNonNull;
Expand Down Expand Up @@ -354,6 +356,13 @@ public class Configs {
private static final String HTTP2_MAX_CONCURRENT_STREAMS = "COSMOS.HTTP2_MAX_CONCURRENT_STREAMS";
private static final String HTTP2_MAX_CONCURRENT_STREAMS_VARIABLE = "COSMOS_HTTP2_MAX_CONCURRENT_STREAMS";

// Config to indicate whether to emit Open Telemetry traces with attribute names following the
// original implementation (`PRE_V1_RELEASE`) or the official semantic convention (`V1`) or both (`ALL`)
public static final String OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME = "COSMOS.OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME";
public static final String OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME_VARIABLE = "COSMOS_OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME";

public static final String DEFAULT_OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME = "All";

public static int getCPUCnt() {
return CPU_CNT;
}
Expand Down Expand Up @@ -1195,4 +1204,18 @@ public static int getWarnLevelLoggingThresholdForPpaf() {

return Integer.parseInt(warnLevelLoggingThresholdForPpaf);
}

public static EnumSet<AttributeNamingScheme> getDefaultOtelSpanAttributeNamingScheme() {
String valueFromSystemProperty = System.getProperty(OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME);
if (valueFromSystemProperty != null && !valueFromSystemProperty.isEmpty()) {
return AttributeNamingScheme.parse(valueFromSystemProperty);
}

String valueFromEnvVariable = System.getenv(OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME_VARIABLE);
if (valueFromEnvVariable != null && !valueFromEnvVariable.isEmpty()) {
return AttributeNamingScheme.parse(valueFromEnvVariable);
}

return AttributeNamingScheme.parse(DEFAULT_OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME);
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.azure.cosmos.implementation.apachecommons.lang.tuple.Pair;
import com.azure.cosmos.implementation.batch.ItemBatchOperation;
import com.azure.cosmos.implementation.batch.PartitionScopeThresholds;
import com.azure.cosmos.implementation.clienttelemetry.AttributeNamingScheme;
import com.azure.cosmos.implementation.clienttelemetry.ClientTelemetry;
import com.azure.cosmos.implementation.clienttelemetry.CosmosMeterOptions;
import com.azure.cosmos.implementation.clienttelemetry.MetricCategory;
Expand Down Expand Up @@ -1639,6 +1640,11 @@ public interface CosmosClientTelemetryConfigAccessor {
Collection<CosmosDiagnosticsHandler> getDiagnosticHandlers(CosmosClientTelemetryConfig config);
void setAccountName(CosmosClientTelemetryConfig config, String accountName);
String getAccountName(CosmosClientTelemetryConfig config);
CosmosClientTelemetryConfig setOtelSpanAttributeNamingSchema(
CosmosClientTelemetryConfig config,
String attributeNamingScheme
);
EnumSet<AttributeNamingScheme> getOtelSpanAttributeNamingSchema(CosmosClientTelemetryConfig config);
void setClientCorrelationTag(CosmosClientTelemetryConfig config, Tag clientCorrelationTag);
Tag getClientCorrelationTag(CosmosClientTelemetryConfig config);
void setClientTelemetry(CosmosClientTelemetryConfig config, ClientTelemetry clientTelemetry);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.cosmos.implementation.clienttelemetry;

public enum AttributeNamesCommon {
DB_SYSTEM("db.system"),
DB_OPERATION("db.operation"),
USER_AGENT("user_agent.original");

private final String name;

private AttributeNamesCommon(String name) {
this.name = name;
}

@Override
public String toString() {
return this.name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.cosmos.implementation.clienttelemetry;

public enum AttributeNamesPreV1 {
NET_PEER_NAME("net.peer.name"),
EXCEPTION_ESCAPED("exception.escaped"),
EXCEPTION_TYPE("exception.type"),
EXCEPTION_MESSAGE("exception.message"),
EXCEPTION_STACKTRACE("exception.stacktrace"),
CDB_OPERATION_TYPE("db.cosmosdb.operation_type"),
CDB_RESOURCE_TYPE("db.cosmosdb.resource_type"),
CDB_DB_NAME("db.name"),
CDB_CLIENT_ID("db.cosmosdb.client_id"),
CDB_CONNECTION_MODE("db.cosmosdb.connection_mode"),
CDB_QUERY_STATEMENT("db.statement"),
CDB_OPERATION_ID("db.cosmosdb.operation_id"),
CDB_CONTAINER_NAME("db.cosmosdb.container"),
CDB_STATUS_CODE("db.cosmosdb.status_code"),
CDB_SUB_STATUS_CODE("db.cosmosdb.sub_status_code"),
CDB_REQUEST_CHARGE("db.cosmosdb.request_charge"),
CDB_REQUEST_CONTENT_SIZE("db.cosmosdb.request_content_length"),
CDB_RESPONSE_CONTENT_SIZE("db.cosmosdb.max_response_content_length_bytes"),
CDB_RETRY_COUNT("db.cosmosdb.retry_count"),
CDB_CONTACTED_REGIONS("db.cosmosdb.regions_contacted"),
CDB_IS_EMPTY_COMPLETION("db.cosmosdb.is_empty_completion"),
;

private final String name;

private AttributeNamesPreV1(String name) {
this.name = name;
}

@Override
public String toString() {
return this.name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.cosmos.implementation.clienttelemetry;

public enum AttributeNamesV1 {
DB_NAMESPACE("db.namespace"),
DB_SYSTEM_NAME("db.system.name"),
DB_OPERATION_NAME("db.operation.name"),
DB_QUERY_TEXT("db.query.text"),
DB_COLLECTION_NAME("db.collection.name"),
DB_RESPONSE_STATUS_CODE("db.response.status_code"),
DB_OPERATION_BATCH_SIZE("db.operation.batch.size"),
ERROR_TYPE("error.type"),
SERVER_ADDRESS("server.address"),
CLIENT_ID("azure.client.id"),
CDB_NAMESPACE("azure.cosmosdb.namespace"),
CDB_COLLECTION_NAME("azure.cosmosdb.collection.name"),
CDB_CONNECTION_MODE("azure.cosmosdb.connection.mode"),
CDB_OPERATION("azure.cosmosdb.operation"),
CDB_QUERY_TEXT("azure.cosmosdb.query.text"),
CDB_RESPONSE_STATUS_CODE("azure.cosmosdb.response.status_code"),
CDB_RESPONSE_SUB_STATUS_CODE("azure.cosmosdb.response.sub_status_code"),
CDB_ERROR_MESSAGE("azure.cosmosdb.error.message"),
CDB_ERROR_STACKTRACE("azure.cosmosdb.error.stacktrace"),
CDB_CONSISTENCY_LEVEL("azure.cosmosdb.consistency.level"),
CDB_READ_CONSISTENCY_STRATEGY("azure.cosmosdb.read_consistency.strategy"),
CDB_REQUEST_CHARGE("azure.cosmosdb.operation.request_charge"),
CDB_REQUEST_BODY_SIZE("azure.cosmosdb.request.body.size"),
CDB_MAX_RESPONSE_BODY_SIZE("azure.cosmosdb.response.body.size"),
CDB_RETRY_COUNT("azure.cosmosdb.retry_count"),
CDB_CONTACTED_REGIONS("azure.cosmosdb.operation.contacted_regions"),
CDB_OPERATION_BATCH_SIZE("azure.cosmosdb.operation.batch.size"),
CDB_IS_EMPTY_COMPLETION("azure.cosmosdb.is_empty_completion");

private final String name;

private AttributeNamesV1(String name) {
this.name = name;
}

@Override
public String toString() {
return this.name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.cosmos.implementation.clienttelemetry;

import com.azure.cosmos.implementation.Configs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

public enum AttributeNamingScheme {
PRE_V1_RELEASE,
V1;

private static final Logger logger = LoggerFactory.getLogger(Configs.class);

public static EnumSet<AttributeNamingScheme> parse(String name) {
if (name == null || name.isEmpty() || "All".equalsIgnoreCase(name) || "Default".equalsIgnoreCase(name)) {
return EnumSet.allOf(AttributeNamingScheme.class);
}

String[] textValues = name.split(",");
List<AttributeNamingScheme> schemeList = new ArrayList<>();
for (String textValue : textValues) {
boolean foundTextValue = false;
for (AttributeNamingScheme scheme : values()) {
if (scheme.name().equalsIgnoreCase(textValue)) {
foundTextValue = true;
schemeList.add(scheme);
break;
}
}

if (!foundTextValue) {
logger.error("Invalid AttributeNamingScheme: " + textValue + " in '" + name +
"' - proceeding with default value 'ALL'");

return EnumSet.allOf(AttributeNamingScheme.class);
}
}

if (schemeList.size() > 0) {
return EnumSet.copyOf(schemeList);
}

return EnumSet.allOf(AttributeNamingScheme.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import com.azure.core.http.ProxyOptions;
import com.azure.core.util.ClientOptions;
import com.azure.core.util.LibraryTelemetryOptions;
import com.azure.core.util.MetricsOptions;
import com.azure.core.util.TracingOptions;
import com.azure.core.util.tracing.Tracer;
Expand All @@ -13,6 +14,7 @@
import com.azure.cosmos.CosmosDiagnosticsThresholds;
import com.azure.cosmos.implementation.*;
import com.azure.cosmos.implementation.apachecommons.lang.StringUtils;
import com.azure.cosmos.implementation.clienttelemetry.AttributeNamingScheme;
import com.azure.cosmos.implementation.clienttelemetry.ClientTelemetry;
import com.azure.cosmos.implementation.clienttelemetry.CosmosMeterOptions;
import com.azure.cosmos.implementation.clienttelemetry.MetricCategory;
Expand Down Expand Up @@ -69,10 +71,9 @@ public final class CosmosClientTelemetryConfig {
private CosmosDiagnosticsThresholds diagnosticsThresholds = new CosmosDiagnosticsThresholds();
private Tracer tracer;
private TracingOptions tracingOptions;

private double samplingRate;

private ShowQueryMode showQueryMode = ShowQueryMode.NONE;
private EnumSet<AttributeNamingScheme> attributeNamingSchemes;

/**
* Instantiates a new Cosmos client telemetry configuration.
Expand All @@ -89,6 +90,7 @@ public CosmosClientTelemetryConfig() {
this.samplingRate = Configs.getMetricsConfig().getSampleRate();
CosmosMicrometerMetricsOptions defaultMetricsOptions = new CosmosMicrometerMetricsOptions();
this.isClientMetricsEnabled = defaultMetricsOptions.isEnabled();
this.attributeNamingSchemes = Configs.getDefaultOtelSpanAttributeNamingScheme();
if (this.isClientMetricsEnabled) {
this.micrometerMetricsOptions = defaultMetricsOptions;
}
Expand All @@ -97,7 +99,7 @@ public CosmosClientTelemetryConfig() {
/**
* Enables or disables sending Cosmos DB client telemetry to the Azure Cosmos DB Service
*
* @deprecated is is not possible to send the telemetry to the service. But client-side telemetry can be
* @deprecated is is not possible to send the telemetry to the service. But client-side telemetry can be
* enabled via {@link CosmosClientTelemetryConfig#diagnosticsHandler(CosmosDiagnosticsHandler)},
* {@link CosmosClientTelemetryConfig#metricsOptions(MetricsOptions)} and
* {@link CosmosClientTelemetryConfig#tracingOptions(TracingOptions)}.
Expand All @@ -106,7 +108,7 @@ public CosmosClientTelemetryConfig() {
* enabled or not
* @return current CosmosClientTelemetryConfig
*/
@Deprecated()
@Deprecated()
public CosmosClientTelemetryConfig sendClientTelemetryToService(boolean enabled) {
return this;
}
Expand Down Expand Up @@ -378,10 +380,10 @@ public CosmosClientTelemetryConfig enableTransportLevelTracing() {
this.isTransportLevelTracingEnabled = true;
return this;
}

/**
* Enables printing query in db.statement attribute and diagnostic logs. By default, query is not printed.
* Users have the option to enable printing parameterized or all queries,
* Users have the option to enable printing parameterized or all queries,
* 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.
* @param showQueryMode the mode for printing none, parameterized or all of the query statements
Expand Down Expand Up @@ -440,15 +442,37 @@ public String toString() {
}

Tracer getOrCreateTracer() {
logger.debug("getOrCreateTracer: {}", this.tracer);
if (this.tracer != null) {
return this.tracer;
}

return TracerProvider.getDefaultProvider().createTracer(
"azure-cosmos",
HttpConstants.Versions.getSdkVersion(),
DiagnosticsProvider.RESOURCE_PROVIDER_NAME,
tracingOptions);
LibraryTelemetryOptions libraryOptions = new LibraryTelemetryOptions("azure-cosmos")
.setLibraryVersion(HttpConstants.Versions.getSdkVersion())
.setResourceProviderNamespace(DiagnosticsProvider.RESOURCE_PROVIDER_NAME);

Tracer tracerCandidate = TracerProvider.getDefaultProvider().createTracer(
libraryOptions,
tracingOptions
);

logger.debug(
"TracerCandidate from config: {} - {} - {}",
tracerCandidate,
tracingOptions != null ? String.valueOf(tracingOptions.isEnabled()) : "null",
tracerCandidate.isEnabled());

return tracerCandidate;
}

CosmosClientTelemetryConfig setOtelSpanAttributeNamingScheme(String name) {
this.attributeNamingSchemes = AttributeNamingScheme.parse(name);

return this;
}

EnumSet<AttributeNamingScheme> getOtelSpanAttributeNamingScheme() {
return this.attributeNamingSchemes.clone();
}

private static class JsonProxyOptionsConfig {
Expand Down Expand Up @@ -568,6 +592,16 @@ public String getAccountName(CosmosClientTelemetryConfig config) {
return config.getAccountName();
}

@Override
public CosmosClientTelemetryConfig setOtelSpanAttributeNamingSchema(CosmosClientTelemetryConfig config, String attributeNamingScheme) {
return config.setOtelSpanAttributeNamingScheme(attributeNamingScheme);
}

@Override
public EnumSet<AttributeNamingScheme> getOtelSpanAttributeNamingSchema(CosmosClientTelemetryConfig config) {
return config.getOtelSpanAttributeNamingScheme();
}

@Override
public void setClientCorrelationTag(CosmosClientTelemetryConfig config, Tag clientCorrelationTag) {
config.setClientCorrelationTag(clientCorrelationTag);
Expand Down Expand Up @@ -643,7 +677,7 @@ public double getSamplingRate(CosmosClientTelemetryConfig config) {
public ShowQueryMode showQueryMode(CosmosClientTelemetryConfig config) {
return config.showQueryMode;
}

@Override
public double[] getDefaultPercentiles(CosmosClientTelemetryConfig config) {
return config.micrometerMetricsOptions.getDefaultPercentiles();
Expand Down