Skip to content

Commit 815a250

Browse files
committed
Move high-cardinality tags from low-cardinality to high-cardinality
Connection IDs, cursor IDs, session IDs, transaction numbers, and exception details were tagged as low-cardinality, causing unbounded Prometheus metric cardinality since their values change per-connection, per-cursor, or per-error. Moved CLIENT_CONNECTION_ID, SERVER_CONNECTION_ID, CURSOR_ID,TRANSACTION_NUMBER, SESSION_ID, EXCEPTION_MESSAGE, EXCEPTION_TYPE, and EXCEPTION_STACKTRACE from CommandLowCardinalityKeyNames to HighCardinalityKeyNames so they appear only in traces, not in metrics. Added tagHighCardinality(KeyValue) and tagHighCardinality(KeyValues) to the Span interface to support string-valued high-cardinality tags alongside the existing BsonDocument overload.
1 parent 4912105 commit 815a250

5 files changed

Lines changed: 77 additions & 40 deletions

File tree

driver-core/src/main/com/mongodb/internal/observability/micrometer/MicrometerTracer.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@
3333
import java.io.PrintWriter;
3434
import java.io.StringWriter;
3535

36-
import static com.mongodb.internal.observability.micrometer.MongodbObservation.CommandLowCardinalityKeyNames.EXCEPTION_MESSAGE;
37-
import static com.mongodb.internal.observability.micrometer.MongodbObservation.CommandLowCardinalityKeyNames.EXCEPTION_STACKTRACE;
38-
import static com.mongodb.internal.observability.micrometer.MongodbObservation.CommandLowCardinalityKeyNames.EXCEPTION_TYPE;
36+
import static com.mongodb.internal.observability.micrometer.MongodbObservation.HighCardinalityKeyNames.EXCEPTION_MESSAGE;
37+
import static com.mongodb.internal.observability.micrometer.MongodbObservation.HighCardinalityKeyNames.EXCEPTION_STACKTRACE;
38+
import static com.mongodb.internal.observability.micrometer.MongodbObservation.HighCardinalityKeyNames.EXCEPTION_TYPE;
3939
import static com.mongodb.internal.observability.micrometer.TracingManager.ENV_OBSERVABILITY_QUERY_TEXT_MAX_LENGTH;
4040
import static java.lang.System.getenv;
4141
import static java.util.Optional.ofNullable;
@@ -161,6 +161,16 @@ public void tagLowCardinality(final KeyValues keyValues) {
161161
observation.lowCardinalityKeyValues(keyValues);
162162
}
163163

