From b4326d91ac23609968fbc32eb65abba94f331f1f Mon Sep 17 00:00:00 2001 From: Pavol Loffay Date: Fri, 13 Nov 2020 20:21:40 +0100 Subject: [PATCH] Add Bytebuddy agent builder customizer SPI (#1613) --- javaagent-spi/javaagent-spi.gradle | 1 + .../spi/ByteBuddyAgentCustomizer.java | 30 +++++++++++++++++++ .../javaagent/tooling/AgentInstaller.java | 17 +++++++++++ 3 files changed, 48 insertions(+) create mode 100644 javaagent-spi/src/main/java/io/opentelemetry/javaagent/spi/ByteBuddyAgentCustomizer.java diff --git a/javaagent-spi/javaagent-spi.gradle b/javaagent-spi/javaagent-spi.gradle index 1944baca5e..b9af4093f7 100644 --- a/javaagent-spi/javaagent-spi.gradle +++ b/javaagent-spi/javaagent-spi.gradle @@ -5,4 +5,5 @@ apply from: "$rootDir/gradle/publish.gradle" dependencies { compileOnly deps.opentelemetrySdk + compileOnly deps.bytebuddy } \ No newline at end of file diff --git a/javaagent-spi/src/main/java/io/opentelemetry/javaagent/spi/ByteBuddyAgentCustomizer.java b/javaagent-spi/src/main/java/io/opentelemetry/javaagent/spi/ByteBuddyAgentCustomizer.java new file mode 100644 index 0000000000..94f423d049 --- /dev/null +++ b/javaagent-spi/src/main/java/io/opentelemetry/javaagent/spi/ByteBuddyAgentCustomizer.java @@ -0,0 +1,30 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.spi; + +import java.lang.instrument.Instrumentation; +import net.bytebuddy.agent.builder.AgentBuilder; + +/** + * {@link ByteBuddyAgentCustomizer} customizes ByteBuddy agent builder right before the agent is + * installed - {@link AgentBuilder#installOn(Instrumentation)}. This SPI can be used to customize + * {@link AgentBuilder} for vendor specific needs. For example install custom listeners or exclude + * classes. Use this SPI carefully because it can change {@link net.bytebuddy.ByteBuddy} behaviour. + * + *

This is a service provider interface that requires implementations to be registered in {@code + * META-INF/services} folder. + */ +public interface ByteBuddyAgentCustomizer { + + /** + * Customize ByteBuddy agent builder before {@link AgentBuilder#installOn(Instrumentation)} is + * called. + * + * @param agentBuilder ByteBuddy agent from {@code AgentInstaller}. + * @return customized agent builder. + */ + AgentBuilder customize(AgentBuilder agentBuilder); +} diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java index 38a8a0f2fb..49c2ba2f9a 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java @@ -18,6 +18,7 @@ import io.opentelemetry.instrumentation.api.internal.BootstrapPackagePrefixesHol import io.opentelemetry.javaagent.instrumentation.api.OpenTelemetrySdkAccess; import io.opentelemetry.javaagent.instrumentation.api.SafeServiceLoader; import io.opentelemetry.javaagent.spi.BootstrapPackagesProvider; +import io.opentelemetry.javaagent.spi.ByteBuddyAgentCustomizer; import io.opentelemetry.javaagent.tooling.config.ConfigInitializer; import io.opentelemetry.javaagent.tooling.context.FieldBackedProvider; import io.opentelemetry.sdk.OpenTelemetrySdk; @@ -29,6 +30,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.ServiceLoader; import java.util.stream.Collectors; import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.agent.builder.ResettableClassFileTransformer; @@ -156,10 +158,25 @@ public class AgentInstaller { } } + agentBuilder = customizeByteBuddyAgent(agentBuilder); log.debug("Installed {} instrumenter(s)", numInstrumenters); return agentBuilder.installOn(inst); } + private static AgentBuilder customizeByteBuddyAgent(AgentBuilder agentBuilder) { + Iterable agentCustomizers = loadByteBuddyAgentCustomizers(); + for (ByteBuddyAgentCustomizer agentCustomizer : agentCustomizers) { + log.debug("Applying agent builder customizer {}", agentCustomizer.getClass().getName()); + agentBuilder = agentCustomizer.customize(agentBuilder); + } + return agentBuilder; + } + + private static Iterable loadByteBuddyAgentCustomizers() { + return ServiceLoader.load( + ByteBuddyAgentCustomizer.class, AgentInstaller.class.getClassLoader()); + } + private static List loadInstrumentationModules() { return SafeServiceLoader.load( InstrumentationModule.class, AgentInstaller.class.getClassLoader())