Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,18 @@ public String extract(REQUEST request) {
namespace, sanitizedStatement.getOperation(), sanitizedStatement.getMainIdentifier());
}

// For stable semconv, use query summary as span name if available
if (rawQueryTexts.size() == 1) {
SqlStatementInfo sanitizedStatement =
SqlStatementSanitizerUtil.sanitize(rawQueryTexts.iterator().next());
String querySummary = sanitizedStatement.getQuerySummary();
if (querySummary != null) {
if (isBatch(request)) {
return "BATCH " + querySummary;
}
return querySummary;
}
// Fall back to old behavior if no query summary
String operation = sanitizedStatement.getOperation();
if (isBatch(request)) {
operation = "BATCH " + operation;
Expand All @@ -122,6 +131,11 @@ public String extract(REQUEST request) {
}

MultiQuery multiQuery = MultiQuery.analyze(rawQueryTexts, false);
String querySummary = multiQuery.getQuerySummary();
if (querySummary != null) {
return "BATCH " + querySummary;
}
// Fall back to old behavior if no query summary
return computeSpanName(
namespace,
multiQuery.getOperation() != null ? "BATCH " + multiQuery.getOperation() : "BATCH",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,43 @@ class MultiQuery {

@Nullable private final String mainIdentifier;
@Nullable private final String operation;
@Nullable private final String querySummary;
private final Set<String> statements;

private MultiQuery(
@Nullable String mainIdentifier, @Nullable String operation, Set<String> statements) {
@Nullable String mainIdentifier,
@Nullable String operation,
@Nullable String querySummary,
Set<String> statements) {
this.mainIdentifier = mainIdentifier;
this.operation = operation;
this.querySummary = querySummary;
this.statements = statements;
}

static MultiQuery analyze(
Collection<String> rawQueryTexts, boolean statementSanitizationEnabled) {
UniqueValue uniqueMainIdentifier = new UniqueValue();
UniqueValue uniqueOperation = new UniqueValue();
UniqueValue uniqueQuerySummary = new UniqueValue();
Set<String> uniqueStatements = new LinkedHashSet<>();
for (String rawQueryText : rawQueryTexts) {
SqlStatementInfo sanitizedStatement = SqlStatementSanitizerUtil.sanitize(rawQueryText);
String mainIdentifier = sanitizedStatement.getMainIdentifier();
uniqueMainIdentifier.set(mainIdentifier);
String operation = sanitizedStatement.getOperation();
uniqueOperation.set(operation);
String querySummary = sanitizedStatement.getQuerySummary();
uniqueQuerySummary.set(querySummary);
uniqueStatements.add(
statementSanitizationEnabled ? sanitizedStatement.getFullStatement() : rawQueryText);
}

return new MultiQuery(
uniqueMainIdentifier.getValue(), uniqueOperation.getValue(), uniqueStatements);
uniqueMainIdentifier.getValue(),
uniqueOperation.getValue(),
uniqueQuerySummary.getValue(),
uniqueStatements);
}

@Nullable
Expand All @@ -52,6 +63,11 @@ public String getOperation() {
return operation;
}

@Nullable
public String getQuerySummary() {
return querySummary;
}

public Set<String> getStatements() {
return statements;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static io.opentelemetry.semconv.DbAttributes.DB_COLLECTION_NAME;
import static io.opentelemetry.semconv.DbAttributes.DB_OPERATION_BATCH_SIZE;
import static io.opentelemetry.semconv.DbAttributes.DB_OPERATION_NAME;
import static io.opentelemetry.semconv.DbAttributes.DB_QUERY_SUMMARY;
import static io.opentelemetry.semconv.DbAttributes.DB_QUERY_TEXT;

import io.opentelemetry.api.common.AttributeKey;
Expand Down Expand Up @@ -119,6 +120,7 @@ public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST
DB_QUERY_TEXT,
statementSanitizationEnabled ? sanitizedStatement.getFullStatement() : rawQueryText);
internalSet(attributes, DB_OPERATION_NAME, isBatch ? "BATCH " + operation : operation);
internalSet(attributes, DB_QUERY_SUMMARY, sanitizedStatement.getQuerySummary());
if (!SQL_CALL.equals(operation)) {
internalSet(attributes, DB_COLLECTION_NAME, sanitizedStatement.getMainIdentifier());
}
Expand All @@ -130,6 +132,7 @@ public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST
String operation =
multiQuery.getOperation() != null ? "BATCH " + multiQuery.getOperation() : "BATCH";
internalSet(attributes, DB_OPERATION_NAME, operation);
internalSet(attributes, DB_QUERY_SUMMARY, multiQuery.getQuerySummary());

if (multiQuery.getMainIdentifier() != null
&& (multiQuery.getOperation() == null || !SQL_CALL.equals(multiQuery.getOperation()))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,34 @@
@AutoValue
public abstract class SqlStatementInfo {

private static final int QUERY_SUMMARY_MAX_LENGTH = 255;

public static SqlStatementInfo create(
@Nullable String fullStatement, @Nullable String operation, @Nullable String identifier) {
return new AutoValue_SqlStatementInfo(fullStatement, operation, identifier);
@Nullable String fullStatement,
@Nullable String operation,
@Nullable String identifier,
@Nullable String querySummary) {
String truncatedQuerySummary = truncateQuerySummary(querySummary);
return new AutoValue_SqlStatementInfo(
fullStatement, operation, identifier, truncatedQuerySummary);
}

/**
* Truncates the query summary to {@link #QUERY_SUMMARY_MAX_LENGTH} characters, ensuring
* truncation does not occur within an operation name or target.
*/
@Nullable
private static String truncateQuerySummary(@Nullable String querySummary) {
if (querySummary == null || querySummary.length() <= QUERY_SUMMARY_MAX_LENGTH) {
return querySummary;
}
// Truncate at the last space before the limit to avoid cutting in the middle of an identifier
int lastSpace = querySummary.lastIndexOf(' ', QUERY_SUMMARY_MAX_LENGTH);
if (lastSpace > 0) {
return querySummary.substring(0, lastSpace);
}
// If no space found, truncate at the limit
return querySummary.substring(0, QUERY_SUMMARY_MAX_LENGTH);
}

@Nullable
Expand All @@ -24,4 +49,24 @@ public static SqlStatementInfo create(

@Nullable
public abstract String getMainIdentifier();

/**
* Returns a low cardinality summary of the database query suitable for use as a span name or
* metric attribute.
*
* <p>The summary contains operations (e.g., SELECT, INSERT) and their targets (e.g., table names)
* in the order they appear in the query. For example:
*
* <ul>
* <li>{@code SELECT wuser_table}
* <li>{@code INSERT shipping_details SELECT orders}
* <li>{@code SELECT songs artists} (multiple tables)
* </ul>
*
* @see <a
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/db/database-spans.md#generating-a-summary-of-the-query">Generating
* a summary of the query</a>
*/
@Nullable
public abstract String getQuerySummary();
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public SqlStatementInfo sanitize(@Nullable String statement) {

public SqlStatementInfo sanitize(@Nullable String statement, SqlDialect dialect) {
if (!statementSanitizationEnabled || statement == null) {
return SqlStatementInfo.create(statement, null, null);
return SqlStatementInfo.create(statement, null, null, null);
}
// sanitization result will not be cached for statements larger than the threshold to avoid
// cache growing too large
Expand Down
Loading
Loading