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) {
|
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
|
// 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.
|
// instrumentation so Gradle doesn't merge projects with same name due to a bug in Gradle.
|
||||||
// https://github.com/gradle/gradle/issues/847
|
// https://github.com/gradle/gradle/issues/847
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ plugins {
|
||||||
id("otel.java-conventions")
|
id("otel.java-conventions")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val bootstrap by configurations.creating
|
||||||
|
|
||||||
val instrumentationProjectTest = tasks.named("test")
|
val instrumentationProjectTest = tasks.named("test")
|
||||||
val instrumentationProjectDependencies = dependencies
|
val instrumentationProjectDependencies = dependencies
|
||||||
|
|
||||||
|
|
@ -15,6 +17,12 @@ subprojects {
|
||||||
instrumentationProjectTest.configure {
|
instrumentationProjectTest.configure {
|
||||||
dependsOn(subProj.tasks.named("test"))
|
dependsOn(subProj.tasks.named("test"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subProj.name == "bootstrap") {
|
||||||
|
instrumentationProjectDependencies.run {
|
||||||
|
add(bootstrap.name, project(subProj.path))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins.withId("otel.javaagent-instrumentation") {
|
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 {
|
dependencies {
|
||||||
library("io.undertow:undertow-core:2.0.0.Final")
|
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.AppServerBridge;
|
||||||
import io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming;
|
import io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming;
|
||||||
import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer;
|
import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.undertow.KeyHolder;
|
import io.opentelemetry.javaagent.bootstrap.undertow.KeyHolder;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.undertow.UndertowActiveHandlers;
|
import io.opentelemetry.javaagent.bootstrap.undertow.UndertowActiveHandlers;
|
||||||
import io.undertow.server.DefaultResponseListener;
|
import io.undertow.server.DefaultResponseListener;
|
||||||
import io.undertow.server.HttpServerExchange;
|
import io.undertow.server.HttpServerExchange;
|
||||||
import io.undertow.util.AttachmentKey;
|
import io.undertow.util.AttachmentKey;
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,9 @@ tasks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val licenseReportDependencies by configurations.creating
|
val licenseReportDependencies by configurations.creating {
|
||||||
|
extendsFrom(shadowInclude)
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testCompileOnly(project(":javaagent-bootstrap"))
|
testCompileOnly(project(":javaagent-bootstrap"))
|
||||||
|
|
@ -126,6 +128,7 @@ dependencies {
|
||||||
testImplementation("io.opentracing.contrib.dropwizard:dropwizard-opentracing:0.2.2")
|
testImplementation("io.opentracing.contrib.dropwizard:dropwizard-opentracing:0.2.2")
|
||||||
|
|
||||||
shadowInclude(project(":javaagent-bootstrap"))
|
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.
|
// We only have compileOnly dependencies on these to make sure they don"t leak into POMs.
|
||||||
licenseReportDependencies("com.github.ben-manes.caffeine:caffeine") {
|
licenseReportDependencies("com.github.ben-manes.caffeine:caffeine") {
|
||||||
|
|
@ -137,10 +140,8 @@ dependencies {
|
||||||
// but I couldn"t get that to work
|
// but I couldn"t get that to work
|
||||||
licenseReportDependencies(project(":javaagent-tooling"))
|
licenseReportDependencies(project(":javaagent-tooling"))
|
||||||
licenseReportDependencies(project(":javaagent-extension-api"))
|
licenseReportDependencies(project(":javaagent-extension-api"))
|
||||||
licenseReportDependencies(project(":javaagent-bootstrap"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
licenseReport {
|
licenseReport {
|
||||||
outputDir = rootProject.file("licenses").absolutePath
|
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-10.0:javaagent")
|
||||||
include(":instrumentation:tomcat:tomcat-common:javaagent")
|
include(":instrumentation:tomcat:tomcat-common:javaagent")
|
||||||
include(":instrumentation:twilio-6.6:javaagent")
|
include(":instrumentation:twilio-6.6:javaagent")
|
||||||
|
include(":instrumentation:undertow-1.4:bootstrap")
|
||||||
include(":instrumentation:undertow-1.4:javaagent")
|
include(":instrumentation:undertow-1.4:javaagent")
|
||||||
include(":instrumentation:vaadin-14.2:javaagent")
|
include(":instrumentation:vaadin-14.2:javaagent")
|
||||||
include(":instrumentation:vaadin-14.2:testing")
|
include(":instrumentation:vaadin-14.2:testing")
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ tasks {
|
||||||
dependencies {
|
dependencies {
|
||||||
// Dependencies to include without obfuscation.
|
// Dependencies to include without obfuscation.
|
||||||
shadowInclude(project(":javaagent-bootstrap"))
|
shadowInclude(project(":javaagent-bootstrap"))
|
||||||
|
shadowInclude(project(":instrumentation", configuration = "bootstrap"))
|
||||||
|
|
||||||
testImplementation(project(":testing-common"))
|
testImplementation(project(":testing-common"))
|
||||||
testImplementation("io.opentelemetry:opentelemetry-api")
|
testImplementation("io.opentelemetry:opentelemetry-api")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue