diff --git a/instrumentation/ktor/ktor-1.0/library/README.md b/instrumentation/ktor/ktor-1.0/library/README.md index 2701fd8c5125..6ec0bedff8f0 100644 --- a/instrumentation/ktor/ktor-1.0/library/README.md +++ b/instrumentation/ktor/ktor-1.0/library/README.md @@ -1,6 +1,7 @@ # Library Instrumentation for Ktor version 1.x -This package contains libraries to help instrument Ktor. Currently, only server instrumentation is supported. +This package contains libraries to help instrument Ktor. +Currently, only server instrumentation is supported. ## Quickstart @@ -29,14 +30,14 @@ implementation("io.opentelemetry.instrumentation:opentelemetry-ktor-1.0:OPENTELE ## Usage -Initialize instrumentation by installing the `KtorServerTracing` feature. You must set the `OpenTelemetry` to use with -the feature. +Initialize instrumentation by installing the `KtorServerTelemetry` feature. +You must set the `OpenTelemetry` to use with the feature. ```kotlin OpenTelemetry openTelemetry = ... embeddedServer(Netty, 8080) { - install(KtorServerTracing) { + install(KtorServerTelemetry) { setOpenTelemetry(openTelemetry) } } diff --git a/instrumentation/ktor/ktor-1.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorServerTelemetry.kt b/instrumentation/ktor/ktor-1.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorServerTelemetry.kt new file mode 100644 index 000000000000..d4635e557962 --- /dev/null +++ b/instrumentation/ktor/ktor-1.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorServerTelemetry.kt @@ -0,0 +1,169 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v1_0 + +import io.ktor.application.* +import io.ktor.request.* +import io.ktor.response.* +import io.ktor.routing.* +import io.ktor.util.* +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.HttpServerRoute +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteSource +import kotlinx.coroutines.withContext + +class KtorServerTelemetry private constructor( + private val instrumenter: Instrumenter, +) { + + class Configuration { + internal lateinit var builder: DefaultHttpServerInstrumenterBuilder + + internal var spanKindExtractor: + (SpanKindExtractor) -> SpanKindExtractor = { a -> a } + + fun setOpenTelemetry(openTelemetry: OpenTelemetry) { + this.builder = + DefaultHttpServerInstrumenterBuilder.create( + INSTRUMENTATION_NAME, + openTelemetry, + KtorHttpServerAttributesGetter.INSTANCE + ) + } + + fun setStatusExtractor( + extractor: (SpanStatusExtractor) -> SpanStatusExtractor + ) { + builder.setStatusExtractor { prevExtractor -> + SpanStatusExtractor { spanStatusBuilder: SpanStatusBuilder, + request: ApplicationRequest, + response: ApplicationResponse?, + throwable: Throwable? -> + extractor(prevExtractor).extract(spanStatusBuilder, request, response, throwable) + } + } + } + + fun setSpanKindExtractor(extractor: (SpanKindExtractor) -> SpanKindExtractor) { + this.spanKindExtractor = extractor + } + + fun addAttributesExtractor(extractor: AttributesExtractor) { + builder.addAttributesExtractor(extractor) + } + + fun setCapturedRequestHeaders(requestHeaders: List) { + builder.setCapturedRequestHeaders(requestHeaders) + } + + fun setCapturedResponseHeaders(responseHeaders: List) { + builder.setCapturedResponseHeaders(responseHeaders) + } + + fun setKnownMethods(knownMethods: Set) { + builder.setKnownMethods(knownMethods) + } + + internal fun isOpenTelemetryInitialized(): Boolean = this::builder.isInitialized + } + + private fun start(call: ApplicationCall): Context? { + val parentContext = Context.current() + if (!instrumenter.shouldStart(parentContext, call.request)) { + return null + } + + return instrumenter.start(parentContext, call.request) + } + + private fun end(context: Context, call: ApplicationCall, error: Throwable?) { + instrumenter.end(context, call.request, call.response, error) + } + + companion object Feature : ApplicationFeature { + private const val INSTRUMENTATION_NAME = "io.opentelemetry.ktor-1.0" + + private val contextKey = AttributeKey("OpenTelemetry") + private val errorKey = AttributeKey("OpenTelemetryException") + + override val key: AttributeKey = AttributeKey("OpenTelemetry") + + override fun install(pipeline: Application, configure: Configuration.() -> Unit): KtorServerTelemetry { + val configuration = Configuration().apply(configure) + + if (!configuration.isOpenTelemetryInitialized()) { + throw IllegalArgumentException("OpenTelemetry must be set") + } + + val instrumenter = InstrumenterUtil.buildUpstreamInstrumenter( + configuration.builder.instrumenterBuilder(), + ApplicationRequestGetter, + configuration.spanKindExtractor(SpanKindExtractor.alwaysServer()) + ) + + val feature = KtorServerTelemetry(instrumenter) + + val startPhase = PipelinePhase("OpenTelemetry") + pipeline.insertPhaseBefore(ApplicationCallPipeline.Monitoring, startPhase) + pipeline.intercept(startPhase) { + val context = feature.start(call) + + if (context != null) { + call.attributes.put(contextKey, context) + withContext(context.asContextElement()) { + try { + proceed() + } catch (err: Throwable) { + // Stash error for reporting later since need ktor to finish setting up the response + call.attributes.put(errorKey, err) + throw err + } + } + } else { + proceed() + } + } + + val postSendPhase = PipelinePhase("OpenTelemetryPostSend") + pipeline.sendPipeline.insertPhaseAfter(ApplicationSendPipeline.After, postSendPhase) + pipeline.sendPipeline.intercept(postSendPhase) { + val context = call.attributes.getOrNull(contextKey) + if (context != null) { + var error: Throwable? = call.attributes.getOrNull(errorKey) + try { + proceed() + } catch (t: Throwable) { + error = t + throw t + } finally { + feature.end(context, call, error) + } + } else { + proceed() + } + } + + pipeline.environment.monitor.subscribe(Routing.RoutingCallStarted) { call -> + val context = call.attributes.getOrNull(contextKey) + if (context != null) { + HttpServerRoute.update(context, HttpServerRouteSource.SERVER, { _, arg -> arg.route.parent.toString() }, call) + } + } + + return feature + } + } +} diff --git a/instrumentation/ktor/ktor-1.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorServerTracing.kt b/instrumentation/ktor/ktor-1.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorServerTracing.kt index 844cbe2895fd..1073053d0639 100644 --- a/instrumentation/ktor/ktor-1.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorServerTracing.kt +++ b/instrumentation/ktor/ktor-1.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorServerTracing.kt @@ -25,6 +25,7 @@ import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteSource import kotlinx.coroutines.withContext +@Deprecated("Use KtorServerTelemetry instead", ReplaceWith("KtorServerTelemetry")) class KtorServerTracing private constructor( private val instrumenter: Instrumenter, ) { diff --git a/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorHttpServerOldTest.kt b/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorHttpServerOldTest.kt new file mode 100644 index 000000000000..3dc5c701a0fc --- /dev/null +++ b/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorHttpServerOldTest.kt @@ -0,0 +1,143 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v1_0 + +import io.ktor.application.* +import io.ktor.http.* +import io.ktor.request.* +import io.ktor.response.* +import io.ktor.routing.* +import io.ktor.server.engine.* +import io.ktor.server.netty.* +import io.opentelemetry.api.trace.Span +import io.opentelemetry.api.trace.SpanKind +import io.opentelemetry.api.trace.StatusCode +import io.opentelemetry.context.Context +import io.opentelemetry.extension.kotlin.asContextElement +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions +import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint +import io.opentelemetry.semconv.ServerAttributes +import kotlinx.coroutines.withContext +import org.junit.jupiter.api.extension.RegisterExtension +import java.util.concurrent.ExecutionException +import java.util.concurrent.TimeUnit + +class KtorHttpServerOldTest : AbstractHttpServerTest() { + + companion object { + @JvmStatic + @RegisterExtension + val testing = HttpServerInstrumentationExtension.forLibrary() + } + + override fun setupServer(): ApplicationEngine { + return embeddedServer(Netty, port = port) { + KtorOldTestUtil.installOpenTelemetry(this, testing.openTelemetry) + + routing { + get(ServerEndpoint.SUCCESS.path) { + controller(ServerEndpoint.SUCCESS) { + call.respondText(ServerEndpoint.SUCCESS.body, status = HttpStatusCode.fromValue(ServerEndpoint.SUCCESS.status)) + } + } + + get(ServerEndpoint.REDIRECT.path) { + controller(ServerEndpoint.REDIRECT) { + call.respondRedirect(ServerEndpoint.REDIRECT.body) + } + } + + get(ServerEndpoint.ERROR.path) { + controller(ServerEndpoint.ERROR) { + call.respondText(ServerEndpoint.ERROR.body, status = HttpStatusCode.fromValue(ServerEndpoint.ERROR.status)) + } + } + + get(ServerEndpoint.EXCEPTION.path) { + controller(ServerEndpoint.EXCEPTION) { + throw IllegalStateException(ServerEndpoint.EXCEPTION.body) + } + } + + get("/query") { + controller(ServerEndpoint.QUERY_PARAM) { + call.respondText("some=${call.request.queryParameters["some"]}", status = HttpStatusCode.fromValue(ServerEndpoint.QUERY_PARAM.status)) + } + } + + get("/path/{id}/param") { + controller(ServerEndpoint.PATH_PARAM) { + call.respondText( + call.parameters["id"] + ?: "", + status = HttpStatusCode.fromValue(ServerEndpoint.PATH_PARAM.status), + ) + } + } + + get("/child") { + controller(ServerEndpoint.INDEXED_CHILD) { + ServerEndpoint.INDEXED_CHILD.collectSpanAttributes { call.request.queryParameters[it] } + call.respondText(ServerEndpoint.INDEXED_CHILD.body, status = HttpStatusCode.fromValue(ServerEndpoint.INDEXED_CHILD.status)) + } + } + + get("/captureHeaders") { + controller(ServerEndpoint.CAPTURE_HEADERS) { + call.response.header("X-Test-Response", call.request.header("X-Test-Request") ?: "") + call.respondText(ServerEndpoint.CAPTURE_HEADERS.body, status = HttpStatusCode.fromValue(ServerEndpoint.CAPTURE_HEADERS.status)) + } + } + } + }.start() + } + + override fun stopServer(server: ApplicationEngine) { + server.stop(0, 10, TimeUnit.SECONDS) + } + + // Copy in HttpServerTest.controller but make it a suspending function + private suspend fun controller(endpoint: ServerEndpoint, wrapped: suspend () -> Unit) { + assert(Span.current().spanContext.isValid, { "Controller should have a parent span. " }) + if (endpoint == ServerEndpoint.NOT_FOUND) { + wrapped() + } + val span = testing.openTelemetry.getTracer("test").spanBuilder("controller").setSpanKind(SpanKind.INTERNAL).startSpan() + try { + withContext(Context.current().with(span).asContextElement()) { + wrapped() + } + span.end() + } catch (e: Exception) { + span.setStatus(StatusCode.ERROR) + span.recordException(if (e is ExecutionException) e.cause ?: e else e) + span.end() + throw e + } + } + + override fun configure(options: HttpServerTestOptions) { + options.setTestPathParam(true) + + options.setHttpAttributes { + HttpServerTestOptions.DEFAULT_HTTP_ATTRIBUTES - ServerAttributes.SERVER_PORT + } + + options.setExpectedHttpRoute { endpoint, method -> + when (endpoint) { + ServerEndpoint.PATH_PARAM -> "/path/{id}/param" + else -> expectedHttpRoute(endpoint, method) + } + } + // ktor does not have a controller lifecycle so the server span ends immediately when the + // response is sent, which is before the controller span finishes. + options.setVerifyServerSpanEndTime(false) + + options.setResponseCodeOnNonStandardHttpMethod(404) + } +} diff --git a/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorOldTestUtil.kt b/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorOldTestUtil.kt new file mode 100644 index 000000000000..e9ff18ea1565 --- /dev/null +++ b/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorOldTestUtil.kt @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v1_0 + +import io.ktor.application.* +import io.opentelemetry.api.OpenTelemetry +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest + +class KtorOldTestUtil { + companion object { + fun installOpenTelemetry(application: Application, openTelemetry: OpenTelemetry) { + application.install(KtorServerTracing) { + setOpenTelemetry(openTelemetry) + setCapturedRequestHeaders(listOf(AbstractHttpServerTest.TEST_REQUEST_HEADER)) + setCapturedResponseHeaders(listOf(AbstractHttpServerTest.TEST_RESPONSE_HEADER)) + } + } + } +} diff --git a/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorServerSpanKindExtractorTest.kt b/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorServerSpanKindExtractorTest.kt index 364c67a9e1a5..a494ed33aced 100644 --- a/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorServerSpanKindExtractorTest.kt +++ b/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorServerSpanKindExtractorTest.kt @@ -58,7 +58,7 @@ class KtorServerSpanKindExtractorTest : AbstractHttpServerUsingTest diff --git a/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorTestUtil.kt b/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorTestUtil.kt index 6daf7382ec40..85fd9d6b78fa 100644 --- a/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorTestUtil.kt +++ b/instrumentation/ktor/ktor-1.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/KtorTestUtil.kt @@ -12,7 +12,7 @@ import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTes class KtorTestUtil { companion object { fun installOpenTelemetry(application: Application, openTelemetry: OpenTelemetry) { - application.install(KtorServerTracing) { + application.install(KtorServerTelemetry) { setOpenTelemetry(openTelemetry) setCapturedRequestHeaders(listOf(AbstractHttpServerTest.TEST_REQUEST_HEADER)) setCapturedResponseHeaders(listOf(AbstractHttpServerTest.TEST_RESPONSE_HEADER)) diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/AbstractKtorClientTelemetry.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/AbstractKtorClientTelemetry.kt new file mode 100644 index 000000000000..80729ec9c343 --- /dev/null +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/AbstractKtorClientTelemetry.kt @@ -0,0 +1,42 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0.common + +import io.ktor.client.call.* +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.opentelemetry.context.Context +import io.opentelemetry.context.propagation.ContextPropagators +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter + +abstract class AbstractKtorClientTelemetry( + private val instrumenter: Instrumenter, + private val propagators: ContextPropagators, +) { + + internal fun createSpan(requestBuilder: HttpRequestBuilder): Context? { + val parentContext = Context.current() + val requestData = requestBuilder.build() + + return if (instrumenter.shouldStart(parentContext, requestData)) { + instrumenter.start(parentContext, requestData) + } else { + null + } + } + + internal fun populateRequestHeaders(requestBuilder: HttpRequestBuilder, context: Context) { + propagators.textMapPropagator.inject(context, requestBuilder, KtorHttpHeadersSetter) + } + + internal fun endSpan(context: Context, call: HttpClientCall, error: Throwable?) { + endSpan(context, HttpRequestBuilder().takeFrom(call.request), call.response, error) + } + + internal fun endSpan(context: Context, requestBuilder: HttpRequestBuilder, response: HttpResponse?, error: Throwable?) { + instrumenter.end(context, requestBuilder.build(), response, error) + } +} diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/AbstractKtorClientTelemetryBuilder.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/AbstractKtorClientTelemetryBuilder.kt new file mode 100644 index 000000000000..f07d5c6764ed --- /dev/null +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/AbstractKtorClientTelemetryBuilder.kt @@ -0,0 +1,121 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0.common + +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.http.* +import io.opentelemetry.api.OpenTelemetry +import io.opentelemetry.api.common.AttributesBuilder +import io.opentelemetry.context.Context +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorBuilderUtil +import java.util.function.Function + +abstract class AbstractKtorClientTelemetryBuilder( + private val instrumentationName: String +) { + companion object { + init { + KtorBuilderUtil.clientBuilderExtractor = { it.builder } + } + } + + internal lateinit var openTelemetry: OpenTelemetry + protected lateinit var builder: DefaultHttpClientInstrumenterBuilder + + internal fun builder(): DefaultHttpClientInstrumenterBuilder { + return builder + } + + fun setOpenTelemetry(openTelemetry: OpenTelemetry) { + this.openTelemetry = openTelemetry + this.builder = DefaultHttpClientInstrumenterBuilder.create( + instrumentationName, + openTelemetry, + KtorHttpClientAttributesGetter + ) + } + + protected fun getOpenTelemetry(): OpenTelemetry { + return openTelemetry + } + + fun capturedRequestHeaders(vararg headers: String) = capturedRequestHeaders(headers.asIterable()) + + fun capturedRequestHeaders(headers: Iterable) { + builder.setCapturedRequestHeaders(headers.toList()) + } + + fun capturedResponseHeaders(vararg headers: String) = capturedResponseHeaders(headers.asIterable()) + + fun capturedResponseHeaders(headers: Iterable) { + builder.setCapturedResponseHeaders(headers.toList()) + } + + fun knownMethods(vararg methods: String) = knownMethods(methods.asIterable()) + + fun knownMethods(vararg methods: HttpMethod) = knownMethods(methods.asIterable()) + + @JvmName("knownMethodsJvm") + fun knownMethods(methods: Iterable) = knownMethods(methods.map { it.value }) + + fun knownMethods(methods: Iterable) { + builder.setKnownMethods(methods.toSet()) + } + + fun attributesExtractor(extractorBuilder: ExtractorBuilder.() -> Unit = {}) { + val builder = ExtractorBuilder().apply(extractorBuilder).build() + this.builder.addAttributesExtractor(object : AttributesExtractor { + override fun onStart(attributes: AttributesBuilder, parentContext: Context, request: HttpRequestData) { + builder.onStart(OnStartData(attributes, parentContext, request)) + } + + override fun onEnd(attributes: AttributesBuilder, context: Context, request: HttpRequestData, response: HttpResponse?, error: Throwable?) { + builder.onEnd(OnEndData(attributes, context, request, response, error)) + } + }) + } + + fun spanNameExtractor(spanNameExtractorTransformer: Function, out SpanNameExtractor>) { + builder.setSpanNameExtractor(spanNameExtractorTransformer) + } + + class ExtractorBuilder { + private var onStart: OnStartData.() -> Unit = {} + private var onEnd: OnEndData.() -> Unit = {} + + fun onStart(block: OnStartData.() -> Unit) { + onStart = block + } + + fun onEnd(block: OnEndData.() -> Unit) { + onEnd = block + } + + internal fun build(): Extractor { + return Extractor(onStart, onEnd) + } + } + + internal class Extractor(val onStart: OnStartData.() -> Unit, val onEnd: OnEndData.() -> Unit) + + data class OnStartData( + val attributes: AttributesBuilder, + val parentContext: Context, + val request: HttpRequestData + ) + + data class OnEndData( + val attributes: AttributesBuilder, + val parentContext: Context, + val request: HttpRequestData, + val response: HttpResponse?, + val error: Throwable? + ) +} diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/AbstractKtorServerTelemetryBuilder.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/AbstractKtorServerTelemetryBuilder.kt new file mode 100644 index 000000000000..2e042bea3fb6 --- /dev/null +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/AbstractKtorServerTelemetryBuilder.kt @@ -0,0 +1,155 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0.common + +import io.ktor.http.* +import io.ktor.server.request.* +import io.ktor.server.response.* +import io.opentelemetry.api.OpenTelemetry +import io.opentelemetry.api.common.AttributesBuilder +import io.opentelemetry.api.trace.SpanKind +import io.opentelemetry.context.Context +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor +import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor +import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusBuilder +import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorBuilderUtil +import java.util.function.Function + +abstract class AbstractKtorServerTelemetryBuilder(private val instrumentationName: String) { + companion object { + init { + KtorBuilderUtil.serverBuilderExtractor = { it.builder } + } + } + + internal lateinit var builder: DefaultHttpServerInstrumenterBuilder + + internal var spanKindExtractor: + (SpanKindExtractor) -> SpanKindExtractor = { a -> a } + + fun setOpenTelemetry(openTelemetry: OpenTelemetry) { + this.builder = + DefaultHttpServerInstrumenterBuilder.create( + instrumentationName, + openTelemetry, + KtorHttpServerAttributesGetter.INSTANCE + ) + } + + fun spanStatusExtractor(extract: SpanStatusData.(SpanStatusExtractor) -> Unit) { + builder.setStatusExtractor { prevExtractor -> + SpanStatusExtractor { spanStatusBuilder: SpanStatusBuilder, + request: ApplicationRequest, + response: ApplicationResponse?, + throwable: Throwable? -> + extract( + SpanStatusData(spanStatusBuilder, request, response, throwable), + prevExtractor + ) + } + } + } + + data class SpanStatusData( + val spanStatusBuilder: SpanStatusBuilder, + val request: ApplicationRequest, + val response: ApplicationResponse?, + val error: Throwable? + ) + + fun spanKindExtractor(extract: ApplicationRequest.(SpanKindExtractor) -> SpanKind) { + spanKindExtractor = { prevExtractor -> + SpanKindExtractor { request: ApplicationRequest -> + extract(request, prevExtractor) + } + } + } + + fun attributesExtractor(extractorBuilder: ExtractorBuilder.() -> Unit = {}) { + val builder = ExtractorBuilder().apply(extractorBuilder).build() + this.builder.addAttributesExtractor( + object : AttributesExtractor { + override fun onStart(attributes: AttributesBuilder, parentContext: Context, request: ApplicationRequest) { + builder.onStart(OnStartData(attributes, parentContext, request)) + } + + override fun onEnd(attributes: AttributesBuilder, context: Context, request: ApplicationRequest, response: ApplicationResponse?, error: Throwable?) { + builder.onEnd(OnEndData(attributes, context, request, response, error)) + } + } + ) + } + + fun spanNameExtractor(spanNameExtractorTransformer: Function, out SpanNameExtractor>) { + builder.setSpanNameExtractor(spanNameExtractorTransformer) + } + + class ExtractorBuilder { + private var onStart: OnStartData.() -> Unit = {} + private var onEnd: OnEndData.() -> Unit = {} + + fun onStart(block: OnStartData.() -> Unit) { + onStart = block + } + + fun onEnd(block: OnEndData.() -> Unit) { + onEnd = block + } + + internal fun build(): Extractor { + return Extractor(onStart, onEnd) + } + } + + internal class Extractor(val onStart: OnStartData.() -> Unit, val onEnd: OnEndData.() -> Unit) + + data class OnStartData( + val attributes: AttributesBuilder, + val parentContext: Context, + val request: ApplicationRequest + ) + + data class OnEndData( + val attributes: AttributesBuilder, + val parentContext: Context, + val request: ApplicationRequest, + val response: ApplicationResponse?, + val error: Throwable? + ) + + fun capturedRequestHeaders(vararg headers: String) = capturedRequestHeaders(headers.asIterable()) + + fun capturedRequestHeaders(headers: Iterable) { + builder.setCapturedRequestHeaders(headers.toList()) + } + + fun capturedResponseHeaders(vararg headers: String) = capturedResponseHeaders(headers.asIterable()) + + fun capturedResponseHeaders(headers: Iterable) { + builder.setCapturedResponseHeaders(headers.toList()) + } + + fun knownMethods(vararg methods: String) = knownMethods(methods.asIterable()) + + fun knownMethods(vararg methods: HttpMethod) = knownMethods(methods.asIterable()) + + @JvmName("knownMethodsJvm") + fun knownMethods(methods: Iterable) = knownMethods(methods.map { it.value }) + + fun knownMethods(methods: Iterable) { + methods.toSet().apply { + builder.setKnownMethods(this) + } + } + + /** + * {@link #setOpenTelemetry(OpenTelemetry)} sets the serverBuilder to a non-null value. + */ + fun isOpenTelemetryInitialized(): Boolean = this::builder.isInitialized +} diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/server/ApplicationRequestGetter.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/ApplicationRequestGetter.kt similarity index 89% rename from instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/server/ApplicationRequestGetter.kt rename to instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/ApplicationRequestGetter.kt index 053436977ef2..acd04567f1e3 100644 --- a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/server/ApplicationRequestGetter.kt +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/ApplicationRequestGetter.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.server +package io.opentelemetry.instrumentation.ktor.v2_0.common import io.ktor.server.request.* import io.opentelemetry.context.propagation.TextMapGetter diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/client/KtorHttpClientAttributesGetter.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/KtorHttpClientAttributesGetter.kt similarity index 96% rename from instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/client/KtorHttpClientAttributesGetter.kt rename to instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/KtorHttpClientAttributesGetter.kt index db1a9d1a0f0b..64df11c673e6 100644 --- a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/client/KtorHttpClientAttributesGetter.kt +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/KtorHttpClientAttributesGetter.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.client +package io.opentelemetry.instrumentation.ktor.v2_0.common import io.ktor.client.request.* import io.ktor.client.statement.* diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/client/KtorHttpHeadersSetter.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/KtorHttpHeadersSetter.kt similarity index 77% rename from instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/client/KtorHttpHeadersSetter.kt rename to instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/KtorHttpHeadersSetter.kt index d6be22087a26..dee42dc4fab4 100644 --- a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/client/KtorHttpHeadersSetter.kt +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/KtorHttpHeadersSetter.kt @@ -3,9 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.client +package io.opentelemetry.instrumentation.ktor.v2_0.common -import io.ktor.client.request.HttpRequestBuilder +import io.ktor.client.request.* import io.opentelemetry.context.propagation.TextMapSetter internal object KtorHttpHeadersSetter : TextMapSetter { diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/server/KtorHttpServerAttributesGetter.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/KtorHttpServerAttributesGetter.kt similarity index 97% rename from instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/server/KtorHttpServerAttributesGetter.kt rename to instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/KtorHttpServerAttributesGetter.kt index 9471aa44f64b..8c4ab938f53e 100644 --- a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/server/KtorHttpServerAttributesGetter.kt +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/KtorHttpServerAttributesGetter.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.server +package io.opentelemetry.instrumentation.ktor.v2_0.common import io.ktor.server.plugins.* import io.ktor.server.request.* diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/client/AbstractKtorClientTracing.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/client/AbstractKtorClientTracing.kt similarity index 85% rename from instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/client/AbstractKtorClientTracing.kt rename to instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/client/AbstractKtorClientTracing.kt index 925cb6cf3156..dc9cafba5b5f 100644 --- a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/client/AbstractKtorClientTracing.kt +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/client/AbstractKtorClientTracing.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.client +package io.opentelemetry.instrumentation.ktor.v2_0.common.client import io.ktor.client.call.* import io.ktor.client.request.* @@ -11,7 +11,9 @@ import io.ktor.client.statement.* import io.opentelemetry.context.Context import io.opentelemetry.context.propagation.ContextPropagators import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter +import io.opentelemetry.instrumentation.ktor.v2_0.common.KtorHttpHeadersSetter +@Deprecated("Use AbstractKtorClientTelemetry instead", ReplaceWith("AbstractKtorClientTelemetry")) abstract class AbstractKtorClientTracing( private val instrumenter: Instrumenter, private val propagators: ContextPropagators, diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/client/AbstractKtorClientTracingBuilder.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/client/AbstractKtorClientTracingBuilder.kt similarity index 91% rename from instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/client/AbstractKtorClientTracingBuilder.kt rename to instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/client/AbstractKtorClientTracingBuilder.kt index 2b412ca5c3e9..12bff4795102 100644 --- a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/client/AbstractKtorClientTracingBuilder.kt +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/client/AbstractKtorClientTracingBuilder.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.client +package io.opentelemetry.instrumentation.ktor.v2_0.common.client import io.ktor.client.request.* import io.ktor.client.statement.* @@ -14,15 +14,17 @@ import io.opentelemetry.context.Context import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor -import io.opentelemetry.instrumentation.ktor.internal.KtorBuilderUtil +import io.opentelemetry.instrumentation.ktor.v2_0.common.KtorHttpClientAttributesGetter +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorBuilderUtilOld import java.util.function.Function +@Deprecated("Use AbstractKtorClientTelemetryBuilder instead", ReplaceWith("AbstractKtorClientTelemetryBuilder")) abstract class AbstractKtorClientTracingBuilder( private val instrumentationName: String ) { companion object { init { - KtorBuilderUtil.clientBuilderExtractor = { it.clientBuilder } + KtorBuilderUtilOld.clientBuilderExtractor = { it.clientBuilder } } } @@ -161,13 +163,14 @@ abstract class AbstractKtorClientTracingBuilder( * * @param emitExperimentalHttpClientMetrics `true` if the experimental HTTP client metrics are to be emitted. */ - @Deprecated("Please use method `emitExperimentalHttpClientMetrics`") + @Deprecated("Please use method `Experimental.emitExperimentalTelemetry`") fun setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientMetrics: Boolean) { if (emitExperimentalHttpClientMetrics) { emitExperimentalHttpClientMetrics() } } + @Deprecated("Please use method `Experimental.emitExperimentalTelemetry`") fun emitExperimentalHttpClientMetrics() { clientBuilder.setEmitExperimentalHttpClientMetrics(true) } diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/Experimental.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/Experimental.kt new file mode 100644 index 000000000000..9fc388d14254 --- /dev/null +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/Experimental.kt @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0.common.internal + +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorClientTelemetryBuilder +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorServerTelemetryBuilder + +class Experimental private constructor() { + + companion object { + fun emitExperimentalTelemetry(builder: AbstractKtorClientTelemetryBuilder) { + builder.builder().setEmitExperimentalHttpClientMetrics(true) + } + + fun emitExperimentalTelemetry(builder: AbstractKtorServerTelemetryBuilder) { + builder.builder.setEmitExperimentalHttpServerMetrics(true) + } + } +} diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorBuilderUtil.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorBuilderUtil.kt new file mode 100644 index 000000000000..c83d8aa6bdba --- /dev/null +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorBuilderUtil.kt @@ -0,0 +1,26 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0.common.internal + +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.server.request.* +import io.ktor.server.response.* +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorClientTelemetryBuilder +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorServerTelemetryBuilder + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +object KtorBuilderUtil { + lateinit var clientBuilderExtractor: (AbstractKtorClientTelemetryBuilder) -> DefaultHttpClientInstrumenterBuilder + lateinit var serverBuilderExtractor: ( + AbstractKtorServerTelemetryBuilder + ) -> DefaultHttpServerInstrumenterBuilder +} diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/internal/KtorBuilderUtil.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorBuilderUtilOld.kt similarity index 70% rename from instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/internal/KtorBuilderUtil.kt rename to instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorBuilderUtilOld.kt index ec074cca66bd..9154c7f7cd60 100644 --- a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/internal/KtorBuilderUtil.kt +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorBuilderUtilOld.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.internal +package io.opentelemetry.instrumentation.ktor.v2_0.common.internal import io.ktor.client.request.* import io.ktor.client.statement.* @@ -11,14 +11,15 @@ import io.ktor.server.request.* import io.ktor.server.response.* import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder -import io.opentelemetry.instrumentation.ktor.client.AbstractKtorClientTracingBuilder -import io.opentelemetry.instrumentation.ktor.server.AbstractKtorServerTracingBuilder +import io.opentelemetry.instrumentation.ktor.v2_0.common.client.AbstractKtorClientTracingBuilder +import io.opentelemetry.instrumentation.ktor.v2_0.common.server.AbstractKtorServerTracingBuilder /** * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. */ -object KtorBuilderUtil { +@Deprecated("Use KtorBuilderUtil instead", ReplaceWith("KtorBuilderUtil")) +object KtorBuilderUtilOld { lateinit var clientBuilderExtractor: (AbstractKtorClientTracingBuilder) -> DefaultHttpClientInstrumenterBuilder lateinit var serverBuilderExtractor: ( AbstractKtorServerTracingBuilder diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorClientTelemetryUtil.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorClientTelemetryUtil.kt new file mode 100644 index 000000000000..2bb2c8f0e016 --- /dev/null +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorClientTelemetryUtil.kt @@ -0,0 +1,88 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0.common.internal + +import io.ktor.client.* +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.util.* +import io.ktor.util.pipeline.* +import io.opentelemetry.context.Context +import io.opentelemetry.extension.kotlin.asContextElement +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientRequestResendCount +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorClientTelemetry +import kotlinx.coroutines.InternalCoroutinesApi +import kotlinx.coroutines.job +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +object KtorClientTelemetryUtil { + private val openTelemetryContextKey = AttributeKey("OpenTelemetry") + + fun install(plugin: AbstractKtorClientTelemetry, scope: HttpClient) { + installSpanCreation(plugin, scope) + installSpanEnd(plugin, scope) + } + + private fun installSpanCreation(plugin: AbstractKtorClientTelemetry, scope: HttpClient) { + val initializeRequestPhase = PipelinePhase("OpenTelemetryInitializeRequest") + scope.requestPipeline.insertPhaseAfter(HttpRequestPipeline.State, initializeRequestPhase) + + scope.requestPipeline.intercept(initializeRequestPhase) { + val openTelemetryContext = HttpClientRequestResendCount.initialize(Context.current()) + withContext(openTelemetryContext.asContextElement()) { proceed() } + } + + val createSpanPhase = PipelinePhase("OpenTelemetryCreateSpan") + scope.sendPipeline.insertPhaseAfter(HttpSendPipeline.State, createSpanPhase) + + scope.sendPipeline.intercept(createSpanPhase) { + val requestBuilder = context + val openTelemetryContext = plugin.createSpan(requestBuilder) + + if (openTelemetryContext != null) { + try { + requestBuilder.attributes.put(openTelemetryContextKey, openTelemetryContext) + plugin.populateRequestHeaders(requestBuilder, openTelemetryContext) + + withContext(openTelemetryContext.asContextElement()) { proceed() } + } catch (e: Throwable) { + plugin.endSpan(openTelemetryContext, requestBuilder, null, e) + throw e + } + } else { + proceed() + } + } + } + + @OptIn(InternalCoroutinesApi::class) + private fun installSpanEnd(plugin: AbstractKtorClientTelemetry, scope: HttpClient) { + val endSpanPhase = PipelinePhase("OpenTelemetryEndSpan") + scope.receivePipeline.insertPhaseBefore(HttpReceivePipeline.State, endSpanPhase) + + scope.receivePipeline.intercept(endSpanPhase) { + val openTelemetryContext = it.call.attributes.getOrNull(openTelemetryContextKey) + openTelemetryContext ?: return@intercept + + scope.launch { + val job = it.call.coroutineContext.job + job.join() + val cause = if (!job.isCancelled) { + null + } else { + kotlin.runCatching { job.getCancellationException() }.getOrNull() + } + + plugin.endSpan(openTelemetryContext, it.call, cause) + } + } + } +} diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/internal/KtorClientTracingUtil.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorClientTracingUtil.kt similarity index 92% rename from instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/internal/KtorClientTracingUtil.kt rename to instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorClientTracingUtil.kt index b1735217a99a..45e0f1d22559 100644 --- a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/internal/KtorClientTracingUtil.kt +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorClientTracingUtil.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.internal +package io.opentelemetry.instrumentation.ktor.v2_0.common.internal import io.ktor.client.* import io.ktor.client.request.* @@ -13,7 +13,7 @@ import io.ktor.util.pipeline.* import io.opentelemetry.context.Context import io.opentelemetry.extension.kotlin.asContextElement import io.opentelemetry.instrumentation.api.semconv.http.HttpClientRequestResendCount -import io.opentelemetry.instrumentation.ktor.client.AbstractKtorClientTracing +import io.opentelemetry.instrumentation.ktor.v2_0.common.client.AbstractKtorClientTracing import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.job import kotlinx.coroutines.launch @@ -23,6 +23,7 @@ import kotlinx.coroutines.withContext * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. */ +@Deprecated("Use KtorClientTelemetryUtil instead", ReplaceWith("KtorClientTelemetryUtil")) object KtorClientTracingUtil { private val openTelemetryContextKey = AttributeKey("OpenTelemetry") diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorServerTelemetryUtil.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorServerTelemetryUtil.kt new file mode 100644 index 000000000000..37f04c8568da --- /dev/null +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorServerTelemetryUtil.kt @@ -0,0 +1,83 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0.common.internal + +import io.ktor.server.application.* +import io.ktor.server.request.* +import io.ktor.server.response.* +import io.ktor.util.* +import io.ktor.util.pipeline.* +import io.opentelemetry.context.Context +import io.opentelemetry.extension.kotlin.asContextElement +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter +import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor +import io.opentelemetry.instrumentation.api.internal.InstrumenterUtil +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorServerTelemetryBuilder +import io.opentelemetry.instrumentation.ktor.v2_0.common.ApplicationRequestGetter +import kotlinx.coroutines.withContext + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +object KtorServerTelemetryUtil { + + fun configureTelemetry(builder: AbstractKtorServerTelemetryBuilder, application: Application) { + val contextKey = AttributeKey("OpenTelemetry") + val errorKey = AttributeKey("OpenTelemetryException") + + val instrumenter = instrumenter(builder) + val tracer = KtorServerTracer(instrumenter) + val startPhase = PipelinePhase("OpenTelemetry") + + application.insertPhaseBefore(ApplicationCallPipeline.Monitoring, startPhase) + application.intercept(startPhase) { + val context = tracer.start(call) + + if (context != null) { + call.attributes.put(contextKey, context) + withContext(context.asContextElement()) { + try { + proceed() + } catch (err: Throwable) { + // Stash error for reporting later since need ktor to finish setting up the response + call.attributes.put(errorKey, err) + throw err + } + } + } else { + proceed() + } + } + + val postSendPhase = PipelinePhase("OpenTelemetryPostSend") + application.sendPipeline.insertPhaseAfter(ApplicationSendPipeline.After, postSendPhase) + application.sendPipeline.intercept(postSendPhase) { + val context = call.attributes.getOrNull(contextKey) + if (context != null) { + var error: Throwable? = call.attributes.getOrNull(errorKey) + try { + proceed() + } catch (t: Throwable) { + error = t + throw t + } finally { + tracer.end(context, call, error) + } + } else { + proceed() + } + } + } + + private fun instrumenter(builder: AbstractKtorServerTelemetryBuilder): Instrumenter { + return InstrumenterUtil.buildUpstreamInstrumenter( + builder.builder.instrumenterBuilder(), + ApplicationRequestGetter, + builder.spanKindExtractor(SpanKindExtractor.alwaysServer()) + ) + } +} diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/internal/KtorServerTracer.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorServerTracer.kt similarity index 92% rename from instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/internal/KtorServerTracer.kt rename to instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorServerTracer.kt index 2226f4169a94..7e6f5af975a8 100644 --- a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/internal/KtorServerTracer.kt +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorServerTracer.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.internal +package io.opentelemetry.instrumentation.ktor.v2_0.common.internal import io.ktor.server.application.* import io.ktor.server.request.* diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/internal/KtorServerTracingUtil.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorServerTracingUtil.kt similarity index 88% rename from instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/internal/KtorServerTracingUtil.kt rename to instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorServerTracingUtil.kt index e5e3ea4fc908..e03c8be47f08 100644 --- a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/internal/KtorServerTracingUtil.kt +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/internal/KtorServerTracingUtil.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.internal +package io.opentelemetry.instrumentation.ktor.v2_0.common.internal import io.ktor.server.application.* import io.ktor.server.request.* @@ -15,14 +15,15 @@ import io.opentelemetry.extension.kotlin.asContextElement import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor import io.opentelemetry.instrumentation.api.internal.InstrumenterUtil -import io.opentelemetry.instrumentation.ktor.server.AbstractKtorServerTracingBuilder -import io.opentelemetry.instrumentation.ktor.server.ApplicationRequestGetter +import io.opentelemetry.instrumentation.ktor.v2_0.common.ApplicationRequestGetter +import io.opentelemetry.instrumentation.ktor.v2_0.common.server.AbstractKtorServerTracingBuilder import kotlinx.coroutines.withContext /** * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. */ +@Deprecated("Use KtorServerTelemetryUtil instead", ReplaceWith("KtorServerTelemetryUtil")) object KtorServerTracingUtil { fun configureTracing(builder: AbstractKtorServerTracingBuilder, application: Application) { diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/server/AbstractKtorServerTracingBuilder.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/server/AbstractKtorServerTracingBuilder.kt similarity index 94% rename from instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/server/AbstractKtorServerTracingBuilder.kt rename to instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/server/AbstractKtorServerTracingBuilder.kt index c822bb806c06..8064f208a29b 100644 --- a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/server/AbstractKtorServerTracingBuilder.kt +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/server/AbstractKtorServerTracingBuilder.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.server +package io.opentelemetry.instrumentation.ktor.v2_0.common.server import io.ktor.http.* import io.ktor.server.request.* @@ -18,13 +18,15 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusBuilder import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor -import io.opentelemetry.instrumentation.ktor.internal.KtorBuilderUtil +import io.opentelemetry.instrumentation.ktor.v2_0.common.KtorHttpServerAttributesGetter +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorBuilderUtilOld import java.util.function.Function +@Deprecated("Use AbstractKtorServerTelemetryBuilder instead", ReplaceWith("AbstractKtorServerTelemetryBuilder")) abstract class AbstractKtorServerTracingBuilder(private val instrumentationName: String) { companion object { init { - KtorBuilderUtil.serverBuilderExtractor = { it.serverBuilder } + KtorBuilderUtilOld.serverBuilderExtractor = { it.serverBuilder } } } diff --git a/instrumentation/ktor/ktor-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v2_0/HttpClientInstrumentation.java b/instrumentation/ktor/ktor-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v2_0/HttpClientInstrumentation.java index 79fb525fdb7a..8a5276c6d695 100644 --- a/instrumentation/ktor/ktor-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v2_0/HttpClientInstrumentation.java +++ b/instrumentation/ktor/ktor-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v2_0/HttpClientInstrumentation.java @@ -13,9 +13,9 @@ import io.ktor.client.HttpClientConfig; import io.ktor.client.engine.HttpClientEngineConfig; import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.ktor.internal.KtorBuilderUtil; -import io.opentelemetry.instrumentation.ktor.v2_0.client.KtorClientTracing; -import io.opentelemetry.instrumentation.ktor.v2_0.client.KtorClientTracingBuilder; +import io.opentelemetry.instrumentation.ktor.v2_0.KtorClientTelemetry; +import io.opentelemetry.instrumentation.ktor.v2_0.KtorClientTelemetryBuilder; +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorBuilderUtil; import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; @@ -46,14 +46,14 @@ public static class ConstructorAdvice { @Advice.OnMethodEnter public static void onEnter( @Advice.Argument(1) HttpClientConfig httpClientConfig) { - httpClientConfig.install(KtorClientTracing.Companion, new SetupFunction()); + httpClientConfig.install(KtorClientTelemetry.Companion, new SetupFunction()); } } - public static class SetupFunction implements Function1 { + public static class SetupFunction implements Function1 { @Override - public Unit invoke(KtorClientTracingBuilder builder) { + public Unit invoke(KtorClientTelemetryBuilder builder) { builder.setOpenTelemetry(GlobalOpenTelemetry.get()); KtorBuilderUtil.clientBuilderExtractor.invoke(builder).configure(AgentCommonConfig.get()); return kotlin.Unit.INSTANCE; diff --git a/instrumentation/ktor/ktor-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v2_0/ServerInstrumentation.java b/instrumentation/ktor/ktor-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v2_0/ServerInstrumentation.java index 214d94d80df0..421c199a95b2 100644 --- a/instrumentation/ktor/ktor-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v2_0/ServerInstrumentation.java +++ b/instrumentation/ktor/ktor-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v2_0/ServerInstrumentation.java @@ -11,9 +11,9 @@ import io.ktor.server.application.Application; import io.ktor.server.application.ApplicationPluginKt; import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.ktor.internal.KtorBuilderUtil; -import io.opentelemetry.instrumentation.ktor.server.AbstractKtorServerTracingBuilder; -import io.opentelemetry.instrumentation.ktor.v2_0.server.KtorServerTracingBuilderKt; +import io.opentelemetry.instrumentation.ktor.v2_0.KtorServerTelemetryBuilderKt; +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorServerTelemetryBuilder; +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorBuilderUtil; import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; @@ -41,15 +41,15 @@ public static class ConstructorAdvice { @Advice.OnMethodExit public static void onExit(@Advice.FieldValue("_applicationInstance") Application application) { ApplicationPluginKt.install( - application, KtorServerTracingBuilderKt.getKtorServerTracing(), new SetupFunction()); + application, KtorServerTelemetryBuilderKt.getKtorServerTelemetry(), new SetupFunction()); } } public static class SetupFunction - implements Function1 { + implements Function1 { @Override - public Unit invoke(AbstractKtorServerTracingBuilder builder) { + public Unit invoke(AbstractKtorServerTelemetryBuilder builder) { builder.setOpenTelemetry(GlobalOpenTelemetry.get()); KtorBuilderUtil.serverBuilderExtractor.invoke(builder).configure(AgentCommonConfig.get()); return kotlin.Unit.INSTANCE; diff --git a/instrumentation/ktor/ktor-2.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorHttpClientTest.kt b/instrumentation/ktor/ktor-2.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpClientTest.kt similarity index 89% rename from instrumentation/ktor/ktor-2.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorHttpClientTest.kt rename to instrumentation/ktor/ktor-2.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpClientTest.kt index 8b8b655f8475..ba9c459b76cb 100644 --- a/instrumentation/ktor/ktor-2.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorHttpClientTest.kt +++ b/instrumentation/ktor/ktor-2.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpClientTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v2_0.client +package io.opentelemetry.instrumentation.ktor.v2_0 import io.ktor.client.* import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension diff --git a/instrumentation/ktor/ktor-3.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v3_0/server/KtorHttpServerTest.kt b/instrumentation/ktor/ktor-2.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpServerTest.kt similarity index 94% rename from instrumentation/ktor/ktor-3.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v3_0/server/KtorHttpServerTest.kt rename to instrumentation/ktor/ktor-2.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpServerTest.kt index 138a6911144d..ec212c53996f 100644 --- a/instrumentation/ktor/ktor-3.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v3_0/server/KtorHttpServerTest.kt +++ b/instrumentation/ktor/ktor-2.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpServerTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v3_0.server +package io.opentelemetry.instrumentation.ktor.v2_0 import io.ktor.server.application.* import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension diff --git a/instrumentation/ktor/ktor-2.0/library/README.md b/instrumentation/ktor/ktor-2.0/library/README.md index f9af95e58a5b..6740d0c0fcea 100644 --- a/instrumentation/ktor/ktor-2.0/library/README.md +++ b/instrumentation/ktor/ktor-2.0/library/README.md @@ -1,6 +1,7 @@ # Library Instrumentation for Ktor version 2.x -This package contains libraries to help instrument Ktor. Server and client instrumentations are supported. +This package contains libraries to help instrument Ktor. +Server and client instrumentations are supported. ## Quickstart @@ -31,14 +32,14 @@ implementation("io.opentelemetry.instrumentation:opentelemetry-ktor-2.0:OPENTELE ## Initializing server instrumentation -Initialize instrumentation by installing the `KtorServerTracing` feature. You must set the `OpenTelemetry` to use with -the feature. +Initialize instrumentation by installing the `KtorServerTelemetry` feature. +You must set the `OpenTelemetry` to use with the feature. ```kotlin val openTelemetry: OpenTelemetry = ... embeddedServer(Netty, 8080) { - install(KtorServerTracing) { + install(KtorServerTelemetry) { setOpenTelemetry(openTelemetry) } } @@ -46,14 +47,15 @@ embeddedServer(Netty, 8080) { ## Initializing client instrumentation -Initialize instrumentation by installing the `KtorClientTracing` feature. You must set the `OpenTelemetry` to use with +Initialize instrumentation by installing the `KtorClientTelemetry` feature. You must set the +`OpenTelemetry` to use with the feature. ```kotlin val openTelemetry: OpenTelemetry = ... val client = HttpClient { - install(KtorClientTracing) { + install(KtorClientTelemetry) { setOpenTelemetry(openTelemetry) } } diff --git a/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorClientTelemetry.kt b/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorClientTelemetry.kt new file mode 100644 index 000000000000..ae06c51b9403 --- /dev/null +++ b/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorClientTelemetry.kt @@ -0,0 +1,33 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0 + +import io.ktor.client.* +import io.ktor.client.plugins.* +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.util.* +import io.opentelemetry.context.propagation.ContextPropagators +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorClientTelemetry +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorClientTelemetryUtil + +class KtorClientTelemetry internal constructor( + instrumenter: Instrumenter, + propagators: ContextPropagators +) : AbstractKtorClientTelemetry(instrumenter, propagators) { + + companion object : HttpClientPlugin { + + override val key = AttributeKey("OpenTelemetry") + + override fun prepare(block: KtorClientTelemetryBuilder.() -> Unit) = KtorClientTelemetryBuilder().apply(block).build() + + override fun install(plugin: KtorClientTelemetry, scope: HttpClient) { + KtorClientTelemetryUtil.install(plugin, scope) + } + } +} diff --git a/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorClientTelemetryBuilder.kt b/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorClientTelemetryBuilder.kt new file mode 100644 index 000000000000..6c71aa3815a8 --- /dev/null +++ b/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorClientTelemetryBuilder.kt @@ -0,0 +1,17 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0 + +import io.opentelemetry.instrumentation.ktor.v2_0.InstrumentationProperties.INSTRUMENTATION_NAME +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorClientTelemetryBuilder + +class KtorClientTelemetryBuilder : AbstractKtorClientTelemetryBuilder(INSTRUMENTATION_NAME) { + + internal fun build(): KtorClientTelemetry = KtorClientTelemetry( + instrumenter = builder.build(), + propagators = getOpenTelemetry().propagators, + ) +} diff --git a/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorServerTelemetryBuilder.kt b/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorServerTelemetryBuilder.kt new file mode 100644 index 000000000000..63d6931f3fe9 --- /dev/null +++ b/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorServerTelemetryBuilder.kt @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0 + +import io.ktor.server.application.* +import io.ktor.server.routing.* +import io.opentelemetry.context.Context +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteSource +import io.opentelemetry.instrumentation.ktor.v2_0.InstrumentationProperties.INSTRUMENTATION_NAME +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorServerTelemetryBuilder +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorServerTelemetryUtil + +class KtorServerTelemetryBuilder internal constructor( + instrumentationName: String +) : AbstractKtorServerTelemetryBuilder(instrumentationName) + +val KtorServerTelemetry = createRouteScopedPlugin("OpenTelemetry", { KtorServerTelemetryBuilder(INSTRUMENTATION_NAME) }) { + require(pluginConfig.isOpenTelemetryInitialized()) { "OpenTelemetry must be set" } + + KtorServerTelemetryUtil.configureTelemetry(pluginConfig, application) + + application.environment.monitor.subscribe(Routing.RoutingCallStarted) { call -> + HttpServerRoute.update(Context.current(), HttpServerRouteSource.SERVER, { _, arg -> arg.route.parent.toString() }, call) + } +} diff --git a/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorClientTracing.kt b/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorClientTracing.kt index 429e2ccdfe0c..d9dcf9796f67 100644 --- a/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorClientTracing.kt +++ b/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorClientTracing.kt @@ -12,9 +12,10 @@ import io.ktor.client.statement.* import io.ktor.util.* import io.opentelemetry.context.propagation.ContextPropagators import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter -import io.opentelemetry.instrumentation.ktor.client.AbstractKtorClientTracing -import io.opentelemetry.instrumentation.ktor.internal.KtorClientTracingUtil +import io.opentelemetry.instrumentation.ktor.v2_0.common.client.AbstractKtorClientTracing +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorClientTracingUtil +@Deprecated("Use KtorClientTelemetry instead", ReplaceWith("KtorClientTelemetry")) class KtorClientTracing internal constructor( instrumenter: Instrumenter, propagators: ContextPropagators diff --git a/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorClientTracingBuilder.kt b/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorClientTracingBuilder.kt index b93fb82f02da..706852a3178a 100644 --- a/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorClientTracingBuilder.kt +++ b/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorClientTracingBuilder.kt @@ -5,9 +5,10 @@ package io.opentelemetry.instrumentation.ktor.v2_0.client -import io.opentelemetry.instrumentation.ktor.client.AbstractKtorClientTracingBuilder import io.opentelemetry.instrumentation.ktor.v2_0.InstrumentationProperties.INSTRUMENTATION_NAME +import io.opentelemetry.instrumentation.ktor.v2_0.common.client.AbstractKtorClientTracingBuilder +@Deprecated("Use KtorClientTelemetryBuilder instead", ReplaceWith("KtorClientTelemetryBuilder")) class KtorClientTracingBuilder : AbstractKtorClientTracingBuilder(INSTRUMENTATION_NAME) { internal fun build(): KtorClientTracing = KtorClientTracing( diff --git a/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorServerTracingBuilder.kt b/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorServerTracingBuilder.kt index b2c4be9b86db..c82c99fccb5e 100644 --- a/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorServerTracingBuilder.kt +++ b/instrumentation/ktor/ktor-2.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorServerTracingBuilder.kt @@ -10,10 +10,11 @@ import io.ktor.server.routing.* import io.opentelemetry.context.Context import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteSource -import io.opentelemetry.instrumentation.ktor.internal.KtorServerTracingUtil -import io.opentelemetry.instrumentation.ktor.server.AbstractKtorServerTracingBuilder import io.opentelemetry.instrumentation.ktor.v2_0.InstrumentationProperties.INSTRUMENTATION_NAME +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorServerTracingUtil +import io.opentelemetry.instrumentation.ktor.v2_0.common.server.AbstractKtorServerTracingBuilder +@Deprecated("Use KtorServerTelemetryBuilder instead", ReplaceWith("KtorServerTelemetryBuilder")) class KtorServerTracingBuilder internal constructor( instrumentationName: String ) : AbstractKtorServerTracingBuilder(instrumentationName) diff --git a/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpClientOldTest.kt b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpClientOldTest.kt new file mode 100644 index 000000000000..be7dfca50080 --- /dev/null +++ b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpClientOldTest.kt @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0 + +import io.ktor.client.* +import io.opentelemetry.instrumentation.ktor.v2_0.client.KtorClientTracing +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension +import org.junit.jupiter.api.extension.RegisterExtension + +class KtorHttpClientOldTest : AbstractKtorHttpClientTest() { + + companion object { + @JvmStatic + @RegisterExtension + private val TESTING = HttpClientInstrumentationExtension.forLibrary() + } + + override fun HttpClientConfig<*>.installTracing() { + install(KtorClientTracing) { + setOpenTelemetry(TESTING.openTelemetry) + capturedRequestHeaders(TEST_REQUEST_HEADER) + capturedResponseHeaders(TEST_RESPONSE_HEADER) + } + } +} diff --git a/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorHttpClientTest.kt b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpClientTest.kt similarity index 88% rename from instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorHttpClientTest.kt rename to instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpClientTest.kt index 0249949e8ebb..6eac7443e164 100644 --- a/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorHttpClientTest.kt +++ b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpClientTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v3_0.client +package io.opentelemetry.instrumentation.ktor.v2_0 import io.ktor.client.* import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension @@ -18,7 +18,7 @@ class KtorHttpClientTest : AbstractKtorHttpClientTest() { } override fun HttpClientConfig<*>.installTracing() { - install(KtorClientTracing) { + install(KtorClientTelemetry) { setOpenTelemetry(TESTING.openTelemetry) capturedRequestHeaders(TEST_REQUEST_HEADER) capturedResponseHeaders(TEST_RESPONSE_HEADER) diff --git a/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpServerOldTest.kt b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpServerOldTest.kt new file mode 100644 index 000000000000..d11469ac3a71 --- /dev/null +++ b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpServerOldTest.kt @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0 + +import io.ktor.server.application.* +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension +import org.junit.jupiter.api.extension.RegisterExtension + +class KtorHttpServerOldTest : AbstractKtorHttpServerTest() { + + companion object { + @JvmStatic + @RegisterExtension + val TESTING: InstrumentationExtension = HttpServerInstrumentationExtension.forLibrary() + } + + override fun getTesting(): InstrumentationExtension { + return TESTING + } + + override fun installOpenTelemetry(application: Application) { + KtorOldTestUtil.installOpenTelemetry(application, TESTING.openTelemetry) + } +} diff --git a/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorHttpServerTest.kt b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpServerTest.kt similarity index 93% rename from instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorHttpServerTest.kt rename to instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpServerTest.kt index 97f4022c3102..ef76aac9cda9 100644 --- a/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorHttpServerTest.kt +++ b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpServerTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v2_0.server +package io.opentelemetry.instrumentation.ktor.v2_0 import io.ktor.server.application.* import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension diff --git a/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorOldTestUtil.kt b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorOldTestUtil.kt new file mode 100644 index 000000000000..10cc11f52222 --- /dev/null +++ b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorOldTestUtil.kt @@ -0,0 +1,23 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v2_0 + +import io.ktor.server.application.* +import io.opentelemetry.api.OpenTelemetry +import io.opentelemetry.instrumentation.ktor.v2_0.server.KtorServerTracing +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest + +class KtorOldTestUtil { + companion object { + fun installOpenTelemetry(application: Application, openTelemetry: OpenTelemetry) { + application.install(KtorServerTracing) { + setOpenTelemetry(openTelemetry) + capturedRequestHeaders(AbstractHttpServerTest.TEST_REQUEST_HEADER) + capturedResponseHeaders(AbstractHttpServerTest.TEST_RESPONSE_HEADER) + } + } + } +} diff --git a/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorServerSpanKindExtractorTest.kt b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorServerSpanKindExtractorTest.kt similarity index 96% rename from instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorServerSpanKindExtractorTest.kt rename to instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorServerSpanKindExtractorTest.kt index e4ab5d89391a..9605454d3b1e 100644 --- a/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorServerSpanKindExtractorTest.kt +++ b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorServerSpanKindExtractorTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v2_0.server +package io.opentelemetry.instrumentation.ktor.v2_0 import io.ktor.http.* import io.ktor.server.application.* @@ -13,6 +13,7 @@ import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.opentelemetry.api.trace.SpanKind +import io.opentelemetry.instrumentation.ktor.v2_0.server.KtorServerTracing import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerUsingTest import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension diff --git a/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorTestUtil.kt b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorTestUtil.kt similarity index 84% rename from instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorTestUtil.kt rename to instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorTestUtil.kt index 6a799635c1c5..dc85e9030b48 100644 --- a/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorTestUtil.kt +++ b/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorTestUtil.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v2_0.server +package io.opentelemetry.instrumentation.ktor.v2_0 import io.ktor.server.application.* import io.opentelemetry.api.OpenTelemetry @@ -12,7 +12,7 @@ import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTes class KtorTestUtil { companion object { fun installOpenTelemetry(application: Application, openTelemetry: OpenTelemetry) { - application.install(KtorServerTracing) { + application.install(KtorServerTelemetry) { setOpenTelemetry(openTelemetry) capturedRequestHeaders(AbstractHttpServerTest.TEST_REQUEST_HEADER) capturedResponseHeaders(AbstractHttpServerTest.TEST_RESPONSE_HEADER) diff --git a/instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/AbstractKtorHttpClientTest.kt b/instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/AbstractKtorHttpClientTest.kt similarity index 92% rename from instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/AbstractKtorHttpClientTest.kt rename to instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/AbstractKtorHttpClientTest.kt index 991e32f347f6..38124f0dc338 100644 --- a/instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/AbstractKtorHttpClientTest.kt +++ b/instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/AbstractKtorHttpClientTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v2_0.client +package io.opentelemetry.instrumentation.ktor.v2_0 import io.ktor.client.* import io.ktor.client.engine.cio.* @@ -17,7 +17,10 @@ import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions.DEFAULT_HTTP_ATTRIBUTES import io.opentelemetry.semconv.NetworkAttributes -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.AfterAll import java.net.URI diff --git a/instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/AbstractKtorHttpServerTest.kt b/instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/AbstractKtorHttpServerTest.kt similarity index 98% rename from instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/AbstractKtorHttpServerTest.kt rename to instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/AbstractKtorHttpServerTest.kt index 13c424166036..863492509cb8 100644 --- a/instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/server/AbstractKtorHttpServerTest.kt +++ b/instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/AbstractKtorHttpServerTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v2_0.server +package io.opentelemetry.instrumentation.ktor.v2_0 import io.ktor.http.* import io.ktor.server.application.* diff --git a/instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorHttpClientSingleConnection.kt b/instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpClientSingleConnection.kt similarity index 89% rename from instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorHttpClientSingleConnection.kt rename to instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpClientSingleConnection.kt index 2396d62bb6b1..2d0de2d6e800 100644 --- a/instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorHttpClientSingleConnection.kt +++ b/instrumentation/ktor/ktor-2.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/KtorHttpClientSingleConnection.kt @@ -3,10 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v2_0.client +package io.opentelemetry.instrumentation.ktor.v2_0 import io.ktor.client.* -import io.ktor.client.engine.cio.* import io.ktor.client.request.* import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection import kotlinx.coroutines.runBlocking diff --git a/instrumentation/ktor/ktor-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v3_0/HttpClientInstrumentation.java b/instrumentation/ktor/ktor-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v3_0/HttpClientInstrumentation.java index 09dfcca67e20..f3b6c676d437 100644 --- a/instrumentation/ktor/ktor-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v3_0/HttpClientInstrumentation.java +++ b/instrumentation/ktor/ktor-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v3_0/HttpClientInstrumentation.java @@ -13,9 +13,9 @@ import io.ktor.client.HttpClientConfig; import io.ktor.client.engine.HttpClientEngineConfig; import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.ktor.internal.KtorBuilderUtil; -import io.opentelemetry.instrumentation.ktor.v3_0.client.KtorClientTracing; -import io.opentelemetry.instrumentation.ktor.v3_0.client.KtorClientTracingBuilder; +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorBuilderUtil; +import io.opentelemetry.instrumentation.ktor.v3_0.KtorClientTelemetry; +import io.opentelemetry.instrumentation.ktor.v3_0.KtorClientTelemetryBuilder; import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; @@ -46,14 +46,14 @@ public static class ConstructorAdvice { @Advice.OnMethodEnter public static void onEnter( @Advice.Argument(1) HttpClientConfig httpClientConfig) { - httpClientConfig.install(KtorClientTracing.Companion, new SetupFunction()); + httpClientConfig.install(KtorClientTelemetry.Companion, new SetupFunction()); } } - public static class SetupFunction implements Function1 { + public static class SetupFunction implements Function1 { @Override - public Unit invoke(KtorClientTracingBuilder builder) { + public Unit invoke(KtorClientTelemetryBuilder builder) { builder.setOpenTelemetry(GlobalOpenTelemetry.get()); KtorBuilderUtil.clientBuilderExtractor.invoke(builder).configure(AgentCommonConfig.get()); return Unit.INSTANCE; diff --git a/instrumentation/ktor/ktor-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v3_0/ServerInstrumentation.java b/instrumentation/ktor/ktor-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v3_0/ServerInstrumentation.java index df4335fa686d..f5dc7368e78a 100644 --- a/instrumentation/ktor/ktor-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v3_0/ServerInstrumentation.java +++ b/instrumentation/ktor/ktor-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v3_0/ServerInstrumentation.java @@ -11,9 +11,9 @@ import io.ktor.server.application.Application; import io.ktor.server.application.ApplicationPluginKt; import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.ktor.internal.KtorBuilderUtil; -import io.opentelemetry.instrumentation.ktor.server.AbstractKtorServerTracingBuilder; -import io.opentelemetry.instrumentation.ktor.v3_0.server.KtorServerTracingBuilderKt; +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorServerTelemetryBuilder; +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorBuilderUtil; +import io.opentelemetry.instrumentation.ktor.v3_0.KtorServerTelemetryBuilderKt; import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; @@ -41,14 +41,14 @@ public static class ConstructorAdvice { @Advice.OnMethodExit public static void onExit(@Advice.FieldValue("_applicationInstance") Application application) { ApplicationPluginKt.install( - application, KtorServerTracingBuilderKt.getKtorServerTracing(), new SetupFunction()); + application, KtorServerTelemetryBuilderKt.getKtorServerTelemetry(), new SetupFunction()); } } - public static class SetupFunction implements Function1 { + public static class SetupFunction implements Function1 { @Override - public Unit invoke(AbstractKtorServerTracingBuilder builder) { + public Unit invoke(AbstractKtorServerTelemetryBuilder builder) { builder.setOpenTelemetry(GlobalOpenTelemetry.get()); KtorBuilderUtil.serverBuilderExtractor.invoke(builder).configure(AgentCommonConfig.get()); return Unit.INSTANCE; diff --git a/instrumentation/ktor/ktor-3.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorHttpClientTest.kt b/instrumentation/ktor/ktor-3.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpClientTest.kt similarity index 89% rename from instrumentation/ktor/ktor-3.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorHttpClientTest.kt rename to instrumentation/ktor/ktor-3.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpClientTest.kt index b9e3623e01a9..a58f4d856e13 100644 --- a/instrumentation/ktor/ktor-3.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorHttpClientTest.kt +++ b/instrumentation/ktor/ktor-3.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpClientTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v3_0.client +package io.opentelemetry.instrumentation.ktor.v3_0 import io.ktor.client.* import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension diff --git a/instrumentation/ktor/ktor-2.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorHttpServerTest.kt b/instrumentation/ktor/ktor-3.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpServerTest.kt similarity index 94% rename from instrumentation/ktor/ktor-2.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorHttpServerTest.kt rename to instrumentation/ktor/ktor-3.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpServerTest.kt index f9776431becf..e25dbb7ac3ea 100644 --- a/instrumentation/ktor/ktor-2.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v2_0/server/KtorHttpServerTest.kt +++ b/instrumentation/ktor/ktor-3.0/javaagent/src/test/java/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpServerTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v2_0.server +package io.opentelemetry.instrumentation.ktor.v3_0 import io.ktor.server.application.* import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension diff --git a/instrumentation/ktor/ktor-3.0/library/README.md b/instrumentation/ktor/ktor-3.0/library/README.md index ce6fe411b3cd..cf60d12cc0fa 100644 --- a/instrumentation/ktor/ktor-3.0/library/README.md +++ b/instrumentation/ktor/ktor-3.0/library/README.md @@ -1,6 +1,7 @@ # Library Instrumentation for Ktor version 3.0 and higher -This package contains libraries to help instrument Ktor. Server and client instrumentations are supported. +This package contains libraries to help instrument Ktor. +Server and client instrumentations are supported. ## Quickstart @@ -31,14 +32,14 @@ implementation("io.opentelemetry.instrumentation:opentelemetry-ktor-3.0:OPENTELE ## Initializing server instrumentation -Initialize instrumentation by installing the `KtorServerTracing` feature. You must set the `OpenTelemetry` to use with -the feature. +Initialize instrumentation by installing the `KtorServerTelemetry` feature. +You must set the `OpenTelemetry` to use with the feature. ```kotlin val openTelemetry: OpenTelemetry = ... embeddedServer(Netty, 8080) { - install(KtorServerTracing) { + install(KtorServerTelemetry) { setOpenTelemetry(openTelemetry) } } @@ -46,14 +47,15 @@ embeddedServer(Netty, 8080) { ## Initializing client instrumentation -Initialize instrumentation by installing the `KtorClientTracing` feature. You must set the `OpenTelemetry` to use with +Initialize instrumentation by installing the `KtorClientTelemetry` feature. You must set the +`OpenTelemetry` to use with the feature. ```kotlin val openTelemetry: OpenTelemetry = ... val client = HttpClient { - install(KtorClientTracing) { + install(KtorClientTelemetry) { setOpenTelemetry(openTelemetry) } } diff --git a/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorClientTelemetry.kt b/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorClientTelemetry.kt new file mode 100644 index 000000000000..09a82366c6cf --- /dev/null +++ b/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorClientTelemetry.kt @@ -0,0 +1,33 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v3_0 + +import io.ktor.client.* +import io.ktor.client.plugins.* +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.util.* +import io.opentelemetry.context.propagation.ContextPropagators +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorClientTelemetry +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorClientTelemetryUtil + +class KtorClientTelemetry internal constructor( + instrumenter: Instrumenter, + propagators: ContextPropagators +) : AbstractKtorClientTelemetry(instrumenter, propagators) { + + companion object : HttpClientPlugin { + + override val key = AttributeKey("OpenTelemetry") + + override fun prepare(block: KtorClientTelemetryBuilder.() -> Unit) = KtorClientTelemetryBuilder().apply(block).build() + + override fun install(plugin: KtorClientTelemetry, scope: HttpClient) { + KtorClientTelemetryUtil.install(plugin, scope) + } + } +} diff --git a/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorClientTelemetryBuilder.kt b/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorClientTelemetryBuilder.kt new file mode 100644 index 000000000000..024f3d770b96 --- /dev/null +++ b/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorClientTelemetryBuilder.kt @@ -0,0 +1,17 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v3_0 + +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorClientTelemetryBuilder +import io.opentelemetry.instrumentation.ktor.v3_0.InstrumentationProperties.INSTRUMENTATION_NAME + +class KtorClientTelemetryBuilder : AbstractKtorClientTelemetryBuilder(INSTRUMENTATION_NAME) { + + internal fun build(): KtorClientTelemetry = KtorClientTelemetry( + instrumenter = builder.build(), + propagators = getOpenTelemetry().propagators, + ) +} diff --git a/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorServerTelemetryBuilder.kt b/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorServerTelemetryBuilder.kt new file mode 100644 index 000000000000..3a582af028ba --- /dev/null +++ b/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorServerTelemetryBuilder.kt @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v3_0 + +import io.ktor.server.application.* +import io.ktor.server.routing.* +import io.opentelemetry.context.Context +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteSource +import io.opentelemetry.instrumentation.ktor.v2_0.common.AbstractKtorServerTelemetryBuilder +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorServerTelemetryUtil +import io.opentelemetry.instrumentation.ktor.v3_0.InstrumentationProperties.INSTRUMENTATION_NAME + +class KtorServerTelemetryBuilder internal constructor( + instrumentationName: String +) : AbstractKtorServerTelemetryBuilder(instrumentationName) + +val KtorServerTelemetry = createRouteScopedPlugin("OpenTelemetry", { KtorServerTelemetryBuilder(INSTRUMENTATION_NAME) }) { + require(pluginConfig.isOpenTelemetryInitialized()) { "OpenTelemetry must be set" } + + KtorServerTelemetryUtil.configureTelemetry(pluginConfig, application) + + application.monitor.subscribe(RoutingRoot.RoutingCallStarted) { call -> + HttpServerRoute.update(Context.current(), HttpServerRouteSource.SERVER, { _, arg -> arg.route.parent.toString() }, call) + } +} diff --git a/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorClientTracing.kt b/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorClientTracing.kt index d5bf578cc56c..b63c4f6974ad 100644 --- a/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorClientTracing.kt +++ b/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorClientTracing.kt @@ -12,9 +12,10 @@ import io.ktor.client.statement.* import io.ktor.util.* import io.opentelemetry.context.propagation.ContextPropagators import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter -import io.opentelemetry.instrumentation.ktor.client.AbstractKtorClientTracing -import io.opentelemetry.instrumentation.ktor.internal.KtorClientTracingUtil +import io.opentelemetry.instrumentation.ktor.v2_0.common.client.AbstractKtorClientTracing +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorClientTracingUtil +@Deprecated("Use KtorClientTelemetry instead", ReplaceWith("KtorClientTelemetry")) class KtorClientTracing internal constructor( instrumenter: Instrumenter, propagators: ContextPropagators diff --git a/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorClientTracingBuilder.kt b/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorClientTracingBuilder.kt index 6f68939d9f06..b4787662b8e2 100644 --- a/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorClientTracingBuilder.kt +++ b/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorClientTracingBuilder.kt @@ -5,9 +5,10 @@ package io.opentelemetry.instrumentation.ktor.v3_0.client -import io.opentelemetry.instrumentation.ktor.client.AbstractKtorClientTracingBuilder +import io.opentelemetry.instrumentation.ktor.v2_0.common.client.AbstractKtorClientTracingBuilder import io.opentelemetry.instrumentation.ktor.v3_0.InstrumentationProperties.INSTRUMENTATION_NAME +@Deprecated("Use KtorClientTelemetryBuilder instead", ReplaceWith("KtorClientTelemetryBuilder")) class KtorClientTracingBuilder : AbstractKtorClientTracingBuilder(INSTRUMENTATION_NAME) { internal fun build(): KtorClientTracing = KtorClientTracing( diff --git a/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/server/KtorServerTracingBuilder.kt b/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/server/KtorServerTracingBuilder.kt index a086f7473fd8..e77e5487c866 100644 --- a/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/server/KtorServerTracingBuilder.kt +++ b/instrumentation/ktor/ktor-3.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/server/KtorServerTracingBuilder.kt @@ -10,10 +10,11 @@ import io.ktor.server.routing.* import io.opentelemetry.context.Context import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteSource -import io.opentelemetry.instrumentation.ktor.internal.KtorServerTracingUtil -import io.opentelemetry.instrumentation.ktor.server.AbstractKtorServerTracingBuilder +import io.opentelemetry.instrumentation.ktor.v2_0.common.internal.KtorServerTracingUtil +import io.opentelemetry.instrumentation.ktor.v2_0.common.server.AbstractKtorServerTracingBuilder import io.opentelemetry.instrumentation.ktor.v3_0.InstrumentationProperties.INSTRUMENTATION_NAME +@Deprecated("Use KtorServerTelemetryBuilder instead", ReplaceWith("KtorServerTelemetryBuilder")) class KtorServerTracingBuilder internal constructor( instrumentationName: String ) : AbstractKtorServerTracingBuilder(instrumentationName) diff --git a/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpClientOldTest.kt b/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpClientOldTest.kt new file mode 100644 index 000000000000..89b0d57bae03 --- /dev/null +++ b/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpClientOldTest.kt @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v3_0 + +import io.ktor.client.* +import io.opentelemetry.instrumentation.ktor.v3_0.client.KtorClientTracing +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension +import org.junit.jupiter.api.extension.RegisterExtension + +class KtorHttpClientOldTest : AbstractKtorHttpClientTest() { + + companion object { + @JvmStatic + @RegisterExtension + private val TESTING = HttpClientInstrumentationExtension.forLibrary() + } + + override fun HttpClientConfig<*>.installTracing() { + install(KtorClientTracing) { + setOpenTelemetry(TESTING.openTelemetry) + capturedRequestHeaders(TEST_REQUEST_HEADER) + capturedResponseHeaders(TEST_RESPONSE_HEADER) + } + } +} diff --git a/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorHttpClientTest.kt b/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpClientTest.kt similarity index 88% rename from instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorHttpClientTest.kt rename to instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpClientTest.kt index ada0183d30a1..a68d883d5bef 100644 --- a/instrumentation/ktor/ktor-2.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/client/KtorHttpClientTest.kt +++ b/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpClientTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v2_0.client +package io.opentelemetry.instrumentation.ktor.v3_0 import io.ktor.client.* import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension @@ -18,7 +18,7 @@ class KtorHttpClientTest : AbstractKtorHttpClientTest() { } override fun HttpClientConfig<*>.installTracing() { - install(KtorClientTracing) { + install(KtorClientTelemetry) { setOpenTelemetry(TESTING.openTelemetry) capturedRequestHeaders(TEST_REQUEST_HEADER) capturedResponseHeaders(TEST_RESPONSE_HEADER) diff --git a/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpServerOldTest.kt b/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpServerOldTest.kt new file mode 100644 index 000000000000..5a92a1df2d15 --- /dev/null +++ b/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpServerOldTest.kt @@ -0,0 +1,35 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ktor.v3_0 + +import io.ktor.server.application.* +import io.opentelemetry.instrumentation.ktor.v3_0.server.KtorServerTracing +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension +import org.junit.jupiter.api.extension.RegisterExtension + +class KtorHttpServerOldTest : AbstractKtorHttpServerTest() { + + companion object { + @JvmStatic + @RegisterExtension + val TESTING: InstrumentationExtension = HttpServerInstrumentationExtension.forLibrary() + } + + override fun getTesting(): InstrumentationExtension { + return TESTING + } + + override fun installOpenTelemetry(application: Application) { + application.apply { + install(KtorServerTracing) { + setOpenTelemetry(TESTING.openTelemetry) + capturedRequestHeaders(TEST_REQUEST_HEADER) + capturedResponseHeaders(TEST_RESPONSE_HEADER) + } + } + } +} diff --git a/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/server/KtorHttpServerTest.kt b/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpServerTest.kt similarity index 90% rename from instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/server/KtorHttpServerTest.kt rename to instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpServerTest.kt index 61caec27af83..a2afe636c077 100644 --- a/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/server/KtorHttpServerTest.kt +++ b/instrumentation/ktor/ktor-3.0/library/src/test/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpServerTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v3_0.server +package io.opentelemetry.instrumentation.ktor.v3_0 import io.ktor.server.application.* import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension @@ -24,7 +24,7 @@ class KtorHttpServerTest : AbstractKtorHttpServerTest() { override fun installOpenTelemetry(application: Application) { application.apply { - install(KtorServerTracing) { + install(KtorServerTelemetry) { setOpenTelemetry(TESTING.openTelemetry) capturedRequestHeaders(TEST_REQUEST_HEADER) capturedResponseHeaders(TEST_RESPONSE_HEADER) diff --git a/instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/AbstractKtorHttpClientTest.kt b/instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/AbstractKtorHttpClientTest.kt similarity index 92% rename from instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/AbstractKtorHttpClientTest.kt rename to instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/AbstractKtorHttpClientTest.kt index 2e698e34e461..086b15d66ae5 100644 --- a/instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/AbstractKtorHttpClientTest.kt +++ b/instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/AbstractKtorHttpClientTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v3_0.client +package io.opentelemetry.instrumentation.ktor.v3_0 import io.ktor.client.* import io.ktor.client.engine.cio.* @@ -17,7 +17,10 @@ import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions.DEFAULT_HTTP_ATTRIBUTES import io.opentelemetry.semconv.NetworkAttributes -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.AfterAll import java.net.URI diff --git a/instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/server/AbstractKtorHttpServerTest.kt b/instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/AbstractKtorHttpServerTest.kt similarity index 98% rename from instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/server/AbstractKtorHttpServerTest.kt rename to instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/AbstractKtorHttpServerTest.kt index 24d4eba8c5e4..5b4fba1eecc8 100644 --- a/instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/server/AbstractKtorHttpServerTest.kt +++ b/instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/AbstractKtorHttpServerTest.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v3_0.server +package io.opentelemetry.instrumentation.ktor.v3_0 import io.ktor.http.* import io.ktor.server.application.* diff --git a/instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorHttpClientSingleConnection.kt b/instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpClientSingleConnection.kt similarity index 89% rename from instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorHttpClientSingleConnection.kt rename to instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpClientSingleConnection.kt index 30290d4f1e0f..82a2679c5a12 100644 --- a/instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/client/KtorHttpClientSingleConnection.kt +++ b/instrumentation/ktor/ktor-3.0/testing/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v3_0/KtorHttpClientSingleConnection.kt @@ -3,10 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ktor.v3_0.client +package io.opentelemetry.instrumentation.ktor.v3_0 import io.ktor.client.* -import io.ktor.client.engine.cio.* import io.ktor.client.request.* import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection import kotlinx.coroutines.runBlocking