Skip to content

Commit

Permalink
Add GlobalTracer
Browse files Browse the repository at this point in the history
bye bye tracer null checks
  • Loading branch information
felixbarny committed Jul 2, 2020
1 parent 55d987b commit 0e20bf0
Show file tree
Hide file tree
Showing 125 changed files with 1,077 additions and 749 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@
import co.elastic.apm.agent.bci.methodmatching.TraceMethodInstrumentation;
import co.elastic.apm.agent.collections.WeakMapSupplier;
import co.elastic.apm.agent.configuration.CoreConfiguration;
import co.elastic.apm.agent.impl.ElasticApmTracer;
import co.elastic.apm.agent.impl.GlobalTracer;
import co.elastic.apm.agent.impl.ElasticApmTracerBuilder;
import co.elastic.apm.agent.impl.ElasticApmTracer;
import co.elastic.apm.agent.util.DependencyInjectingServiceLoader;
import co.elastic.apm.agent.util.ExecutorUtils;
import co.elastic.apm.agent.util.ThreadUtils;
Expand Down Expand Up @@ -84,7 +85,6 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import static co.elastic.apm.agent.bci.ElasticApmInstrumentation.tracer;
import static co.elastic.apm.agent.bci.bytebuddy.ClassLoaderNameMatcher.classLoaderWithName;
import static co.elastic.apm.agent.bci.bytebuddy.ClassLoaderNameMatcher.isReflectionClassLoader;
import static co.elastic.apm.agent.bci.bytebuddy.CustomElementMatchers.anyMatch;
Expand Down Expand Up @@ -174,7 +174,7 @@ public void run() {
logger.warn("Instrumentation has already been initialized");
return;
}
ElasticApmInstrumentation.staticInit(tracer);
GlobalTracer.set(tracer);
// POOL_ONLY because we don't want to cause eager linking on startup as the class path may not be complete yet
AgentBuilder agentBuilder = initAgentBuilder(tracer, instrumentation, instrumentations, logger, AgentBuilder.DescriptionStrategy.Default.POOL_ONLY, premain);
resettableClassFileTransformer = agentBuilder.installOn(ElasticApmAgent.instrumentation);
Expand All @@ -190,7 +190,7 @@ public void onChange(ConfigurationOption configurationOption, Object oldValue, O
}

public static synchronized Future<?> reInitInstrumentation() {
final ElasticApmTracer tracer = ElasticApmInstrumentation.tracer;
final ElasticApmTracer tracer = GlobalTracer.getTracerImpl();
if (tracer == null || instrumentation == null) {
throw new IllegalStateException("Can't re-init agent before it has been initialized");
}
Expand All @@ -199,15 +199,15 @@ public static synchronized Future<?> reInitInstrumentation() {
return executor.submit(new Runnable() {
@Override
public void run() {
doReInitInstrumentation(loadInstrumentations(tracer));
doReInitInstrumentation(loadInstrumentations(tracer), tracer);
}
});
} finally {
executor.shutdown();
}
}

static synchronized void doReInitInstrumentation(Iterable<ElasticApmInstrumentation> instrumentations) {
static synchronized void doReInitInstrumentation(Iterable<ElasticApmInstrumentation> instrumentations, ElasticApmTracer tracer) {
final Logger logger = LoggerFactory.getLogger(ElasticApmAgent.class);
logger.info("Re initializing instrumentation");
AgentBuilder agentBuilder = initAgentBuilder(tracer, instrumentation, instrumentations, logger, AgentBuilder.DescriptionStrategy.Default.POOL_ONLY, false);
Expand Down Expand Up @@ -305,7 +305,7 @@ public boolean matches(TypeDescription typeDescription, ClassLoader classLoader,
}
})
.transform(new PatchBytecodeVersionTo51Transformer())
.transform(getTransformer(tracer, instrumentation, logger, methodMatcher))
.transform(getTransformer(instrumentation, logger, methodMatcher))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
Expand All @@ -315,7 +315,7 @@ public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDesc
});
}

