-
Notifications
You must be signed in to change notification settings - Fork 1k
Closed
Labels
contribution welcomeRequest makes sense, maintainers probably won't have time, contribution would be welcomeRequest makes sense, maintainers probably won't have time, contribution would be welcomeenhancementNew feature or requestNew feature or request
Description
The current JDBC instrumentation hardcodes the Instrumenter creation logic, which I understand to be a bit of an anti-pattern compared to things like GrpcTelemetryBuilder. So my feature request is to introduce a similar builder that lets me customize naming/attributes for the JDBC spans that get emitted. Here is a rough first draft of what it might look like:
package io.opentelemetry.instrumentation.jdbc.datasource;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.code.CodeAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.code.CodeSpanNameExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientSpanNameExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.db.SqlClientAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesExtractor;
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
import io.opentelemetry.instrumentation.jdbc.internal.DataSourceCodeAttributesGetter;
import io.opentelemetry.instrumentation.jdbc.internal.DbRequest;
import io.opentelemetry.instrumentation.jdbc.internal.JdbcAttributesGetter;
import io.opentelemetry.instrumentation.jdbc.internal.JdbcNetAttributesGetter;
import javax.annotation.Nullable;
import javax.sql.DataSource;
import java.util.function.Function;
public class OpenTelemetryDataSourceBuilder {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jdbc";
private final DataSource delegate;
private final OpenTelemetry openTelemetry;
private @Nullable Function<SpanNameExtractor<DataSource>, ? extends SpanNameExtractor<? super DataSource>> dataSourceNameExtractorTransformer;
private @Nullable Function<SpanNameExtractor<DbRequest>, ? extends SpanNameExtractor<? super DbRequest>> requestNameExtractorTransformer;
OpenTelemetryDataSourceBuilder(DataSource delegate, OpenTelemetry openTelemetry) {
this.delegate = delegate;
this.openTelemetry = openTelemetry;
}
@CanIgnoreReturnValue
public OpenTelemetryDataSourceBuilder setDataSourceNameExtractor(Function<SpanNameExtractor<DataSource>, ? extends SpanNameExtractor<? super DataSource>> dataSourceNameExtractor) {
this.dataSourceNameExtractorTransformer = dataSourceNameExtractor;
return this;
}
@CanIgnoreReturnValue
public OpenTelemetryDataSourceBuilder setRequestNameExtractor(Function<SpanNameExtractor<DbRequest>, ? extends SpanNameExtractor<? super DbRequest>> requestNameExtractor) {
this.requestNameExtractorTransformer = requestNameExtractor;
return this;
}
public OpenTelemetryDataSource build() {
// ~~ datasource ~~
final DataSourceCodeAttributesGetter codeAttributesGetter = new DataSourceCodeAttributesGetter();
final SpanNameExtractor<? super DataSource> dataSourceNameExtractor = computeDataSourceNameExtractor(codeAttributesGetter);
final Instrumenter<DataSource, Void> dataSourceInstrumenter = Instrumenter.<DataSource, Void>builder(openTelemetry, INSTRUMENTATION_NAME, dataSourceNameExtractor)
.addAttributesExtractor(CodeAttributesExtractor.create(codeAttributesGetter))
.buildInstrumenter();
// ~~ statement ~~
final JdbcAttributesGetter dbAttributesGetter = new JdbcAttributesGetter();
final JdbcNetAttributesGetter netAttributesGetter = new JdbcNetAttributesGetter();
final SpanNameExtractor<? super DbRequest> requestNameExtractor = requestNameExtractor(dbAttributesGetter);
final Instrumenter<DbRequest, Void> statementInstrumenter = Instrumenter.<DbRequest, Void>builder(openTelemetry, INSTRUMENTATION_NAME, requestNameExtractor)
.addAttributesExtractor(
SqlClientAttributesExtractor.builder(dbAttributesGetter)
.setStatementSanitizationEnabled(
ConfigPropertiesUtil.getBoolean(
"otel.instrumentation.common.db-statement-sanitizer.enabled", true))
.build())
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
.buildInstrumenter(SpanKindExtractor.alwaysClient());
// ~~ return it ~~
return new OpenTelemetryDataSource(delegate, dataSourceInstrumenter, statementInstrumenter);
}
private SpanNameExtractor<? super DataSource> computeDataSourceNameExtractor(DataSourceCodeAttributesGetter codeAttributesGetter) {
final SpanNameExtractor<DataSource> original = CodeSpanNameExtractor.create(codeAttributesGetter);
if (dataSourceNameExtractorTransformer != null) {
return dataSourceNameExtractorTransformer.apply(original);
}
return original;
}
private SpanNameExtractor<? super DbRequest> requestNameExtractor(JdbcAttributesGetter dbAttributesGetter) {
final SpanNameExtractor<DbRequest> original = DbClientSpanNameExtractor.create(dbAttributesGetter);
if (requestNameExtractorTransformer != null) {
return requestNameExtractorTransformer.apply(original);
}
return original;
}
}public class OpenTelemetryDataSource implements DataSource, AutoCloseable {
public static OpenTelemetryDataSourceBuilder builder(DataSource delegate, OpenTelemetry openTelemetry) {
return new OpenTelemetryDataSourceBuilder(delegate, openTelemetry);
}
// continued...mateuszrzeszutek
Metadata
Metadata
Assignees
Labels
contribution welcomeRequest makes sense, maintainers probably won't have time, contribution would be welcomeRequest makes sense, maintainers probably won't have time, contribution would be welcomeenhancementNew feature or requestNew feature or request