Skip to content
Merged
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 @@ -8,7 +8,7 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.db.DbAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesExtractor;
import javax.annotation.Nullable;
Expand All @@ -21,7 +21,7 @@
* at each stage of a request's lifecycle. It is best to populate as much as possible in {@link
* #onStart(AttributesBuilder, Context, Object)} to have it available during sampling.
*
* @see DbAttributesExtractor
* @see DbClientAttributesExtractor
* @see HttpClientAttributesExtractor
* @see NetServerAttributesExtractor
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import io.opentelemetry.context.propagation.TextMapSetter;
import io.opentelemetry.instrumentation.api.annotations.UnstableApi;
import io.opentelemetry.instrumentation.api.config.Config;
import io.opentelemetry.instrumentation.api.instrumenter.db.DbAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.rpc.RpcAttributesExtractor;
Expand Down Expand Up @@ -169,8 +169,8 @@ public InstrumenterBuilder<REQUEST, RESPONSE> setDisabled(boolean disabled) {
* <ul>
* <li>CLIENT nested spans are suppressed depending on their type: {@linkplain
* HttpClientAttributesExtractor HTTP}, {@linkplain RpcAttributesExtractor RPC} or
* {@linkplain DbAttributesExtractor database} clients. If a span with the same type is
* present in the parent context object, new span of the same type will not be started.
* {@linkplain DbClientAttributesExtractor database} clients. If a span with the same type
* is present in the parent context object, new span of the same type will not be started.
* </ul>
*
* <p><strong>When disabled:</strong>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

package io.opentelemetry.instrumentation.api.instrumenter;

import io.opentelemetry.instrumentation.api.instrumenter.db.DbAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.rpc.RpcAttributesExtractor;
Expand All @@ -28,7 +28,7 @@ static Set<SpanKey> determineSpanKeys(
spanKeys.add(SpanKey.HTTP_CLIENT);
} else if (attributeExtractor instanceof RpcAttributesExtractor) {
spanKeys.add(SpanKey.RPC_CLIENT);
} else if (attributeExtractor instanceof DbAttributesExtractor) {
} else if (attributeExtractor instanceof DbClientAttributesExtractor) {
spanKeys.add(SpanKey.DB_CLIENT);
} else if (attributeExtractor instanceof MessagingAttributesExtractor) {
spanKeys.add(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.instrumenter.db;

import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;

/**
* Extractor of <a
* href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/database.md">database
* client attributes</a>.
*
* <p>This class delegates to a type-specific {@link DbClientAttributesGetter} for individual
* attribute extraction from request/response objects.
*/
public final class DbClientAttributesExtractor<REQUEST, RESPONSE>
extends DbClientCommonAttributesExtractor<
REQUEST, RESPONSE, DbClientAttributesGetter<REQUEST>> {

/** Creates the database client attributes extractor with default configuration. */
public static <REQUEST, RESPONSE> DbClientAttributesExtractor<REQUEST, RESPONSE> create(
DbClientAttributesGetter<REQUEST> getter) {
return new DbClientAttributesExtractor<>(getter);
}

DbClientAttributesExtractor(DbClientAttributesGetter<REQUEST> getter) {
super(getter);
}

@Override
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {
super.onStart(attributes, parentContext, request);

set(attributes, SemanticAttributes.DB_STATEMENT, getter.statement(request));
set(attributes, SemanticAttributes.DB_OPERATION, getter.operation(request));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.instrumenter.db;

import javax.annotation.Nullable;

/**
* An interface for getting database client attributes.
*
* <p>Instrumentation authors will create implementations of this interface for their specific
* library/framework. It will be used by the {@link DbClientAttributesExtractor} to obtain the
* various database client attributes in a type-generic way.
*
* <p>If an attribute is not available in this library, it is appropriate to return {@code null}
* from the attribute methods, but implement as many as possible for best compliance with the
* OpenTelemetry specification.
*/
public interface DbClientAttributesGetter<REQUEST> extends DbClientCommonAttributesGetter<REQUEST> {

@Nullable
String statement(REQUEST request);

@Nullable
String operation(REQUEST request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.instrumenter.db;

import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import javax.annotation.Nullable;

abstract class DbClientCommonAttributesExtractor<
REQUEST, RESPONSE, GETTER extends DbClientCommonAttributesGetter<REQUEST>>
implements AttributesExtractor<REQUEST, RESPONSE> {

final GETTER getter;

DbClientCommonAttributesExtractor(GETTER getter) {
this.getter = getter;
}

@Override
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {
set(attributes, SemanticAttributes.DB_SYSTEM, getter.system(request));
set(attributes, SemanticAttributes.DB_USER, getter.user(request));
set(attributes, SemanticAttributes.DB_NAME, getter.name(request));
set(attributes, SemanticAttributes.DB_CONNECTION_STRING, getter.connectionString(request));
}

@Override
public final void onEnd(
AttributesBuilder attributes,
Context context,
REQUEST request,
@Nullable RESPONSE response,
@Nullable Throwable error) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.instrumenter.db;

import javax.annotation.Nullable;

/** An interface for getting attributes common to database clients. */
public interface DbClientCommonAttributesGetter<REQUEST> {

@Nullable
String system(REQUEST request);

@Nullable
String user(REQUEST request);

@Nullable
String name(REQUEST request);

@Nullable
String connectionString(REQUEST request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.instrumenter.db;

import io.opentelemetry.instrumentation.api.db.SqlStatementInfo;
import io.opentelemetry.instrumentation.api.db.SqlStatementSanitizer;
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;

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

/**
* Returns a {@link SpanNameExtractor} that constructs the span name according to DB semantic
* conventions: {@code <db.operation> <db.name>}.
*
* @see DbClientAttributesGetter#operation(Object) used to extract {@code <db.operation>}.
* @see DbClientAttributesGetter#name(Object) used to extract {@code <db.name>}.
*/
public static <REQUEST> SpanNameExtractor<REQUEST> create(
DbClientAttributesGetter<REQUEST> getter) {
return new GenericDbClientSpanNameExtractor<>(getter);
}

/**
* Returns a {@link SpanNameExtractor} that constructs the span name according to DB semantic
* conventions: {@code <db.operation> <db.name>.<table>}.
*
* @see SqlStatementInfo#getOperation() used to extract {@code <db.operation>}.
* @see DbClientAttributesGetter#name(Object) used to extract {@code <db.name>}.
* @see SqlStatementInfo#getTable() used to extract {@code <db.table>}.
*/
public static <REQUEST> SpanNameExtractor<REQUEST> create(
SqlClientAttributesGetter<REQUEST> getter) {
return new SqlClientSpanNameExtractor<>(getter);
}

private static final String DEFAULT_SPAN_NAME = "DB Query";

private DbClientSpanNameExtractor() {}

protected String computeSpanName(String dbName, String operation, String table) {
if (operation == null) {
return dbName == null ? DEFAULT_SPAN_NAME : dbName;
}

StringBuilder name = new StringBuilder(operation);
if (dbName != null || table != null) {
name.append(' ');
}
// skip db name if table already has a db name prefixed to it
if (dbName != null && (table == null || table.indexOf('.') == -1)) {
name.append(dbName);
if (table != null) {
name.append('.');
}
}
if (table != null) {
name.append(table);
}
return name.toString();
}

private static final class GenericDbClientSpanNameExtractor<REQUEST>
extends DbClientSpanNameExtractor<REQUEST> {

private final DbClientAttributesGetter<REQUEST> getter;

private GenericDbClientSpanNameExtractor(DbClientAttributesGetter<REQUEST> getter) {
this.getter = getter;
}

@Override
public String extract(REQUEST request) {
String dbName = getter.name(request);
String operation = getter.operation(request);
return computeSpanName(dbName, operation, null);
}
}

private static final class SqlClientSpanNameExtractor<REQUEST>
extends DbClientSpanNameExtractor<REQUEST> {

private final SqlClientAttributesGetter<REQUEST> getter;

private SqlClientSpanNameExtractor(SqlClientAttributesGetter<REQUEST> getter) {
this.getter = getter;
}

@Override
public String extract(REQUEST request) {
String dbName = getter.name(request);
SqlStatementInfo sanitizedStatement =
SqlStatementSanitizer.sanitize(getter.rawStatement(request));
return computeSpanName(
dbName, sanitizedStatement.getOperation(), sanitizedStatement.getTable());
}
}
}
Loading