Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,10 @@ InstrumenterBuilder<BUILDERREQUEST, BUILDERRESPONSE> instrumenterBuilder(
return Instrumenter.builder(openTelemetry, instrumentationName, spanNameExtractor);
}

public String getInstrumentationName() {
return instrumentationName;
}

@CanIgnoreReturnValue
public DefaultHttpClientInstrumenterBuilder<REQUEST, RESPONSE> configure(CommonConfig config) {
set(config::getKnownHttpRequestMethods, this::setKnownMethods);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,15 @@ public DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE> setBuilderCustomi
}

public Instrumenter<REQUEST, RESPONSE> build() {
InstrumenterBuilder<REQUEST, RESPONSE> builder = instrumenterBuilder();

if (headerGetter != null) {
return builder.buildServerInstrumenter(headerGetter);
}
return builder.buildInstrumenter(SpanKindExtractor.alwaysServer());
}

public InstrumenterBuilder<REQUEST, RESPONSE> instrumenterBuilder() {
SpanNameExtractor<? super REQUEST> spanNameExtractor =
spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build());

Expand All @@ -190,11 +199,7 @@ public Instrumenter<REQUEST, RESPONSE> build() {
.addOperationMetrics(HttpServerExperimentalMetrics.get());
}
builderCustomizer.accept(builder);

if (headerGetter != null) {
return builder.buildServerInstrumenter(headerGetter);
}
return builder.buildInstrumenter(SpanKindExtractor.alwaysServer());
return builder;
}

@CanIgnoreReturnValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,50 +7,20 @@

import akka.http.scaladsl.model.HttpRequest;
import akka.http.scaladsl.model.HttpResponse;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor;
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute;
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor;
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor;
import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig;
import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpServerInstrumenters;
import io.opentelemetry.javaagent.instrumentation.akkahttp.AkkaHttpUtil;

public final class AkkaHttpServerSingletons {

private static final Instrumenter<HttpRequest, HttpResponse> INSTRUMENTER;

static {
AkkaHttpServerAttributesGetter httpAttributesGetter = new AkkaHttpServerAttributesGetter();
InstrumenterBuilder<HttpRequest, HttpResponse> builder =
Instrumenter.<HttpRequest, HttpResponse>builder(
GlobalOpenTelemetry.get(),
AkkaHttpUtil.instrumentationName(),
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpServerAttributesExtractor.builder(httpAttributesGetter)
.setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders())
.setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders())
.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods())
.build())
.addOperationMetrics(HttpServerMetrics.get())
.addContextCustomizer(
HttpServerRoute.builder(httpAttributesGetter)
.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods())
.build());
if (AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) {
builder
.addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter))
.addOperationMetrics(HttpServerExperimentalMetrics.get());
}
INSTRUMENTER = builder.buildServerInstrumenter(AkkaHttpServerHeaders.INSTANCE);
INSTRUMENTER =
JavaagentHttpServerInstrumenters.create(
AkkaHttpUtil.instrumentationName(),
new AkkaHttpServerAttributesGetter(),
AkkaHttpServerHeaders.INSTANCE);
Comment on lines -28 to +23
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow, nice

}

public static Instrumenter<HttpRequest, HttpResponse> instrumenter() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,8 @@

package io.opentelemetry.javaagent.instrumentation.grizzly;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor;
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute;
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor;
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor;
import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig;
import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpServerInstrumenters;
import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge;
import org.glassfish.grizzly.http.HttpRequestPacket;
import org.glassfish.grizzly.http.HttpResponsePacket;
Expand All @@ -25,43 +16,22 @@ public final class GrizzlySingletons {
private static final Instrumenter<HttpRequestPacket, HttpResponsePacket> INSTRUMENTER;

static {
GrizzlyHttpAttributesGetter httpAttributesGetter = new GrizzlyHttpAttributesGetter();

InstrumenterBuilder<HttpRequestPacket, HttpResponsePacket> builder =
Instrumenter.<HttpRequestPacket, HttpResponsePacket>builder(
GlobalOpenTelemetry.get(),
"io.opentelemetry.grizzly-2.3",
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpServerAttributesExtractor.builder(httpAttributesGetter)
.setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders())
.setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders())
.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods())
.build())
.addOperationMetrics(HttpServerMetrics.get());
if (AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) {
builder
.addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter))
.addOperationMetrics(HttpServerExperimentalMetrics.get());
}
INSTRUMENTER =
builder
.addContextCustomizer(
(context, request, attributes) ->
new AppServerBridge.Builder()
.captureServletAttributes()
.recordException()
.init(context))
.addContextCustomizer(
(context, httpRequestPacket, startAttributes) -> GrizzlyErrorHolder.init(context))
.addContextCustomizer(
HttpServerRoute.builder(httpAttributesGetter)
.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods())
.build())
.buildServerInstrumenter(HttpRequestHeadersGetter.INSTANCE);
JavaagentHttpServerInstrumenters.create(
"io.opentelemetry.grizzly-2.3",
new GrizzlyHttpAttributesGetter(),
HttpRequestHeadersGetter.INSTANCE,
builder ->
builder
.addContextCustomizer(
(context, request, attributes) ->
new AppServerBridge.Builder()
.captureServletAttributes()
.recordException()
.init(context))
.addContextCustomizer(
(context, httpRequestPacket, startAttributes) ->
GrizzlyErrorHolder.init(context)));
}

public static Instrumenter<HttpRequestPacket, HttpResponsePacket> instrumenter() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,8 @@

package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor;
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute;
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor;
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor;
import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig;
import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpServerInstrumenters;
import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
Expand All @@ -26,39 +17,18 @@ public final class Jetty12Singletons {
private static final Instrumenter<Request, Response> INSTRUMENTER;

static {
Jetty12HttpAttributesGetter httpAttributesGetter = new Jetty12HttpAttributesGetter();

InstrumenterBuilder<Request, Response> builder =
Instrumenter.<Request, Response>builder(
GlobalOpenTelemetry.get(),
INSTRUMENTATION_NAME,
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpServerAttributesExtractor.builder(httpAttributesGetter)
.setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders())
.setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders())
.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods())
.build())
.addContextCustomizer(
HttpServerRoute.builder(httpAttributesGetter)
.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods())
.build())
.addContextCustomizer(
(context, request, attributes) ->
new AppServerBridge.Builder()
.captureServletAttributes()
.recordException()
.init(context))
.addOperationMetrics(HttpServerMetrics.get());
if (AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) {
builder
.addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter))
.addOperationMetrics(HttpServerExperimentalMetrics.get());
}
INSTRUMENTER = builder.buildServerInstrumenter(Jetty12TextMapGetter.INSTANCE);
INSTRUMENTER =
JavaagentHttpServerInstrumenters.create(
INSTRUMENTATION_NAME,
new Jetty12HttpAttributesGetter(),
Jetty12TextMapGetter.INSTANCE,
builder ->
builder.addContextCustomizer(
(context, request, attributes) ->
new AppServerBridge.Builder()
.captureServletAttributes()
.recordException()
.init(context)));
}

