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

Move global tracer and substitute agent-core types with API types where this is trivially possible. #3054

Merged
merged 17 commits into from
Mar 28, 2023
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
1 change: 0 additions & 1 deletion CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ endif::[]
////

=== Unreleased
* Introduce *apm-agent-tracer* module that contains a minimal, zero-dependency `Tracer` API. - {pull}3043[#3043]

[[release-notes-1.37.0]]
==== 1.37.0 - YYYY/MM/DD
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
import co.elastic.apm.agent.configuration.CoreConfiguration;
import co.elastic.apm.agent.impl.ElasticApmTracer;
import co.elastic.apm.agent.impl.ElasticApmTracerBuilder;
import co.elastic.apm.agent.impl.GlobalTracer;
import co.elastic.apm.agent.impl.Tracer;
import co.elastic.apm.agent.tracer.GlobalTracer;
import co.elastic.apm.agent.logging.ApmServerLogAppender;
import co.elastic.apm.agent.matcher.MethodMatcher;
import co.elastic.apm.agent.sdk.ElasticApmInstrumentation;
Expand Down Expand Up @@ -179,7 +180,7 @@ private static void initInstrumentation(ElasticApmTracer tracer, Instrumentation
}

@Nonnull
private static Iterable<ElasticApmInstrumentation> loadInstrumentations(ElasticApmTracer tracer) {
private static Iterable<ElasticApmInstrumentation> loadInstrumentations(Tracer tracer) {
List<ClassLoader> pluginClassLoaders = new ArrayList<>();
pluginClassLoaders.add(PrivilegedActionUtils.getClassLoader(ElasticApmAgent.class));
pluginClassLoaders.addAll(createExternalPluginClassLoaders(tracer.getConfig(CoreConfiguration.class).getPluginsDir()));
Expand Down Expand Up @@ -308,7 +309,7 @@ public void onChange(ConfigurationOption configurationOption, Object oldValue, O
}

public static synchronized Future<?> reInitInstrumentation() {
final ElasticApmTracer tracer = GlobalTracer.requireTracerImpl();
final Tracer tracer = TracerAwareInstrumentation.tracer.require(Tracer.class);
if (instrumentation == null) {
throw new IllegalStateException("Can't re-init agent before it has been initialized");
}
Expand Down Expand Up @@ -340,7 +341,7 @@ public static boolean openModule(Class<?> classFromTargetModule, ClassLoader ope
static synchronized void doReInitInstrumentation(Iterable<ElasticApmInstrumentation> instrumentations) {
Logger logger = getLogger();
logger.info("Re initializing instrumentation");
AgentBuilder agentBuilder = initAgentBuilder(GlobalTracer.requireTracerImpl(), instrumentation, instrumentations, logger, AgentBuilder.DescriptionStrategy.Default.POOL_ONLY, false);
AgentBuilder agentBuilder = initAgentBuilder(GlobalTracer.get().require(ElasticApmTracer.class), instrumentation, instrumentations, logger, AgentBuilder.DescriptionStrategy.Default.POOL_ONLY, false);

resettableClassFileTransformer = agentBuilder.patchOn(instrumentation, resettableClassFileTransformer);
}
Expand Down Expand Up @@ -457,7 +458,7 @@ public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDesc
private static Logger getLogger() {
if (logger == null) {
// lazily init logger to allow the tracer builder to init the logging config first
GlobalTracer.requireTracerImpl();
GlobalTracer.get().require(ElasticApmTracer.class);
logger = LoggerFactory.getLogger(ElasticApmAgent.class);
}
// re-using an existing logger avoids running into a JVM bug that leads to a segfault
Expand Down Expand Up @@ -646,7 +647,7 @@ public static synchronized void reset() {
if (instrumentation == null) {
return;
}
GlobalTracer.get().stop();
GlobalTracer.get().require(Tracer.class).stop();
GlobalTracer.setNoop();
Exception exception = null;
if (resettableClassFileTransformer != null) {
Expand Down Expand Up @@ -788,7 +789,7 @@ public static void ensureInstrumented(final Class<?> classToInstrument,

if (!appliedInstrumentations.contains(instrumentationClasses)) {
synchronized (ElasticApmAgent.class) {
final ElasticApmTracer tracer = GlobalTracer.requireTracerImpl();
final ElasticApmTracer tracer = GlobalTracer.get().require(ElasticApmTracer.class);
if (instrumentation == null) {
throw new IllegalStateException("Agent is not initialized");
}
Expand Down Expand Up @@ -896,7 +897,11 @@ private static ElasticApmInstrumentation tryInstantiate(Class<? extends ElasticA
Constructor<? extends ElasticApmInstrumentation> constructor = null;
try {
if (withTracer) {
constructor = instrumentation.getConstructor(ElasticApmTracer.class);
try {
constructor = instrumentation.getConstructor(ElasticApmTracer.class);
} catch (NoSuchMethodException ignored) {
constructor = instrumentation.getConstructor(co.elastic.apm.agent.tracer.Tracer.class);
}
} else {
constructor = instrumentation.getConstructor();
}
Expand All @@ -908,7 +913,7 @@ private static ElasticApmInstrumentation tryInstantiate(Class<? extends ElasticA
if (constructor != null) {
try {
if (withTracer) {
instance = constructor.newInstance(GlobalTracer.requireTracerImpl());
instance = constructor.newInstance(GlobalTracer.get().require(ElasticApmTracer.class));
} else {
instance = constructor.newInstance();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@
*/
package co.elastic.apm.agent.bci;

import co.elastic.apm.agent.impl.ElasticApmTracer;
import co.elastic.apm.agent.impl.GlobalTracer;
import co.elastic.apm.agent.impl.Tracer;
import co.elastic.apm.agent.tracer.GlobalTracer;
import co.elastic.apm.agent.sdk.ElasticApmInstrumentation;
import co.elastic.apm.agent.tracer.Tracer;

/**
* The constructor can optionally have a {@link ElasticApmTracer} parameter.
* The constructor can optionally have a {@link Tracer} parameter.
*/
public abstract class TracerAwareInstrumentation extends ElasticApmInstrumentation {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/
package co.elastic.apm.agent.collections;

import co.elastic.apm.agent.impl.transaction.AbstractSpan;
import co.elastic.apm.agent.tracer.AbstractSpan;

import javax.annotation.Nullable;
import java.util.Iterator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
*/
package co.elastic.apm.agent.collections;

import co.elastic.apm.agent.impl.transaction.AbstractSpan;
import co.elastic.apm.agent.sdk.weakconcurrent.DetachedThreadLocal;
import co.elastic.apm.agent.sdk.weakconcurrent.WeakConcurrent;
import co.elastic.apm.agent.sdk.weakconcurrent.WeakMap;
import co.elastic.apm.agent.sdk.weakconcurrent.WeakSet;
import co.elastic.apm.agent.tracer.AbstractSpan;
import com.blogspot.mydailyjava.weaklockfree.AbstractWeakConcurrentMap;
import com.blogspot.mydailyjava.weaklockfree.WeakConcurrentSet;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,21 @@
import co.elastic.apm.agent.sdk.logging.LoggerFactory;
import co.elastic.apm.agent.sdk.weakconcurrent.WeakConcurrent;
import co.elastic.apm.agent.sdk.weakconcurrent.WeakMap;
import co.elastic.apm.agent.tracer.GlobalTracer;
import co.elastic.apm.agent.util.DependencyInjectingServiceLoader;
import co.elastic.apm.agent.util.ExecutorUtils;
import co.elastic.apm.agent.tracer.Scope;
import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderGetter;
import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter;
import co.elastic.apm.agent.util.PrivilegedActionUtils;
import co.elastic.apm.agent.util.VersionUtils;
import org.stagemonitor.configuration.ConfigurationOption;
import org.stagemonitor.configuration.ConfigurationOptionProvider;
import org.stagemonitor.configuration.ConfigurationRegistry;

import javax.annotation.Nullable;
import java.io.Closeable;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand All @@ -77,6 +81,8 @@ public class ElasticApmTracer implements Tracer {

private static final WeakMap<ClassLoader, ServiceInfo> serviceInfoByClassLoader = WeakConcurrent.buildMap();

private static volatile boolean classloaderCheckOk = false;

private final ConfigurationRegistry configurationRegistry;
private final StacktraceConfiguration stacktraceConfiguration;
private final ApmServerClient apmServerClient;
Expand Down Expand Up @@ -117,6 +123,49 @@ protected ActiveStack initialValue() {
private final String ephemeralId;
private final MetaDataFuture metaDataFuture;

static {
checkClassloader();
}

private static void checkClassloader() {
ClassLoader cl = PrivilegedActionUtils.getClassLoader(GlobalTracer.class);

// agent currently loaded in the bootstrap CL, which is the current correct location
if (cl == null) {
return;
}

if (classloaderCheckOk) {
return;
}

String agentLocation = PrivilegedActionUtils.getProtectionDomain(GlobalTracer.class).getCodeSource().getLocation().getFile();
if (!agentLocation.endsWith(".jar")) {
// agent is not packaged, thus we assume running tests
classloaderCheckOk = true;
return;
}

String premainClass = VersionUtils.getManifestEntry(new File(agentLocation), "Premain-Class");
if (null == premainClass) {
// packaged within a .jar, but not within an agent jar, thus we assume it's still for testing
classloaderCheckOk = true;
return;
}

if (premainClass.startsWith("co.elastic.apm.agent")) {
// premain class will only be present when packaged as an agent jar
classloaderCheckOk = true;
return;
}

// A packaged agent class has been loaded outside of bootstrap classloader, we are not in the context of
// unit/integration tests, that's likely a setup issue where the agent jar has been added to application
// classpath.
throw new IllegalStateException(String.format("Agent setup error: agent jar file \"%s\" likely referenced in JVM or application classpath", agentLocation));

}

ElasticApmTracer(ConfigurationRegistry configurationRegistry, MetricRegistry metricRegistry, Reporter reporter, ObjectPoolFactory poolFactory,
ApmServerClient apmServerClient, final String ephemeralId, MetaDataFuture metaDataFuture) {
this.metricRegistry = metricRegistry;
Expand Down
Loading