Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't call Thread#setContextClassLoader() #7391

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
import io.opentelemetry.javaagent.bootstrap.AgentClassLoader;
import io.opentelemetry.javaagent.bootstrap.AgentInitializer;
import io.opentelemetry.javaagent.bootstrap.BootstrapPackagePrefixesHolder;
import io.opentelemetry.javaagent.bootstrap.ClassFileTransformerHolder;
import io.opentelemetry.javaagent.bootstrap.DefineClassHelper;
Expand Down Expand Up @@ -78,7 +77,7 @@ public class AgentInstaller {

private static final Map<String, List<Runnable>> CLASS_LOAD_CALLBACKS = new HashMap<>();

public static void installBytebuddyAgent(Instrumentation inst) {
public static void installBytebuddyAgent(Instrumentation inst, ClassLoader extensionClassLoader) {
addByteBuddyRawSetting();

Integer strictContextStressorMillis = Integer.getInteger(STRICT_CONTEXT_STRESSOR_MILLIS);
Expand All @@ -90,34 +89,37 @@ public static void installBytebuddyAgent(Instrumentation inst) {
logVersionInfo();
if (ConfigPropertiesUtil.getBoolean(JAVAAGENT_ENABLED_CONFIG, true)) {
setupUnsafe(inst);
List<AgentListener> agentListeners = loadOrdered(AgentListener.class);
installBytebuddyAgent(inst, agentListeners);
List<AgentListener> agentListeners = loadOrdered(AgentListener.class, extensionClassLoader);
installBytebuddyAgent(inst, extensionClassLoader, agentListeners);
} else {
logger.fine("Tracing is disabled, not installing instrumentations.");
}
}

private static void installBytebuddyAgent(
Instrumentation inst, Iterable<AgentListener> agentListeners) {
Instrumentation inst,
ClassLoader extensionClassLoader,
Iterable<AgentListener> agentListeners) {

WeakRefAsyncOperationEndStrategies.initialize();

EmbeddedInstrumentationProperties.setPropertiesLoader(
AgentInitializer.getExtensionsClassLoader());
EmbeddedInstrumentationProperties.setPropertiesLoader(extensionClassLoader);

setDefineClassHandler();

// If noop OpenTelemetry is enabled, autoConfiguredSdk will be null and AgentListeners are not
// called
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk = installOpenTelemetrySdk();
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
installOpenTelemetrySdk(extensionClassLoader);

ConfigProperties sdkConfig = autoConfiguredSdk.getConfig();
InstrumentationConfig.internalInitializeConfig(new ConfigPropertiesBridge(sdkConfig));
copyNecessaryConfigToSystemProperties(sdkConfig);

setBootstrapPackages(sdkConfig);
setBootstrapPackages(sdkConfig, extensionClassLoader);

for (BeforeAgentListener agentListener : loadOrdered(BeforeAgentListener.class)) {
for (BeforeAgentListener agentListener :
loadOrdered(BeforeAgentListener.class, extensionClassLoader)) {
agentListener.beforeAgent(autoConfiguredSdk);
}

Expand All @@ -140,7 +142,7 @@ private static void installBytebuddyAgent(
agentBuilder = agentBuilder.with(new ExposeAgentBootstrapListener(inst));
}

agentBuilder = configureIgnoredTypes(sdkConfig, agentBuilder);
agentBuilder = configureIgnoredTypes(sdkConfig, extensionClassLoader, agentBuilder);

if (AgentConfig.isDebugModeEnabled(sdkConfig)) {
agentBuilder =
Expand All @@ -152,7 +154,7 @@ private static void installBytebuddyAgent(
}

int numberOfLoadedExtensions = 0;
for (AgentExtension agentExtension : loadOrdered(AgentExtension.class)) {
for (AgentExtension agentExtension : loadOrdered(AgentExtension.class, extensionClassLoader)) {
if (logger.isLoggable(FINE)) {
logger.log(
FINE,
Expand Down Expand Up @@ -196,9 +198,11 @@ private static void setupUnsafe(Instrumentation inst) {
}
}

private static void setBootstrapPackages(ConfigProperties config) {
private static void setBootstrapPackages(
ConfigProperties config, ClassLoader extensionClassLoader) {
BootstrapPackagesBuilderImpl builder = new BootstrapPackagesBuilderImpl();
for (BootstrapPackagesConfigurer configurer : load(BootstrapPackagesConfigurer.class)) {
for (BootstrapPackagesConfigurer configurer :
load(BootstrapPackagesConfigurer.class, extensionClassLoader)) {
configurer.configure(builder, config);
}
BootstrapPackagePrefixesHolder.setBoostrapPackagePrefixes(builder.build());
Expand All @@ -209,9 +213,10 @@ private static void setDefineClassHandler() {
}

private static AgentBuilder configureIgnoredTypes(
ConfigProperties config, AgentBuilder agentBuilder) {
ConfigProperties config, ClassLoader extensionClassLoader, AgentBuilder agentBuilder) {
IgnoredTypesBuilderImpl builder = new IgnoredTypesBuilderImpl();
for (IgnoredTypesConfigurer configurer : loadOrdered(IgnoredTypesConfigurer.class)) {
for (IgnoredTypesConfigurer configurer :
loadOrdered(IgnoredTypesConfigurer.class, extensionClassLoader)) {
configurer.configure(builder, config);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,9 @@ public boolean delayStart() {
@Override
public void start() {
extensionClassLoader = createExtensionClassLoader(getClass().getClassLoader(), javaagentFile);
ClassLoader savedContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(extensionClassLoader);
internalStart();
} finally {
Thread.currentThread().setContextClassLoader(savedContextClassLoader);
}
}

private void internalStart() {
Iterator<LoggingCustomizer> loggingCustomizers =
ServiceLoader.load(LoggingCustomizer.class).iterator();
ServiceLoader.load(LoggingCustomizer.class, extensionClassLoader).iterator();
LoggingCustomizer loggingCustomizer;
if (loggingCustomizers.hasNext()) {
loggingCustomizer = loggingCustomizers.next();
Expand All @@ -84,7 +75,7 @@ private void internalStart() {
Throwable startupError = null;
try {
loggingCustomizer.init();
AgentInstaller.installBytebuddyAgent(instrumentation);
AgentInstaller.installBytebuddyAgent(instrumentation, extensionClassLoader);
WeakConcurrentMapCleaner.start();
} catch (Throwable t) {
// this is logged below and not rethrown to avoid logging it twice
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@

package io.opentelemetry.javaagent.tooling;

import io.opentelemetry.javaagent.bootstrap.AgentInitializer;
import io.opentelemetry.javaagent.bootstrap.OpenTelemetrySdkAccess;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder;
import io.opentelemetry.sdk.common.CompletableResultCode;
import java.util.Arrays;

Expand All @@ -21,17 +19,14 @@ public final class OpenTelemetryInstaller {
*
* @return the {@link AutoConfiguredOpenTelemetrySdk}
*/
public static AutoConfiguredOpenTelemetrySdk installOpenTelemetrySdk() {
AutoConfiguredOpenTelemetrySdkBuilder builder =
AutoConfiguredOpenTelemetrySdk.builder().setResultAsGlobal(true);

ClassLoader classLoader = AgentInitializer.getExtensionsClassLoader();
if (classLoader != null) {
// May be null in unit tests.
builder.setServiceClassLoader(classLoader);
}

AutoConfiguredOpenTelemetrySdk autoConfiguredSdk = builder.build();
public static AutoConfiguredOpenTelemetrySdk installOpenTelemetrySdk(
ClassLoader extensionClassLoader) {

AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
AutoConfiguredOpenTelemetrySdk.builder()
.setResultAsGlobal(true)
.setServiceClassLoader(extensionClassLoader)
.build();
OpenTelemetrySdk sdk = autoConfiguredSdk.getOpenTelemetrySdk();

OpenTelemetrySdkAccess.internalSetForceFlush(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ public final class SafeServiceLoader {
*/
// Because we want to catch exception per iteration
@SuppressWarnings("ForEachIterable")
public static <T> List<T> load(Class<T> serviceClass) {
public static <T> List<T> load(Class<T> serviceClass, ClassLoader classLoader) {
List<T> result = new ArrayList<>();
ServiceLoader<T> services = ServiceLoader.load(serviceClass);
ServiceLoader<T> services = ServiceLoader.load(serviceClass, classLoader);
for (Iterator<T> iterator = new SafeIterator<>(services.iterator()); iterator.hasNext(); ) {
T service = iterator.next();
if (service != null) {
Expand All @@ -43,11 +43,12 @@ public static <T> List<T> load(Class<T> serviceClass) {
}

/**
* Same as {@link #load(Class)}, but also orders the returned implementations by comparing their
* {@link Ordered#order()}.
* Same as {@link #load(Class, ClassLoader)}, but also orders the returned implementations by
* comparing their {@link Ordered#order()}.
*/
public static <T extends Ordered> List<T> loadOrdered(Class<T> serviceClass) {
List<T> result = load(serviceClass);
public static <T extends Ordered> List<T> loadOrdered(
Class<T> serviceClass, ClassLoader classLoader) {
List<T> result = load(serviceClass, classLoader);
result.sort(Comparator.comparing(Ordered::order));
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import io.opentelemetry.javaagent.bootstrap.InstrumentationHolder;
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.AgentExtension;
import io.opentelemetry.javaagent.tooling.Utils;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import java.util.logging.Logger;
import net.bytebuddy.agent.builder.AgentBuilder;
Expand All @@ -27,7 +28,8 @@ public class InstrumentationLoader implements AgentExtension {
@Override
public AgentBuilder extend(AgentBuilder agentBuilder, ConfigProperties config) {
int numberOfLoadedModules = 0;
for (InstrumentationModule instrumentationModule : loadOrdered(InstrumentationModule.class)) {
for (InstrumentationModule instrumentationModule :
loadOrdered(InstrumentationModule.class, Utils.getExtensionsClassLoader())) {
if (logger.isLoggable(FINE)) {
logger.log(
FINE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class HelperInjectionTest extends Specification {
def "helpers injected on bootstrap classloader"() {
setup:
ByteBuddyAgent.install()
AgentInstaller.installBytebuddyAgent(ByteBuddyAgent.getInstrumentation())
AgentInstaller.installBytebuddyAgent(ByteBuddyAgent.getInstrumentation(), this.class.classLoader)
String helperClassName = HelperInjectionTest.getPackage().getName() + '.HelperClass'
HelperInjector injector = new HelperInjector("test", [helperClassName], [], this.class.classLoader, ByteBuddyAgent.getInstrumentation())
URLClassLoader bootstrapChild = new URLClassLoader(new URL[0], (ClassLoader) null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class OpenTelemetryInstallerTest extends Specification {

def "should initialize GlobalOpenTelemetry"() {
when:
def otelInstaller = OpenTelemetryInstaller.installOpenTelemetrySdk()
def otelInstaller = OpenTelemetryInstaller.installOpenTelemetrySdk(OpenTelemetryInstaller.classLoader)

then:
otelInstaller != null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void fileConfigOverwritesUserPropertiesSupplier(@TempDir Path tempDir) throws IO

// when
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
OpenTelemetryInstaller.installOpenTelemetrySdk();
OpenTelemetryInstaller.installOpenTelemetrySdk(this.getClass().getClassLoader());

// then
assertThat(autoConfiguredSdk.getConfig().getString("custom.key")).isEqualTo("42");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public static AgentBuilder.PoolStrategy poolStrategy() {

private static ClassLoader getBootstrapProxy() {
Iterator<BootstrapProxyProvider> iterator =
ServiceLoader.load(BootstrapProxyProvider.class).iterator();
ServiceLoader.load(BootstrapProxyProvider.class, AgentTooling.class.getClassLoader())
.iterator();
if (iterator.hasNext()) {
BootstrapProxyProvider bootstrapProxyProvider = iterator.next();
return bootstrapProxyProvider.getBootstrapProxy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class ClassLoaderMatcher {
public static Map<String, List<Mismatch>> matchesAll(
ClassLoader classLoader, boolean injectHelpers, Set<String> excludedInstrumentationNames) {
Map<String, List<Mismatch>> result = new HashMap<>();
ServiceLoader.load(InstrumentationModule.class)
ServiceLoader.load(InstrumentationModule.class, ClassLoaderMatcher.class.getClassLoader())
.forEach(
module -> {
if (module.instrumentationNames().stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public final class ReferencesPrinter {
*/
public static void printMuzzleReferences() {
for (InstrumentationModule instrumentationModule :
ServiceLoader.load(InstrumentationModule.class)) {
ServiceLoader.load(InstrumentationModule.class, ReferencesPrinter.class.getClassLoader())) {
try {
System.out.println(instrumentationModule.getClass().getName());
for (ClassRef ref :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.opentelemetry.javaagent.extension.ignore.IgnoredTypesConfigurer;
import io.opentelemetry.javaagent.tooling.EmptyConfigProperties;
import io.opentelemetry.javaagent.tooling.SafeServiceLoader;
import io.opentelemetry.javaagent.tooling.Utils;
import io.opentelemetry.javaagent.tooling.ignore.AdditionalLibraryIgnoredTypesConfigurer;
import io.opentelemetry.javaagent.tooling.ignore.GlobalIgnoredTypesConfigurer;
import io.opentelemetry.javaagent.tooling.ignore.IgnoreAllow;
Expand Down Expand Up @@ -51,7 +52,8 @@ private static Trie<IgnoreAllow> buildAdditionalLibraryIgnores() {
private static Trie<IgnoreAllow> buildOtherConfiguredIgnores() {
IgnoredTypesBuilderImpl builder = new IgnoredTypesBuilderImpl();
for (IgnoredTypesConfigurer configurer :
SafeServiceLoader.loadOrdered(IgnoredTypesConfigurer.class)) {
SafeServiceLoader.loadOrdered(
IgnoredTypesConfigurer.class, Utils.getExtensionsClassLoader())) {
// skip built-in agent ignores
if (configurer instanceof AdditionalLibraryIgnoredTypesConfigurer
|| configurer instanceof GlobalIgnoredTypesConfigurer) {
Expand Down