Skip to content

Commit e5c4937

Browse files
authored
Merge pull request #408 from trask/jdbc-batch
Updates to jdbc-batch
2 parents a095e6e + 0062bae commit e5c4937

File tree

13 files changed

+148
-150
lines changed

13 files changed

+148
-150
lines changed

instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientSpanNameExtractor.java

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55

66
package io.opentelemetry.instrumentation.api.incubator.semconv.db;
77

8-
import io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.MultiQuerySqlClientAttributesGetter;
98
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
109
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
10+
import java.util.Collection;
1111

1212
public abstract class DbClientSpanNameExtractor<REQUEST> implements SpanNameExtractor<REQUEST> {
1313

@@ -95,39 +95,41 @@ private SqlClientSpanNameExtractor(SqlClientAttributesGetter<REQUEST> getter) {
9595

9696
@Override
9797
public String extract(REQUEST request) {
98-
boolean isMultiQuery = false;
99-
MultiQuerySqlClientAttributesGetter<REQUEST> multiGetter = null;
100-
if (getter instanceof MultiQuerySqlClientAttributesGetter) {
101-
multiGetter = (MultiQuerySqlClientAttributesGetter<REQUEST>) getter;
102-
isMultiQuery = multiGetter.getRawQueryTexts(request).size() > 1;
103-
}
98+
String namespace = getter.getDbNamespace(request);
99+
Collection<String> rawQueryTexts = getter.getRawQueryTexts(request);
104100

105-
Long batchSize = getter.getBatchSize(request);
106-
boolean isBatch = batchSize != null && batchSize > 1;
101+
if (rawQueryTexts.isEmpty()) {
102+
return computeSpanName(namespace, null, null);
103+
}
107104

108-
String namespace = getter.getDbNamespace(request);
109-
if (!isBatch || (!SemconvStability.emitStableDatabaseSemconv() && !isMultiQuery)) {
110-
SqlStatementInfo sanitizedStatement = sanitizer.sanitize(getter.getRawQueryText(request));
105+
if (!SemconvStability.emitStableDatabaseSemconv()) {
106+
if (rawQueryTexts.size() > 1) { // for backcompat(?)
107+
return computeSpanName(namespace, null, null);
108+
}
109+
SqlStatementInfo sanitizedStatement = sanitizer.sanitize(rawQueryTexts.iterator().next());
111110
return computeSpanName(
112111
namespace, sanitizedStatement.getOperation(), sanitizedStatement.getMainIdentifier());
113-
} else if (SemconvStability.emitStableDatabaseSemconv()) {
114-
if (!isMultiQuery) { // batch query with single unique query
115-
SqlStatementInfo sanitizedStatement = sanitizer.sanitize(getter.getRawQueryText(request));
116-
return computeSpanName(
117-
namespace,
118-
"BATCH " + sanitizedStatement.getOperation(),
119-
sanitizedStatement.getMainIdentifier());
120-
} else { // batch query with multiple unique queries
121-
MultiQuery multiQuery = MultiQuery.analyze(multiGetter.getRawQueryTexts(request), false);
122-
123-
return computeSpanName(
124-
namespace,
125-
multiQuery.getOperation() != null ? "BATCH " + multiQuery.getOperation() : "BATCH",
126-
multiQuery.getMainIdentifier());
112+
}
113+
114+
if (rawQueryTexts.size() == 1) {
115+
SqlStatementInfo sanitizedStatement = sanitizer.sanitize(rawQueryTexts.iterator().next());
116+
String operation = sanitizedStatement.getOperation();
117+
if (isBatch(request)) {
118+
operation = "BATCH " + operation;
127119
}
128-
} else {
129-
return computeSpanName(namespace, null, null);
120+
return computeSpanName(namespace, operation, sanitizedStatement.getMainIdentifier());
130121
}
122+
123+
MultiQuery multiQuery = MultiQuery.analyze(rawQueryTexts, false);
124+
return computeSpanName(
125+
namespace,
126+
multiQuery.getOperation() != null ? "BATCH " + multiQuery.getOperation() : "BATCH",
127+
multiQuery.getMainIdentifier());
128+
}
129+
130+
private boolean isBatch(REQUEST request) {
131+
Long batchSize = getter.getBatchSize(request);
132+
return batchSize != null && batchSize > 1;
131133
}
132134
}
133135
}

instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractor.java

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import io.opentelemetry.api.common.AttributeKey;
1111
import io.opentelemetry.api.common.AttributesBuilder;
1212
import io.opentelemetry.context.Context;
13-
import io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.MultiQuerySqlClientAttributesGetter;
1413
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
1514
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
1615
import java.util.Collection;
@@ -75,61 +74,60 @@ public static <REQUEST, RESPONSE> SqlClientAttributesExtractorBuilder<REQUEST, R
7574
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {
7675
super.onStart(attributes, parentContext, request);
7776

78-
boolean isMultiQuery = false;
79-
MultiQuerySqlClientAttributesGetter<REQUEST> multiGetter = null;
80-
if (getter instanceof MultiQuerySqlClientAttributesGetter) {
81-
multiGetter = (MultiQuerySqlClientAttributesGetter<REQUEST>) getter;
82-
isMultiQuery = multiGetter.getRawQueryTexts(request).size() > 1;
83-
}
77+
Collection<String> rawQueryTexts = getter.getRawQueryTexts(request);
8478

85-
Long batchSize = getter.getBatchSize(request);
86-
boolean isBatch = batchSize != null && batchSize > 1;
79+
if (rawQueryTexts.isEmpty()) {
80+
return;
81+
}
8782

88-
if (!isMultiQuery) {
89-
String rawQueryText = getter.getRawQueryText(request);
90-
SqlStatementInfo sanitizedStatement = sanitizer.sanitize(rawQueryText);
91-
String operation = sanitizedStatement.getOperation();
92-
if (SemconvStability.emitStableDatabaseSemconv()) {
83+
if (SemconvStability.emitOldDatabaseSemconv()) {
84+
if (rawQueryTexts.size() == 1) { // for backcompat(?)
85+
String rawQueryText = rawQueryTexts.iterator().next();
86+
SqlStatementInfo sanitizedStatement = sanitizer.sanitize(rawQueryText);
87+
String operation = sanitizedStatement.getOperation();
9388
internalSet(
9489
attributes,
95-
DB_QUERY_TEXT,
90+
DB_STATEMENT,
9691
statementSanitizationEnabled ? sanitizedStatement.getFullStatement() : rawQueryText);
97-
if (operation != null) {
98-
internalSet(attributes, DB_OPERATION_NAME, (isBatch ? "BATCH " : "") + operation);
92+
internalSet(attributes, DB_OPERATION, operation);
93+
if (!SQL_CALL.equals(operation)) {
94+
internalSet(attributes, oldSemconvTableAttribute, sanitizedStatement.getMainIdentifier());
9995
}
10096
}
101-
if (SemconvStability.emitOldDatabaseSemconv()) {
97+
}
98+
99+
if (SemconvStability.emitStableDatabaseSemconv()) {
100+
Long batchSize = getter.getBatchSize(request);
101+
boolean isBatch = batchSize != null && batchSize > 1;
102+
if (isBatch) {
103+
internalSet(attributes, DB_OPERATION_BATCH_SIZE, batchSize);
104+
}
105+
if (rawQueryTexts.size() == 1) {
106+
String rawQueryText = rawQueryTexts.iterator().next();
107+
SqlStatementInfo sanitizedStatement = sanitizer.sanitize(rawQueryText);
108+
String operation = sanitizedStatement.getOperation();
102109
internalSet(
103110
attributes,
104-
DB_STATEMENT,
111+
DB_QUERY_TEXT,
105112
statementSanitizationEnabled ? sanitizedStatement.getFullStatement() : rawQueryText);
106-
internalSet(attributes, DB_OPERATION, operation);
107-
}
108-
if (!SQL_CALL.equals(operation)) {
109-
if (SemconvStability.emitStableDatabaseSemconv()) {
113+
internalSet(attributes, DB_OPERATION_NAME, isBatch ? "BATCH " + operation : operation);
114+
if (!SQL_CALL.equals(operation)) {
110115
internalSet(attributes, DB_COLLECTION_NAME, sanitizedStatement.getMainIdentifier());
111116
}
112-
if (SemconvStability.emitOldDatabaseSemconv()) {
113-
internalSet(attributes, oldSemconvTableAttribute, sanitizedStatement.getMainIdentifier());
117+
} else {
118+
MultiQuery multiQuery =
119+
MultiQuery.analyze(getter.getRawQueryTexts(request), statementSanitizationEnabled);
120+
internalSet(attributes, DB_QUERY_TEXT, join("; ", multiQuery.getStatements()));
121+
122+
String operation =
123+
multiQuery.getOperation() != null ? "BATCH " + multiQuery.getOperation() : "BATCH";
124+
internalSet(attributes, DB_OPERATION_NAME, operation);
125+
126+
if (multiQuery.getMainIdentifier() != null
127+
&& (multiQuery.getOperation() == null || !SQL_CALL.equals(multiQuery.getOperation()))) {
128+
internalSet(attributes, DB_COLLECTION_NAME, multiQuery.getMainIdentifier());
114129
}
115130
}
116-
if (SemconvStability.emitStableDatabaseSemconv() && isBatch) {
117-
internalSet(attributes, DB_OPERATION_BATCH_SIZE, batchSize);
118-
}
119-
} else if (SemconvStability.emitStableDatabaseSemconv()) {
120-
MultiQuery multiQuery =
121-
MultiQuery.analyze(multiGetter.getRawQueryTexts(request), statementSanitizationEnabled);
122-
123-
internalSet(attributes, DB_QUERY_TEXT, join(";", multiQuery.getStatements()));
124-
String operation =
125-
multiQuery.getOperation() != null ? "BATCH " + multiQuery.getOperation() : "BATCH";
126-
internalSet(attributes, DB_OPERATION_NAME, operation);
127-
128-
if (multiQuery.getMainIdentifier() != null
129-
&& (multiQuery.getOperation() == null || !SQL_CALL.equals(multiQuery.getOperation()))) {
130-
internalSet(attributes, DB_COLLECTION_NAME, multiQuery.getMainIdentifier());
131-
}
132-
internalSet(attributes, DB_OPERATION_BATCH_SIZE, batchSize);
133131
}
134132
}
135133

instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesGetter.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
package io.opentelemetry.instrumentation.api.incubator.semconv.db;
77

8+
import static java.util.Collections.emptySet;
9+
import static java.util.Collections.singleton;
10+
11+
import java.util.Collection;
812
import javax.annotation.Nullable;
913

1014
/**
@@ -33,12 +37,31 @@ default String getRawStatement(REQUEST request) {
3337
return null;
3438
}
3539

36-
// TODO: make this required to implement
40+
/**
41+
* Get the raw SQL query text. The value returned by this method is later sanitized by the {@link
42+
* SqlClientAttributesExtractor} before being set as span attribute.
43+
*
44+
* @deprecated Use {@link #getRawQueryTexts(Object)} instead.
45+
*/
46+
@Deprecated
3747
@Nullable
3848
default String getRawQueryText(REQUEST request) {
3949
return getRawStatement(request);
4050
}
4151

52+
/**
53+
* Get the raw SQL query texts. The values returned by this method is later sanitized by the
54+
* {@link SqlClientAttributesExtractor} before being set as span attribute.
55+
*
56+
* <p>If {@code request} is not a batch query, then this method should return a collection with a
57+
* single element.
58+
*/
59+
// TODO: make this required to implement
60+
default Collection<String> getRawQueryTexts(REQUEST request) {
61+
String rawQueryText = getRawQueryText(request);
62+
return rawQueryText == null ? emptySet() : singleton(rawQueryText);
63+
}
64+
4265
// TODO: make this required to implement
4366
default Long getBatchSize(REQUEST request) {
4467
return null;

instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/MultiQuerySqlClientAttributesGetter.java

Lines changed: 0 additions & 27 deletions
This file was deleted.

instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientSpanNameExtractorTest.java

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55

66
package io.opentelemetry.instrumentation.api.incubator.semconv.db;
77

8+
import static java.util.Collections.singleton;
89
import static org.junit.jupiter.api.Assertions.assertEquals;
910
import static org.mockito.Mockito.when;
1011

11-
import io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.MultiQuerySqlClientAttributesGetter;
1212
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
1313
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
1414
import java.util.Arrays;
15-
import java.util.Collections;
1615
import org.junit.jupiter.api.Test;
1716
import org.junit.jupiter.api.extension.ExtendWith;
1817
import org.mockito.Mock;
@@ -22,14 +21,14 @@
2221
class DbClientSpanNameExtractorTest {
2322
@Mock DbClientAttributesGetter<DbRequest> dbAttributesGetter;
2423
@Mock SqlClientAttributesGetter<DbRequest> sqlAttributesGetter;
25-
@Mock MultiQuerySqlClientAttributesGetter<DbRequest> multiQuerySqlClientAttributesGetter;
2624

2725
@Test
2826
void shouldExtractFullSpanName() {
2927
// given
3028
DbRequest dbRequest = new DbRequest();
3129

32-
when(sqlAttributesGetter.getRawQueryText(dbRequest)).thenReturn("SELECT * from table");
30+
when(sqlAttributesGetter.getRawQueryTexts(dbRequest))
31+
.thenReturn(singleton("SELECT * from table"));
3332
when(sqlAttributesGetter.getDbNamespace(dbRequest)).thenReturn("database");
3433

3534
SpanNameExtractor<DbRequest> underTest = DbClientSpanNameExtractor.create(sqlAttributesGetter);
@@ -46,7 +45,8 @@ void shouldSkipDbNameIfTableAlreadyHasDbNamePrefix() {
4645
// given
4746
DbRequest dbRequest = new DbRequest();
4847

49-
when(sqlAttributesGetter.getRawQueryText(dbRequest)).thenReturn("SELECT * from another.table");
48+
when(sqlAttributesGetter.getRawQueryTexts(dbRequest))
49+
.thenReturn(singleton("SELECT * from another.table"));
5050
when(sqlAttributesGetter.getDbNamespace(dbRequest)).thenReturn("database");
5151

5252
SpanNameExtractor<DbRequest> underTest = DbClientSpanNameExtractor.create(sqlAttributesGetter);
@@ -63,7 +63,8 @@ void shouldExtractOperationAndTable() {
6363
// given
6464
DbRequest dbRequest = new DbRequest();
6565

66-
when(sqlAttributesGetter.getRawQueryText(dbRequest)).thenReturn("SELECT * from table");
66+
when(sqlAttributesGetter.getRawQueryTexts(dbRequest))
67+
.thenReturn(singleton("SELECT * from table"));
6768

6869
SpanNameExtractor<DbRequest> underTest = DbClientSpanNameExtractor.create(sqlAttributesGetter);
6970

@@ -142,13 +143,11 @@ void shouldExtractFullSpanNameForBatch() {
142143
// given
143144
DbRequest dbRequest = new DbRequest();
144145

145-
when(multiQuerySqlClientAttributesGetter.getRawQueryTexts(dbRequest))
146+
when(sqlAttributesGetter.getRawQueryTexts(dbRequest))
146147
.thenReturn(Arrays.asList("INSERT INTO table VALUES(1)", "INSERT INTO table VALUES(2)"));
147-
when(multiQuerySqlClientAttributesGetter.getDbNamespace(dbRequest)).thenReturn("database");
148-
when(multiQuerySqlClientAttributesGetter.getBatchSize(dbRequest)).thenReturn(2L);
148+
when(sqlAttributesGetter.getDbNamespace(dbRequest)).thenReturn("database");
149149

150-
SpanNameExtractor<DbRequest> underTest =
151-
DbClientSpanNameExtractor.create(multiQuerySqlClientAttributesGetter);
150+
SpanNameExtractor<DbRequest> underTest = DbClientSpanNameExtractor.create(sqlAttributesGetter);
152151

153152
// when
154153
String spanName = underTest.extract(dbRequest);
@@ -164,24 +163,23 @@ void shouldExtractFullSpanNameForSingleQueryBatch() {
164163
// given
165164
DbRequest dbRequest = new DbRequest();
166165

167-
when(multiQuerySqlClientAttributesGetter.getRawQueryTexts(dbRequest))
168-
.thenReturn(Collections.singletonList("INSERT INTO table VALUES(?)"));
166+
when(sqlAttributesGetter.getRawQueryTexts(dbRequest))
167+
.thenReturn(singleton("INSERT INTO table VALUES(?)"));
168+
when(sqlAttributesGetter.getDbNamespace(dbRequest)).thenReturn("database");
169169
if (SemconvStability.emitStableDatabaseSemconv()) {
170-
when(multiQuerySqlClientAttributesGetter.getRawQueryText(dbRequest))
171-
.thenReturn("INSERT INTO table VALUES(?)");
170+
when(sqlAttributesGetter.getBatchSize(dbRequest)).thenReturn(2L);
172171
}
173-
when(multiQuerySqlClientAttributesGetter.getDbNamespace(dbRequest)).thenReturn("database");
174-
when(multiQuerySqlClientAttributesGetter.getBatchSize(dbRequest)).thenReturn(2L);
175172

176-
SpanNameExtractor<DbRequest> underTest =
177-
DbClientSpanNameExtractor.create(multiQuerySqlClientAttributesGetter);
173+
SpanNameExtractor<DbRequest> underTest = DbClientSpanNameExtractor.create(sqlAttributesGetter);
178174

179175
// when
180176
String spanName = underTest.extract(dbRequest);
181177

182178
// then
183179
assertEquals(
184-
SemconvStability.emitStableDatabaseSemconv() ? "BATCH INSERT database.table" : "database",
180+
SemconvStability.emitStableDatabaseSemconv()
181+
? "BATCH INSERT database.table"
182+
: "INSERT database.table",
185183
spanName);
186184
}
187185

0 commit comments

Comments
 (0)