Skip to content

Commit 0dca69d

Browse files
Fixing OpenTelemetryTraces to include the GA V1 semantic conventionttributes (#45929)
* Fixing OpenTelemetryTraces to include the GA V1 semantic convention attributes * Update CHANGELOG.md * Update sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/DiagnosticsProvider.java Co-authored-by: Copilot <[email protected]> * Update AttributeNamingScheme.java --------- Co-authored-by: Copilot <[email protected]>
1 parent e374355 commit 0dca69d

File tree

10 files changed

+762
-88
lines changed

10 files changed

+762
-88
lines changed

sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/CosmosTracerTest.java

Lines changed: 300 additions & 20 deletions
Large diffs are not rendered by default.

sdk/cosmos/azure-cosmos/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#### Breaking Changes
88

99
#### Bugs Fixed
10+
* 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)
1011

1112
#### Other Changes
1213

sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package com.azure.cosmos.implementation;
44

55
import com.azure.cosmos.implementation.apachecommons.lang.StringUtils;
6+
import com.azure.cosmos.implementation.clienttelemetry.AttributeNamingScheme;
67
import com.azure.cosmos.implementation.perPartitionCircuitBreaker.PartitionLevelCircuitBreakerConfig;
78
import com.azure.cosmos.implementation.directconnectivity.Protocol;
89
import io.netty.handler.ssl.ApplicationProtocolConfig;
@@ -16,6 +17,7 @@
1617
import javax.net.ssl.SSLException;
1718
import java.net.URI;
1819
import java.time.Duration;
20+
import java.util.EnumSet;
1921
import java.util.Locale;
2022

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

359+
// Config to indicate whether to emit Open Telemetry traces with attribute names following the
360+
// original implementation (`PRE_V1_RELEASE`) or the official semantic convention (`V1`) or both (`ALL`)
361+
public static final String OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME = "COSMOS.OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME";
362+
public static final String OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME_VARIABLE = "COSMOS_OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME";
363+
364+
public static final String DEFAULT_OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME = "All";
365+
357366
public static int getCPUCnt() {
358367
return CPU_CNT;
359368
}
@@ -1195,4 +1204,18 @@ public static int getWarnLevelLoggingThresholdForPpaf() {
11951204

11961205
return Integer.parseInt(warnLevelLoggingThresholdForPpaf);
11971206
}
1207+
1208+
public static EnumSet<AttributeNamingScheme> getDefaultOtelSpanAttributeNamingScheme() {
1209+
String valueFromSystemProperty = System.getProperty(OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME);
1210+
if (valueFromSystemProperty != null && !valueFromSystemProperty.isEmpty()) {
1211+
return AttributeNamingScheme.parse(valueFromSystemProperty);
1212+
}
1213+
1214+
String valueFromEnvVariable = System.getenv(OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME_VARIABLE);
1215+
if (valueFromEnvVariable != null && !valueFromEnvVariable.isEmpty()) {
1216+
return AttributeNamingScheme.parse(valueFromEnvVariable);
1217+
}
1218+
1219+
return AttributeNamingScheme.parse(DEFAULT_OTEL_SPAN_ATTRIBUTE_NAMING_SCHEME);
1220+
}
11981221
}

sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/DiagnosticsProvider.java

Lines changed: 232 additions & 56 deletions
Large diffs are not rendered by default.

sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/ImplementationBridgeHelpers.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.azure.cosmos.implementation.apachecommons.lang.tuple.Pair;
3434
import com.azure.cosmos.implementation.batch.ItemBatchOperation;
3535
import com.azure.cosmos.implementation.batch.PartitionScopeThresholds;
36+
import com.azure.cosmos.implementation.clienttelemetry.AttributeNamingScheme;
3637
import com.azure.cosmos.implementation.clienttelemetry.ClientTelemetry;
3738
import com.azure.cosmos.implementation.clienttelemetry.CosmosMeterOptions;
3839
import com.azure.cosmos.implementation.clienttelemetry.MetricCategory;
@@ -1639,6 +1640,11 @@ public interface CosmosClientTelemetryConfigAccessor {
16391640
Collection<CosmosDiagnosticsHandler> getDiagnosticHandlers(CosmosClientTelemetryConfig config);
16401641
void setAccountName(CosmosClientTelemetryConfig config, String accountName);
16411642
String getAccountName(CosmosClientTelemetryConfig config);
1643+
CosmosClientTelemetryConfig setOtelSpanAttributeNamingSchema(
1644+
CosmosClientTelemetryConfig config,
1645+
String attributeNamingScheme
1646+
);
1647+
EnumSet<AttributeNamingScheme> getOtelSpanAttributeNamingSchema(CosmosClientTelemetryConfig config);
16421648
void setClientCorrelationTag(CosmosClientTelemetryConfig config, Tag clientCorrelationTag);
16431649
Tag getClientCorrelationTag(CosmosClientTelemetryConfig config);
16441650
void setClientTelemetry(CosmosClientTelemetryConfig config, ClientTelemetry clientTelemetry);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
package com.azure.cosmos.implementation.clienttelemetry;
4+
5+
public enum AttributeNamesCommon {
6+
DB_SYSTEM("db.system"),
7+
DB_OPERATION("db.operation"),
8+
USER_AGENT("user_agent.original");
9+
10+
private final String name;
11+
12+
private AttributeNamesCommon(String name) {
13+
this.name = name;
14+
}
15+
16+
@Override
17+
public String toString() {
18+
return this.name;
19+
}
20+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
package com.azure.cosmos.implementation.clienttelemetry;
4+
5+
public enum AttributeNamesPreV1 {
6+
NET_PEER_NAME("net.peer.name"),
7+
EXCEPTION_ESCAPED("exception.escaped"),
8+
EXCEPTION_TYPE("exception.type"),
9+
EXCEPTION_MESSAGE("exception.message"),
10+
EXCEPTION_STACKTRACE("exception.stacktrace"),
11+
CDB_OPERATION_TYPE("db.cosmosdb.operation_type"),
12+
CDB_RESOURCE_TYPE("db.cosmosdb.resource_type"),
13+
CDB_DB_NAME("db.name"),
14+
CDB_CLIENT_ID("db.cosmosdb.client_id"),
15+
CDB_CONNECTION_MODE("db.cosmosdb.connection_mode"),
16+
CDB_QUERY_STATEMENT("db.statement"),
17+
CDB_OPERATION_ID("db.cosmosdb.operation_id"),
18+
CDB_CONTAINER_NAME("db.cosmosdb.container"),
19+
CDB_STATUS_CODE("db.cosmosdb.status_code"),
20+
CDB_SUB_STATUS_CODE("db.cosmosdb.sub_status_code"),
21+
CDB_REQUEST_CHARGE("db.cosmosdb.request_charge"),
22+
CDB_REQUEST_CONTENT_SIZE("db.cosmosdb.request_content_length"),
23+
CDB_RESPONSE_CONTENT_SIZE("db.cosmosdb.max_response_content_length_bytes"),
24+
CDB_RETRY_COUNT("db.cosmosdb.retry_count"),
25+
CDB_CONTACTED_REGIONS("db.cosmosdb.regions_contacted"),
26+
CDB_IS_EMPTY_COMPLETION("db.cosmosdb.is_empty_completion"),
27+
;
28+
29+
private final String name;
30+
31+
private AttributeNamesPreV1(String name) {
32+
this.name = name;
33+
}
34+
35+
@Override
36+
public String toString() {
37+
return this.name;
38+
}
39+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
package com.azure.cosmos.implementation.clienttelemetry;
4+
5+
public enum AttributeNamesV1 {
6+
DB_NAMESPACE("db.namespace"),
7+
DB_SYSTEM_NAME("db.system.name"),
8+
DB_OPERATION_NAME("db.operation.name"),
9+
DB_QUERY_TEXT("db.query.text"),
10+
DB_COLLECTION_NAME("db.collection.name"),
11+
DB_RESPONSE_STATUS_CODE("db.response.status_code"),
12+
DB_OPERATION_BATCH_SIZE("db.operation.batch.size"),
13+
ERROR_TYPE("error.type"),
14+
SERVER_ADDRESS("server.address"),
15+
CLIENT_ID("azure.client.id"),
16+
CDB_NAMESPACE("azure.cosmosdb.namespace"),
17+
CDB_COLLECTION_NAME("azure.cosmosdb.collection.name"),
18+
CDB_CONNECTION_MODE("azure.cosmosdb.connection.mode"),
19+
CDB_OPERATION("azure.cosmosdb.operation"),
20+
CDB_QUERY_TEXT("azure.cosmosdb.query.text"),
21+
CDB_RESPONSE_STATUS_CODE("azure.cosmosdb.response.status_code"),
22+
CDB_RESPONSE_SUB_STATUS_CODE("azure.cosmosdb.response.sub_status_code"),
23+
CDB_ERROR_MESSAGE("azure.cosmosdb.error.message"),
24+
CDB_ERROR_STACKTRACE("azure.cosmosdb.error.stacktrace"),
25+
CDB_CONSISTENCY_LEVEL("azure.cosmosdb.consistency.level"),
26+
CDB_READ_CONSISTENCY_STRATEGY("azure.cosmosdb.read_consistency.strategy"),
27+
CDB_REQUEST_CHARGE("azure.cosmosdb.operation.request_charge"),
28+
CDB_REQUEST_BODY_SIZE("azure.cosmosdb.request.body.size"),
29+
CDB_MAX_RESPONSE_BODY_SIZE("azure.cosmosdb.response.body.size"),
30+
CDB_RETRY_COUNT("azure.cosmosdb.retry_count"),
31+
CDB_CONTACTED_REGIONS("azure.cosmosdb.operation.contacted_regions"),
32+
CDB_OPERATION_BATCH_SIZE("azure.cosmosdb.operation.batch.size"),
33+
CDB_IS_EMPTY_COMPLETION("azure.cosmosdb.is_empty_completion");
34+
35+
private final String name;
36+
37+
private AttributeNamesV1(String name) {
38+
this.name = name;
39+
}
40+
41+
@Override
42+
public String toString() {
43+
return this.name;
44+
}
45+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
package com.azure.cosmos.implementation.clienttelemetry;
4+
5+
import com.azure.cosmos.implementation.Configs;
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
9+
import java.util.ArrayList;
10+
import java.util.EnumSet;
11+
import java.util.List;
12+
13+
public enum AttributeNamingScheme {
14+
PRE_V1_RELEASE,
15+
V1;
16+
17+
private static final Logger logger = LoggerFactory.getLogger(AttributeNamingScheme.class);
18+
19+
public static EnumSet<AttributeNamingScheme> parse(String name) {
20+
if (name == null || name.isEmpty() || "All".equalsIgnoreCase(name) || "Default".equalsIgnoreCase(name)) {
21+
return EnumSet.allOf(AttributeNamingScheme.class);
22+
}
23+
24+
String[] textValues = name.split(",");
25+
List<AttributeNamingScheme> schemeList = new ArrayList<>();
26+
for (String textValue : textValues) {
27+
boolean foundTextValue = false;
28+
for (AttributeNamingScheme scheme : values()) {
29+
if (scheme.name().equalsIgnoreCase(textValue)) {
30+
foundTextValue = true;
31+
schemeList.add(scheme);
32+
break;
33+
}
34+
}
35+
36+
if (!foundTextValue) {
37+
logger.error("Invalid AttributeNamingScheme: " + textValue + " in '" + name +
38+
"' - proceeding with default value 'ALL'");
39+
40+
return EnumSet.allOf(AttributeNamingScheme.class);
41+
}
42+
}
43+
44+
if (schemeList.size() > 0) {
45+
return EnumSet.copyOf(schemeList);
46+
}
47+
48+
return EnumSet.allOf(AttributeNamingScheme.class);
49+
}
50+
}

sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosClientTelemetryConfig.java

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import com.azure.core.http.ProxyOptions;
77
import com.azure.core.util.ClientOptions;
8+
import com.azure.core.util.LibraryTelemetryOptions;
89
import com.azure.core.util.MetricsOptions;
910
import com.azure.core.util.TracingOptions;
1011
import com.azure.core.util.tracing.Tracer;
@@ -13,6 +14,7 @@
1314
import com.azure.cosmos.CosmosDiagnosticsThresholds;
1415
import com.azure.cosmos.implementation.*;
1516
import com.azure.cosmos.implementation.apachecommons.lang.StringUtils;
17+
import com.azure.cosmos.implementation.clienttelemetry.AttributeNamingScheme;
1618
import com.azure.cosmos.implementation.clienttelemetry.ClientTelemetry;
1719
import com.azure.cosmos.implementation.clienttelemetry.CosmosMeterOptions;
1820
import com.azure.cosmos.implementation.clienttelemetry.MetricCategory;
@@ -69,10 +71,9 @@ public final class CosmosClientTelemetryConfig {
6971
private CosmosDiagnosticsThresholds diagnosticsThresholds = new CosmosDiagnosticsThresholds();
7072
private Tracer tracer;
7173
private TracingOptions tracingOptions;
72-
7374
private double samplingRate;
74-
7575
private ShowQueryMode showQueryMode = ShowQueryMode.NONE;
76+
private EnumSet<AttributeNamingScheme> attributeNamingSchemes;
7677

7778
/**
7879
* Instantiates a new Cosmos client telemetry configuration.
@@ -89,6 +90,7 @@ public CosmosClientTelemetryConfig() {
8990
this.samplingRate = Configs.getMetricsConfig().getSampleRate();
9091
CosmosMicrometerMetricsOptions defaultMetricsOptions = new CosmosMicrometerMetricsOptions();
9192
this.isClientMetricsEnabled = defaultMetricsOptions.isEnabled();
93+
this.attributeNamingSchemes = Configs.getDefaultOtelSpanAttributeNamingScheme();
9294
if (this.isClientMetricsEnabled) {
9395
this.micrometerMetricsOptions = defaultMetricsOptions;
9496
}
@@ -97,7 +99,7 @@ public CosmosClientTelemetryConfig() {
9799
/**
98100
* Enables or disables sending Cosmos DB client telemetry to the Azure Cosmos DB Service
99101
*
100-
* @deprecated is is not possible to send the telemetry to the service. But client-side telemetry can be
102+
* @deprecated is is not possible to send the telemetry to the service. But client-side telemetry can be
101103
* enabled via {@link CosmosClientTelemetryConfig#diagnosticsHandler(CosmosDiagnosticsHandler)},
102104
* {@link CosmosClientTelemetryConfig#metricsOptions(MetricsOptions)} and
103105
* {@link CosmosClientTelemetryConfig#tracingOptions(TracingOptions)}.
@@ -106,7 +108,7 @@ public CosmosClientTelemetryConfig() {
106108
* enabled or not
107109
* @return current CosmosClientTelemetryConfig
108110
*/
109-
@Deprecated()
111+
@Deprecated()
110112
public CosmosClientTelemetryConfig sendClientTelemetryToService(boolean enabled) {
111113
return this;
112114
}
@@ -378,10 +380,10 @@ public CosmosClientTelemetryConfig enableTransportLevelTracing() {
378380
this.isTransportLevelTracingEnabled = true;
379381
return this;
380382
}
381-
383+
382384
/**
383385
* Enables printing query in db.statement attribute and diagnostic logs. By default, query is not printed.
384-
* Users have the option to enable printing parameterized or all queries,
386+
* Users have the option to enable printing parameterized or all queries,
385387
* but has to beware that customer data may be shown when the later option is chosen
386388
* It's the user's responsibility to sanitize the queries if necessary.
387389
* @param showQueryMode the mode for printing none, parameterized or all of the query statements
@@ -440,15 +442,37 @@ public String toString() {
440442
}
441443

442444
Tracer getOrCreateTracer() {
445+
logger.debug("getOrCreateTracer: {}", this.tracer);
443446
if (this.tracer != null) {
444447
return this.tracer;
445448
}
446449

447-
return TracerProvider.getDefaultProvider().createTracer(
448-
"azure-cosmos",
449-
HttpConstants.Versions.getSdkVersion(),
450-
DiagnosticsProvider.RESOURCE_PROVIDER_NAME,
451-
tracingOptions);
450+
LibraryTelemetryOptions libraryOptions = new LibraryTelemetryOptions("azure-cosmos")
451+
.setLibraryVersion(HttpConstants.Versions.getSdkVersion())
452+
.setResourceProviderNamespace(DiagnosticsProvider.RESOURCE_PROVIDER_NAME);
453+
454+
Tracer tracerCandidate = TracerProvider.getDefaultProvider().createTracer(
455+
libraryOptions,
456+
tracingOptions
457+
);
458+
459+
logger.debug(
460+
"TracerCandidate from config: {} - {} - {}",
461+
tracerCandidate,
462+
tracingOptions != null ? String.valueOf(tracingOptions.isEnabled()) : "null",
463+
tracerCandidate.isEnabled());
464+
465+
return tracerCandidate;
466+
}
467+
468+
CosmosClientTelemetryConfig setOtelSpanAttributeNamingScheme(String name) {
469+
this.attributeNamingSchemes = AttributeNamingScheme.parse(name);
470+
471+
return this;
472+
}
473+
474+
EnumSet<AttributeNamingScheme> getOtelSpanAttributeNamingScheme() {
475+
return this.attributeNamingSchemes.clone();
452476
}
453477

454478
private static class JsonProxyOptionsConfig {
@@ -568,6 +592,16 @@ public String getAccountName(CosmosClientTelemetryConfig config) {
568592
return config.getAccountName();
569593
}
570594

595+
@Override
596+
public CosmosClientTelemetryConfig setOtelSpanAttributeNamingSchema(CosmosClientTelemetryConfig config, String attributeNamingScheme) {
597+
return config.setOtelSpanAttributeNamingScheme(attributeNamingScheme);
598+
}
599+
600+
@Override
601+
public EnumSet<AttributeNamingScheme> getOtelSpanAttributeNamingSchema(CosmosClientTelemetryConfig config) {
602+
return config.getOtelSpanAttributeNamingScheme();
603+
}
604+
571605
@Override
572606
public void setClientCorrelationTag(CosmosClientTelemetryConfig config, Tag clientCorrelationTag) {
573607
config.setClientCorrelationTag(clientCorrelationTag);
@@ -643,7 +677,7 @@ public double getSamplingRate(CosmosClientTelemetryConfig config) {
643677
public ShowQueryMode showQueryMode(CosmosClientTelemetryConfig config) {
644678
return config.showQueryMode;
645679
}
646-
680+
647681
@Override
648682
public double[] getDefaultPercentiles(CosmosClientTelemetryConfig config) {
649683
return config.micrometerMetricsOptions.getDefaultPercentiles();

0 commit comments

Comments
 (0)