164+
@Override
165+
public void tagHighCardinality(final KeyValue keyValue) {
166+
observation.highCardinalityKeyValue(keyValue);
167+
}
168+
169+
@Override
170+
public void tagHighCardinality(final KeyValues keyValues) {
171+
observation.highCardinalityKeyValues(keyValues);
172+
}
173+
164174
@Override
165175
public void tagHighCardinality(final String keyName, final BsonDocument value) {
166176
observation.highCardinalityKeyValue(keyName,
@@ -176,7 +186,7 @@ public void event(final String event) {
176186

177187
@Override
178188
public void error(final Throwable throwable) {
179-
observation.lowCardinalityKeyValues(KeyValues.of(
189+
observation.highCardinalityKeyValues(KeyValues.of(
180190
EXCEPTION_MESSAGE.withValue(throwable.getMessage()),
181191
EXCEPTION_TYPE.withValue(throwable.getClass().getName()),
182192
EXCEPTION_STACKTRACE.withValue(getStackTraceAsString(throwable))

driver-core/src/main/com/mongodb/internal/observability/micrometer/MongodbObservation.java

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,25 @@ public String asString() {
159159
return "server.port";
160160
}
161161
},
162+
RESPONSE_STATUS_CODE {
163+
@Override
164+
public String asString() {
165+
return "db.response.status_code";
166+
}
167+
}
168+
}
169+
170+
/**
171+
* High cardinality (highly variable values) key names for command-level observations.
172+
*/
173+
public enum HighCardinalityKeyNames implements KeyName {
174+
175+
QUERY_TEXT {
176+
@Override
177+
public String asString() {
178+
return "db.query.text";
179+
}
180+
},
162181
CLIENT_CONNECTION_ID {
163182
@Override
164183
public String asString() {
@@ -189,10 +208,10 @@ public String asString() {
189208
return "db.mongodb.lsid";
190209
}
191210
},
192-
EXCEPTION_STACKTRACE {
211+
EXCEPTION_MESSAGE {
193212
@Override
194213
public String asString() {
195-
return "exception.stacktrace";
214+
return "exception.message";
196215
}
197216
},
198217
EXCEPTION_TYPE {
@@ -201,29 +220,10 @@ public String asString() {
201220
return "exception.type";
202221
}
203222
},
204-
EXCEPTION_MESSAGE {
205-
@Override
206-
public String asString() {
207-
return "exception.message";
208-
}
209-
},
210-
RESPONSE_STATUS_CODE {
211-
@Override
212-
public String asString() {
213-
return "db.response.status_code";
214-
}
215-
}
216-
}
217-
218-
/**
219-
* High cardinality (highly variable values) key names for command-level observations.
220-
*/
221-
public enum HighCardinalityKeyNames implements KeyName {
222-
223-
QUERY_TEXT {
223+
EXCEPTION_STACKTRACE {
224224
@Override
225225
public String asString() {
226-
return "db.query.text";
226+
return "exception.stacktrace";
227227
}
228228
}
229229
}

driver-core/src/main/com/mongodb/internal/observability/micrometer/Span.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ public void tagLowCardinality(final KeyValue tag) {
5555
public void tagLowCardinality(final KeyValues keyValues) {
5656
}
5757

58+
@Override
59+
public void tagHighCardinality(final KeyValue keyValue) {
60+
}
61+
62+
@Override
63+
public void tagHighCardinality(final KeyValues keyValues) {
64+
}
65+
5866
@Override
5967
public void tagHighCardinality(final String keyName, final BsonDocument value) {
6068
}
@@ -97,6 +105,20 @@ public MongoNamespace getNamespace() {
97105
*/
98106
void tagLowCardinality(KeyValues keyValues);
99107

108+
/**
109+
* Adds a high-cardinality tag to the span.
110+
*
111+
* @param keyValue The key-value pair representing the tag.
112+
*/
113+
void tagHighCardinality(KeyValue keyValue);
114+
115+
/**
116+
* Adds multiple high-cardinality tags to the span.
117+
*
118+
* @param keyValues The key-value pairs representing the tags.
119+
*/
120+
void tagHighCardinality(KeyValues keyValues);
121+
100122
/**
101123
* Adds a high-cardinality (highly variable values) tag to the span with a BSON document value.
102124
*

driver-core/src/main/com/mongodb/internal/observability/micrometer/TracingManager.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import static com.mongodb.internal.observability.micrometer.MongodbObservation.MONGODB_COMMAND;
3838
import static com.mongodb.internal.observability.micrometer.MongodbObservation.MONGODB_OPERATION;
3939
import static com.mongodb.internal.observability.micrometer.MongodbObservation.CommandLowCardinalityKeyNames;
40+
import static com.mongodb.internal.observability.micrometer.MongodbObservation.HighCardinalityKeyNames;
4041
import static com.mongodb.internal.observability.micrometer.MongodbObservation.OperationLowCardinalityKeyNames;
4142
import static java.lang.System.getenv;
4243

@@ -194,9 +195,9 @@ public Span createTracingSpan(final CommandMessage message,
194195

195196
if (command.containsKey("getMore")) {
196197
long cursorId = command.getInt64("getMore").longValue();
197-
span.tagLowCardinality(CommandLowCardinalityKeyNames.CURSOR_ID.withValue(String.valueOf(cursorId)));
198+
span.tagHighCardinality(HighCardinalityKeyNames.CURSOR_ID.withValue(String.valueOf(cursorId)));
198199
if (operationSpan != null) {
199-
operationSpan.tagLowCardinality(CommandLowCardinalityKeyNames.CURSOR_ID.withValue(String.valueOf(cursorId)));
200+
operationSpan.tagHighCardinality(HighCardinalityKeyNames.CURSOR_ID.withValue(String.valueOf(cursorId)));
200201
}
201202
}
202203

@@ -231,21 +232,25 @@ public Span createTracingSpan(final CommandMessage message,
231232

232233
// tag server and connection info
233234
ServerAddress serverAddress = serverAddressSupplier.get();
234-
ConnectionId connectionId = connectionIdSupplier.get();
235235
span.tagLowCardinality(KeyValues.of(
236236
CommandLowCardinalityKeyNames.SERVER_ADDRESS.withValue(serverAddress.getHost()),
237237
CommandLowCardinalityKeyNames.SERVER_PORT.withValue(String.valueOf(serverAddress.getPort())),
238-
CommandLowCardinalityKeyNames.CLIENT_CONNECTION_ID.withValue(String.valueOf(connectionId.getLocalValue())),
239-
CommandLowCardinalityKeyNames.SERVER_CONNECTION_ID.withValue(String.valueOf(connectionId.getServerValue())),
240238
CommandLowCardinalityKeyNames.NETWORK_TRANSPORT.withValue(serverAddress instanceof UnixServerAddress ? "unix" : "tcp")
241239
));
242240

241+
// tag connection info
242+
ConnectionId connectionId = connectionIdSupplier.get();
243+
span.tagHighCardinality(KeyValues.of(
244+
HighCardinalityKeyNames.CLIENT_CONNECTION_ID.withValue(String.valueOf(connectionId.getLocalValue())),
245+
HighCardinalityKeyNames.SERVER_CONNECTION_ID.withValue(String.valueOf(connectionId.getServerValue()))
246+
));
247+
243248
// tag session and transaction info
244249
SessionContext sessionContext = operationContext.getSessionContext();
245250
if (sessionContext.hasSession() && !sessionContext.isImplicitSession()) {
246-
span.tagLowCardinality(KeyValues.of(
247-
CommandLowCardinalityKeyNames.TRANSACTION_NUMBER.withValue(String.valueOf(sessionContext.getTransactionNumber())),
248-
CommandLowCardinalityKeyNames.SESSION_ID.withValue(String.valueOf(sessionContext.getSessionId()
251+
span.tagHighCardinality(KeyValues.of(
252+
HighCardinalityKeyNames.TRANSACTION_NUMBER.withValue(String.valueOf(sessionContext.getTransactionNumber())),
253+
HighCardinalityKeyNames.SESSION_ID.withValue(String.valueOf(sessionContext.getSessionId()
249254
.get(sessionContext.getSessionId().getFirstKey())
250255
.asBinary().asUuid()))
251256
));

driver-sync/src/test/functional/com/mongodb/client/observability/SpanTree.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@
3434
import java.util.UUID;
3535
import java.util.function.BiConsumer;
3636

37-
import static com.mongodb.internal.observability.micrometer.MongodbObservation.CommandLowCardinalityKeyNames.CLIENT_CONNECTION_ID;
38-
import static com.mongodb.internal.observability.micrometer.MongodbObservation.CommandLowCardinalityKeyNames.CURSOR_ID;
39-
import static com.mongodb.internal.observability.micrometer.MongodbObservation.CommandLowCardinalityKeyNames.SERVER_CONNECTION_ID;
4037
import static com.mongodb.internal.observability.micrometer.MongodbObservation.CommandLowCardinalityKeyNames.SERVER_PORT;
41-
import static com.mongodb.internal.observability.micrometer.MongodbObservation.CommandLowCardinalityKeyNames.SESSION_ID;
42-
import static com.mongodb.internal.observability.micrometer.MongodbObservation.CommandLowCardinalityKeyNames.TRANSACTION_NUMBER;
38+
import static com.mongodb.internal.observability.micrometer.MongodbObservation.HighCardinalityKeyNames.CLIENT_CONNECTION_ID;
39+
import static com.mongodb.internal.observability.micrometer.MongodbObservation.HighCardinalityKeyNames.CURSOR_ID;
40+
import static com.mongodb.internal.observability.micrometer.MongodbObservation.HighCardinalityKeyNames.SERVER_CONNECTION_ID;
41+
import static com.mongodb.internal.observability.micrometer.MongodbObservation.HighCardinalityKeyNames.SESSION_ID;
42+
import static com.mongodb.internal.observability.micrometer.MongodbObservation.HighCardinalityKeyNames.TRANSACTION_NUMBER;
4343
import static org.bson.assertions.Assertions.notNull;
4444
import static org.junit.jupiter.api.Assertions.fail;
4545

0 commit comments

Comments
 (0)