private static AgentBuilder.Transformer.ForAdvice getTransformer(final ElasticApmTracer tracer, final ElasticApmInstrumentation instrumentation, final Logger logger, final ElementMatcher<? super MethodDescription> methodMatcher) {
private static AgentBuilder.Transformer.ForAdvice getTransformer(final ElasticApmInstrumentation instrumentation, final Logger logger, final ElementMatcher<? super MethodDescription> methodMatcher) {
Advice.WithCustomMapping withCustomMapping = Advice
.withCustomMapping()
.with(new AssignToPostProcessorFactory())
Expand Down Expand Up @@ -574,7 +574,7 @@ public static void ensureInstrumented(Class<?> classToInstrument, Collection<Cla

if (!appliedInstrumentations.contains(instrumentationClasses)) {
synchronized (ElasticApmAgent.class) {
ElasticApmTracer tracer = ElasticApmInstrumentation.tracer;
ElasticApmTracer tracer = GlobalTracer.getTracerImpl();
if (tracer == null || instrumentation == null) {
throw new IllegalStateException("Agent is not initialized");
}
Expand Down Expand Up @@ -666,7 +666,7 @@ private static ElasticApmInstrumentation tryInstantiate(Class<? extends ElasticA
if (constructor != null) {
try {
if (withTracer) {
instance = constructor.newInstance(ElasticApmInstrumentation.tracer);
instance = constructor.newInstance(GlobalTracer.getTracerImpl());
} else {
instance = constructor.newInstance();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
*/
package co.elastic.apm.agent.bci;

import co.elastic.apm.agent.impl.ElasticApmTracer;
import co.elastic.apm.agent.impl.transaction.AbstractSpan;
import co.elastic.apm.agent.impl.transaction.Span;
import co.elastic.apm.agent.threadlocal.GlobalThreadLocal;
import net.bytebuddy.asm.Advice;
Expand All @@ -48,73 +46,8 @@
* The actual instrumentation of the matched methods is performed by static methods within this class,
* which are annotated by {@link net.bytebuddy.asm.Advice.OnMethodEnter} or {@link net.bytebuddy.asm.Advice.OnMethodExit}.
* </p>
* <p>
* The constructor can optionally have a {@link ElasticApmTracer} parameter.
* </p>
*/
public abstract class ElasticApmInstrumentation {

@Nullable
@VisibleForAdvice
public static ElasticApmTracer tracer;

/**
* Initializes the advice with the {@link ElasticApmTracer}
* <p>
* This enables tests to register a custom instance with a {@link co.elastic.apm.agent.impl.ElasticApmTracerBuilder#configurationRegistry}
* and {@link co.elastic.apm.agent.impl.ElasticApmTracerBuilder#reporter} which is specific to a particular test or test class.
* </p>
*
* @param tracer the tracer to use for this advice.
*/
static void staticInit(ElasticApmTracer tracer) {
// allow re-init with a different tracer
ElasticApmInstrumentation.tracer = tracer;
}

@Nullable
@VisibleForAdvice
public static AbstractSpan<?> getActive() {
if (tracer != null) {
return tracer.getActive();
}
return null;
}

@Nullable
@VisibleForAdvice
public static Span getActiveSpan() {
if (tracer != null) {
final AbstractSpan<?> active = tracer.getActive();
if (active instanceof Span) {
return (Span) active;
}
}
return null;
}


@Nullable
@VisibleForAdvice
public static Span getActiveExitSpan() {
final Span span = getActiveSpan();
if (span != null && span.isExit()) {
return span;
}
return null;
}

@Nullable
@VisibleForAdvice
public static Span createExitSpan() {
final AbstractSpan<?> activeSpan = getActive();
if (activeSpan == null || activeSpan.isExit()) {
return null;
}

return activeSpan.createExitSpan();
}

/**
* Pre-select candidates solely based on the class name for the slower {@link #getTypeMatcher()},
* at the expense of potential false negative matches.
Expand Down Expand Up @@ -167,7 +100,6 @@ public Class<?> getAdviceClass() {
return getClass();
}


/**
* Return {@code true},
* if this instrumentation should even be applied when
Expand Down Expand Up @@ -218,8 +150,7 @@ public void onTypeMatch(TypeDescription typeDescription, ClassLoader classLoader
* <li>
* Both the return type and the arguments of advice methods must not contain types from the agent.
* If you'd like to return a {@link Span} from an advice, for example, return an {@link Object} instead.
* When using an {@link net.bytebuddy.asm.Advice.Enter} argument on the
* {@linkplain net.bytebuddy.asm.Advice.OnMethodExit exit advice},
* When using an {@link Advice.Enter} argument on the {@linkplain Advice.OnMethodExit exit advice},
* that argument also has to be of type {@link Object} and you have to cast it within the method body.
* The reason is that the return value will become a local variable in the instrumented method.
* Due to OSGi, those methods may not have access to agent types.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
package co.elastic.apm.agent.bci;

import co.elastic.apm.agent.impl.Tracer;
import co.elastic.apm.agent.impl.ElasticApmTracer;
import com.blogspot.mydailyjava.weaklockfree.WeakConcurrentMap;
import net.bytebuddy.description.type.TypeDescription;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

import co.elastic.apm.agent.bci.bytebuddy.MatcherTimer;
import co.elastic.apm.agent.context.AbstractLifecycleListener;
import co.elastic.apm.agent.impl.ElasticApmTracer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*-
* #%L
* Elastic APM Java agent
* %%
* Copyright (C) 2018 - 2020 Elastic and contributors
* %%
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* #L%
*/
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;

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

@VisibleForAdvice
public static final Tracer tracer = GlobalTracer.get();

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
*/
package co.elastic.apm.agent.bci.methodmatching;

import co.elastic.apm.agent.bci.ElasticApmInstrumentation;
import co.elastic.apm.agent.bci.TracerAwareElasticApmInstrumentation;
import co.elastic.apm.agent.bci.bytebuddy.SimpleMethodSignatureOffsetMappingFactory;
import co.elastic.apm.agent.configuration.CoreConfiguration;
import co.elastic.apm.agent.impl.ElasticApmTracer;
Expand All @@ -51,38 +51,37 @@
import static net.bytebuddy.matcher.ElementMatchers.isSynthetic;
import static net.bytebuddy.matcher.ElementMatchers.isTypeInitializer;
import static net.bytebuddy.matcher.ElementMatchers.nameContains;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;

public class TraceMethodInstrumentation extends ElasticApmInstrumentation {
public class TraceMethodInstrumentation extends TracerAwareElasticApmInstrumentation {

public static long traceMethodThresholdMicros;

protected final MethodMatcher methodMatcher;
private final CoreConfiguration config;

public TraceMethodInstrumentation(ElasticApmTracer tracer, MethodMatcher methodMatcher) {
this.methodMatcher = methodMatcher;
traceMethodThresholdMicros = tracer.getConfig(CoreConfiguration.class).getTraceMethodsDurationThreshold().getMillis() * 1000;
config = tracer.getConfig(CoreConfiguration.class);
traceMethodThresholdMicros = config.getTraceMethodsDurationThreshold().getMillis() * 1000;
}

@Advice.OnMethodEnter(suppress = Throwable.class)
public static void onMethodEnter(@Advice.Origin Class<?> clazz,
@SimpleMethodSignatureOffsetMappingFactory.SimpleMethodSignature String signature,
@Advice.Local("span") AbstractSpan<?> span) {
if (tracer != null) {
final AbstractSpan<?> parent = tracer.getActive();
if (parent == null) {
span = tracer.startRootTransaction(clazz.getClassLoader());
if (span != null) {
span.withName(signature).activate();
}
} else if (parent.isSampled()) {
span = parent.createSpan()
.withName(signature)
.activate();
final AbstractSpan<?> parent = tracer.getActive();
if (parent == null) {
span = tracer.startRootTransaction(clazz.getClassLoader());
if (span != null) {
span.withName(signature).activate();
}
} else if (parent.isSampled()) {
span = parent.createSpan()
.withName(signature)
.activate();
}
}

Expand Down Expand Up @@ -118,9 +117,8 @@ public ElementMatcher<? super TypeDescription> getTypeMatcher() {
public ElementMatcher<? super MethodDescription> getMethodMatcher() {
ElementMatcher.Junction<? super MethodDescription> matcher = matches(methodMatcher.getMethodMatcher());

final List<WildcardMatcher> methodsExcludedFromInstrumentation =
(tracer != null)? tracer.getConfig(CoreConfiguration.class).getMethodsExcludedFromInstrumentation(): null;
if (methodsExcludedFromInstrumentation != null && !methodsExcludedFromInstrumentation.isEmpty()) {
final List<WildcardMatcher> methodsExcludedFromInstrumentation = config.getMethodsExcludedFromInstrumentation();
if (!methodsExcludedFromInstrumentation.isEmpty()) {
matcher = matcher.and(not(new ElementMatcher<MethodDescription>() {
@Override
public boolean matches(MethodDescription target) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@

import co.elastic.apm.agent.impl.ElasticApmTracer;

import java.io.Closeable;

/**
* A {@link LifecycleListener} notifies about the start and stop event of the {@link ElasticApmTracer}.
* <p>
Expand Down
Loading

0 comments on commit 0e20bf0

Please sign in to comment.