private static final Jetty12Helper HELPER = new Jetty12Helper(INSTRUMENTER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,73 +14,73 @@ import io.ktor.util.pipeline.*
import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.context.Context
import io.opentelemetry.extension.kotlin.asContextElement
import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor
import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusBuilder
import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor
import io.opentelemetry.instrumentation.api.internal.InstrumenterUtil
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteSource
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor
import kotlinx.coroutines.withContext

class KtorServerTracing private constructor(
private val instrumenter: Instrumenter<ApplicationRequest, ApplicationResponse>,
) {

class Configuration {
internal lateinit var openTelemetry: OpenTelemetry

internal val additionalExtractors = mutableListOf<AttributesExtractor<in ApplicationRequest, in ApplicationResponse>>()

internal val httpAttributesExtractorBuilder = HttpServerAttributesExtractor.builder(KtorHttpServerAttributesGetter.INSTANCE)

internal val httpSpanNameExtractorBuilder = HttpSpanNameExtractor.builder(KtorHttpServerAttributesGetter.INSTANCE)

internal val httpServerRouteBuilder = HttpServerRoute.builder(KtorHttpServerAttributesGetter.INSTANCE)

internal var statusExtractor:
(SpanStatusExtractor<ApplicationRequest, ApplicationResponse>) -> SpanStatusExtractor<in ApplicationRequest, in ApplicationResponse> = { a -> a }
internal lateinit var builder: DefaultHttpServerInstrumenterBuilder<ApplicationRequest, ApplicationResponse>

internal var spanKindExtractor:
(SpanKindExtractor<ApplicationRequest>) -> SpanKindExtractor<ApplicationRequest> = { a -> a }

fun setOpenTelemetry(openTelemetry: OpenTelemetry) {
this.openTelemetry = openTelemetry
this.builder =
DefaultHttpServerInstrumenterBuilder(
INSTRUMENTATION_NAME,
openTelemetry,
KtorHttpServerAttributesGetter.INSTANCE,
null
)
}

fun setStatusExtractor(
extractor: (SpanStatusExtractor<ApplicationRequest, ApplicationResponse>) -> SpanStatusExtractor<in ApplicationRequest, in ApplicationResponse>
) {
this.statusExtractor = extractor
builder.setStatusExtractor { prevExtractor ->
SpanStatusExtractor { spanStatusBuilder: SpanStatusBuilder,
request: ApplicationRequest,
response: ApplicationResponse?,
throwable: Throwable? ->
@Suppress("UNCHECKED_CAST")
extractor(prevExtractor as SpanStatusExtractor<ApplicationRequest, ApplicationResponse>)
.extract(spanStatusBuilder, request, response, throwable)
}
}
}

fun setSpanKindExtractor(extractor: (SpanKindExtractor<ApplicationRequest>) -> SpanKindExtractor<ApplicationRequest>) {
this.spanKindExtractor = extractor
}

fun addAttributeExtractor(extractor: AttributesExtractor<in ApplicationRequest, in ApplicationResponse>) {
additionalExtractors.add(extractor)
builder.addAttributesExtractor(extractor)
}

fun setCapturedRequestHeaders(requestHeaders: List<String>) {
httpAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders)
builder.setCapturedRequestHeaders(requestHeaders)
}

fun setCapturedResponseHeaders(responseHeaders: List<String>) {
httpAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders)
builder.setCapturedResponseHeaders(responseHeaders)
}

fun setKnownMethods(knownMethods: Set<String>) {
httpAttributesExtractorBuilder.setKnownMethods(knownMethods)
httpSpanNameExtractorBuilder.setKnownMethods(knownMethods)
httpServerRouteBuilder.setKnownMethods(knownMethods)
builder.setKnownMethods(knownMethods)
}

internal fun isOpenTelemetryInitialized(): Boolean = this::openTelemetry.isInitialized
internal fun isOpenTelemetryInitialized(): Boolean = this::builder.isInitialized
}

private fun start(call: ApplicationCall): Context? {
Expand All @@ -97,7 +97,7 @@ class KtorServerTracing private constructor(
}

companion object Feature : ApplicationFeature<Application, Configuration, KtorServerTracing> {
private val INSTRUMENTATION_NAME = "io.opentelemetry.ktor-1.0"
private const val INSTRUMENTATION_NAME = "io.opentelemetry.ktor-1.0"

private val contextKey = AttributeKey<Context>("OpenTelemetry")
private val errorKey = AttributeKey<Throwable>("OpenTelemetryException")
Expand All @@ -111,25 +111,8 @@ class KtorServerTracing private constructor(
throw IllegalArgumentException("OpenTelemetry must be set")
}

val httpAttributesGetter = KtorHttpServerAttributesGetter.INSTANCE

val instrumenterBuilder = Instrumenter.builder<ApplicationRequest, ApplicationResponse>(
configuration.openTelemetry,
INSTRUMENTATION_NAME,
configuration.httpSpanNameExtractorBuilder.build()
)

configuration.additionalExtractors.forEach { instrumenterBuilder.addAttributesExtractor(it) }

with(instrumenterBuilder) {
setSpanStatusExtractor(configuration.statusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)))
addAttributesExtractor(configuration.httpAttributesExtractorBuilder.build())
addOperationMetrics(HttpServerMetrics.get())
addContextCustomizer(configuration.httpServerRouteBuilder.build())
}

val instrumenter = InstrumenterUtil.buildUpstreamInstrumenter(
instrumenterBuilder,
configuration.builder.instrumenterBuilder(),
ApplicationRequestGetter,
configuration.spanKindExtractor(SpanKindExtractor.alwaysServer())
)
Expand Down
Loading
Loading