Instrumentation-specific bootstrap classes (#3495)
* Instrumentation-specific bootstrap classes * try to move bootstrap modules dependency to javaagent
This commit is contained in:
parent
e5bbc392c6
commit
3d1e782fc5
|
|
@ -261,7 +261,7 @@ idea {
|
|||
}
|
||||
|
||||
when (projectDir.name) {
|
||||
"javaagent", "library", "testing" -> {
|
||||
"bootstrap", "javaagent", "library", "testing" -> {
|
||||
// We don't use this group anywhere in our config, but we need to make sure it is unique per
|
||||
// instrumentation so Gradle doesn't merge projects with same name due to a bug in Gradle.
|
||||
// https://github.com/gradle/gradle/issues/847
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ plugins {
|
|||
id("otel.java-conventions")
|
||||
}
|
||||
|
||||
val bootstrap by configurations.creating
|
||||
|
||||
val instrumentationProjectTest = tasks.named("test")
|
||||
val instrumentationProjectDependencies = dependencies
|
||||
|
||||
|
|
@ -15,6 +17,12 @@ subprojects {
|
|||
instrumentationProjectTest.configure {
|
||||
dependsOn(subProj.tasks.named("test"))
|
||||
}
|
||||
|
||||
if (subProj.name == "bootstrap") {
|
||||
instrumentationProjectDependencies.run {
|
||||
add(bootstrap.name, project(subProj.path))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugins.withId("otel.javaagent-instrumentation") {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
plugins {
|
||||
id("otel.java-conventions")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("io.opentelemetry:opentelemetry-api")
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.bootstrap.undertow;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* Undertow's {@code io.undertow.server.HttpServerExchange} uses {@code
|
||||
* io.undertow.util.AttachmentKey} as a key for storing arbitrary data. It uses {@link
|
||||
* IdentityHashMap} and thus all keys are compared for equality by object reference. This means that
|
||||
* we cannot hold an instance of {@code io.undertow.util.AttachmentKey} in a static field of the
|
||||
* corresponding Tracer, as we usually do. Tracers are loaded into user's classloaders and thus it
|
||||
* is totally possible to have several instances of tracers. Each of those instances will have a
|
||||
* separate value in a static field and {@code io.undertow.server.HttpServerExchange} will treat
|
||||
* them as different keys then.
|
||||
*
|
||||
* <p>That is why this class exists and resides in a separate package. This package is treated in a
|
||||
* special way and is always loaded by bootstrap classloader. This makes sure that this class is
|
||||
* available to all tracers from every classloader.
|
||||
*
|
||||
* <p>But at the same time, being loaded by bootstrap classloader, this class itself cannot initiate
|
||||
* the loading of {@code io.undertow.util.AttachmentKey} class. Class has to be loaded by <i>any</i>
|
||||
* classloader that has it, e.g. by the classloader of a Tracer that uses this key holder. After
|
||||
* that, <i>all</i> Tracers, loaded by all classloaders, will be able to use exactly the same sole
|
||||
* instance of the key.
|
||||
*/
|
||||
// TODO allow instrumentation to have their own classes that should go to bootstrap classloader
|
||||
public final class KeyHolder {
|
||||
public static final ConcurrentMap<Class<?>, Object> contextKeys = new ConcurrentHashMap<>();
|
||||
|
||||
private KeyHolder() {}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.bootstrap.undertow;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.ContextKey;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/** Helper container for keeping track of request processing state in undertow. */
|
||||
public final class UndertowActiveHandlers {
|
||||
private static final ContextKey<AtomicInteger> CONTEXT_KEY =
|
||||
ContextKey.named("opentelemetry-undertow-active-handlers");
|
||||
|
||||
private UndertowActiveHandlers() {}
|
||||
|
||||
/**
|
||||
* Attach to context.
|
||||
*
|
||||
* @param context server context
|
||||
* @param initialValue initial value for counter
|
||||
* @return new context
|
||||
*/
|
||||
public static Context init(Context context, int initialValue) {
|
||||
return context.with(CONTEXT_KEY, new AtomicInteger(initialValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment counter.
|
||||
*
|
||||
* @param context server context
|
||||
*/
|
||||
public static void increment(Context context) {
|
||||
context.get(CONTEXT_KEY).incrementAndGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement counter.
|
||||
*
|
||||
* @param context server context
|
||||
* @return value of counter after decrementing it
|
||||
*/
|
||||
public static int decrementAndGet(Context context) {
|
||||
return context.get(CONTEXT_KEY).decrementAndGet();
|
||||
}
|
||||
}
|
||||
|
|
@ -13,4 +13,6 @@ muzzle {
|
|||
|
||||
dependencies {
|
||||
library("io.undertow:undertow-core:2.0.0.Final")
|
||||
|
||||
compileOnly(project(":instrumentation:undertow-1.4:bootstrap"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import io.opentelemetry.context.propagation.TextMapGetter;
|
|||
import io.opentelemetry.instrumentation.api.servlet.AppServerBridge;
|
||||
import io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming;
|
||||
import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.undertow.KeyHolder;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.undertow.UndertowActiveHandlers;
|
||||
import io.opentelemetry.javaagent.bootstrap.undertow.KeyHolder;
|
||||
import io.opentelemetry.javaagent.bootstrap.undertow.UndertowActiveHandlers;
|
||||
import io.undertow.server.DefaultResponseListener;
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.util.AttachmentKey;
|
||||
|
|
|
|||
|
|
@ -115,7 +115,9 @@ tasks {
|
|||
}
|
||||
}
|
||||
|
||||
val licenseReportDependencies by configurations.creating
|
||||
val licenseReportDependencies by configurations.creating {
|
||||
extendsFrom(shadowInclude)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompileOnly(project(":javaagent-bootstrap"))
|
||||
|
|
@ -126,6 +128,7 @@ dependencies {
|
|||
testImplementation("io.opentracing.contrib.dropwizard:dropwizard-opentracing:0.2.2")
|
||||
|
||||
shadowInclude(project(":javaagent-bootstrap"))
|
||||
shadowInclude(project(":instrumentation", configuration = "bootstrap"))
|
||||
|
||||
// We only have compileOnly dependencies on these to make sure they don"t leak into POMs.
|
||||
licenseReportDependencies("com.github.ben-manes.caffeine:caffeine") {
|
||||
|
|
@ -137,10 +140,8 @@ dependencies {
|
|||
// but I couldn"t get that to work
|
||||
licenseReportDependencies(project(":javaagent-tooling"))
|
||||
licenseReportDependencies(project(":javaagent-extension-api"))
|
||||
licenseReportDependencies(project(":javaagent-bootstrap"))
|
||||
}
|
||||
|
||||
|
||||
licenseReport {
|
||||
outputDir = rootProject.file("licenses").absolutePath
|
||||
|
||||
|
|
|
|||
|
|
@ -308,6 +308,7 @@ include(":instrumentation:tomcat:tomcat-7.0:javaagent")
|
|||
include(":instrumentation:tomcat:tomcat-10.0:javaagent")
|
||||
include(":instrumentation:tomcat:tomcat-common:javaagent")
|
||||
include(":instrumentation:twilio-6.6:javaagent")
|
||||
include(":instrumentation:undertow-1.4:bootstrap")
|
||||
include(":instrumentation:undertow-1.4:javaagent")
|
||||
include(":instrumentation:vaadin-14.2:javaagent")
|
||||
include(":instrumentation:vaadin-14.2:testing")
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ tasks {
|
|||
dependencies {
|
||||
// Dependencies to include without obfuscation.
|
||||
shadowInclude(project(":javaagent-bootstrap"))
|
||||
shadowInclude(project(":instrumentation", configuration = "bootstrap"))
|
||||
|
||||
testImplementation(project(":testing-common"))
|
||||
testImplementation("io.opentelemetry:opentelemetry-api")
|
||||
|
|
|
|||
Loading…
Reference in New Issue