Skip to content

Commit

Permalink
\elastic#3030: Reduce dependency on elastic APM tracer in plugins but…
Browse files Browse the repository at this point in the history
… rather depend on a more general API.
  • Loading branch information
raphw committed Feb 20, 2023
1 parent 435e1d3 commit 53e70e0
Show file tree
Hide file tree
Showing 130 changed files with 1,131 additions and 729 deletions.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public ElasticApmTracerBuilder(List<ConfigurationSource> configSources) {
this.ephemeralId = UUID.randomUUID().toString();
LoggingConfiguration.init(configSources, ephemeralId);
logger = LoggerFactory.getLogger(getClass());
objectPoolFactory = new ObjectPoolFactory();
objectPoolFactory = ObjectPoolFactory.INSTANCE;
extraLifecycleListeners = new ArrayList<>();
}

Expand Down Expand Up @@ -182,7 +182,7 @@ private ElasticApmTracer build(boolean startTracer) {
reporter = new ReporterFactory().createReporter(configurationRegistry, apmServerClient, metaDataFuture, healthMetrics);
}

ElasticApmTracer tracer = new ElasticApmTracer(configurationRegistry, metricRegistry, reporter, objectPoolFactory, apmServerClient, ephemeralId, metaDataFuture);
ElasticApmTracer tracer = ElasticApmTracer.of(configurationRegistry, metricRegistry, reporter, objectPoolFactory, apmServerClient, ephemeralId, metaDataFuture);
lifecycleListeners.addAll(DependencyInjectingServiceLoader.load(LifecycleListener.class, tracer));
lifecycleListeners.addAll(extraLifecycleListeners);
tracer.init(lifecycleListeners);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
import co.elastic.apm.agent.impl.transaction.Span;
import co.elastic.apm.agent.impl.transaction.TextHeaderGetter;
import co.elastic.apm.agent.impl.transaction.Transaction;
import co.elastic.apm.agent.objectpool.ObjectPoolFactory;
import co.elastic.apm.agent.util.PrivilegedActionUtils;
import co.elastic.apm.agent.util.VersionUtils;
import org.stagemonitor.configuration.ConfigurationOptionProvider;

import javax.annotation.Nullable;
import java.io.File;
Expand All @@ -51,14 +53,23 @@ public static Tracer get() {
}

@Nullable
public static ElasticApmTracer getTracerImpl() {
public static <T extends Tracer> T get(Class<T> type) {
Tracer tracer = INSTANCE.tracer;
if (tracer instanceof ElasticApmTracer) {
return ((ElasticApmTracer) tracer);
if (type.isInstance(tracer)) {
return type.cast(tracer);
}
return null;
}

public static <T extends Tracer> T require(Class<T> type) {
return Objects.requireNonNull(get(type), "Registered tracer is not an instance of " + type.getName());
}

@Nullable
public static ElasticApmTracer getTracerImpl() {
return get(ElasticApmTracer.class);
}

public static ElasticApmTracer requireTracerImpl() {
return Objects.requireNonNull(getTracerImpl(), "Registered tracer is not an instance of ElasticApmTracer");
}
Expand Down Expand Up @@ -231,4 +242,39 @@ public boolean isRunning() {
public Span createExitChildSpan() {
return tracer.createExitChildSpan();
}

@Override
public void recycle(Transaction transaction) {
tracer.recycle(transaction);
}

@Override
public void endSpan(Span span) {
tracer.endSpan(span);
}

@Override
public void endTransaction(Transaction transaction) {
tracer.endTransaction(transaction);
}

@Override
public void endError(ErrorCapture errorCapture) {
tracer.endError(errorCapture);
}

@Override
public <T extends ConfigurationOptionProvider> T getConfig(Class<T> configuration) {
return tracer.getConfig(configuration);
}

@Override
public ObjectPoolFactory getObjectPoolFactory() {
return tracer.getObjectPoolFactory();
}

@Override
public void recycle(ErrorCapture errorCapture) {
tracer.recycle(errorCapture);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 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.
*/
package co.elastic.apm.agent.impl;

import co.elastic.apm.agent.metrics.MetricRegistry;

public interface MetricsAwareTracer extends SpanAwareTracer {

MetricRegistry getMetricRegistry();
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import co.elastic.apm.agent.impl.transaction.Span;
import co.elastic.apm.agent.impl.transaction.TextHeaderGetter;
import co.elastic.apm.agent.impl.transaction.Transaction;
import co.elastic.apm.agent.objectpool.ObjectPoolFactory;
import org.stagemonitor.configuration.ConfigurationOptionProvider;

import javax.annotation.Nullable;

Expand Down Expand Up @@ -154,4 +156,29 @@ public boolean isRunning() {
public Span createExitChildSpan() {
return null;
}

@Override
public void recycle(Transaction transaction) { }

@Override
public void recycle(ErrorCapture errorCapture) { }

@Override
public void endSpan(Span span) { }

@Override
public void endTransaction(Transaction transaction) { }

@Override
public void endError(ErrorCapture errorCapture) { }

@Override
public <T extends ConfigurationOptionProvider> T getConfig(Class<T> configuration) {
return null;
}

@Override
public ObjectPoolFactory getObjectPoolFactory() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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.
*/
package co.elastic.apm.agent.impl;

import co.elastic.apm.agent.impl.transaction.AbstractSpan;
import co.elastic.apm.agent.impl.transaction.ElasticContext;
import co.elastic.apm.agent.impl.transaction.Span;
import co.elastic.apm.agent.impl.transaction.TraceContext;

public interface SpanAwareTracer extends Tracer {

TraceContext createSpanLink();

void recycle(TraceContext context);

void recycle(Span span);

Span startSpan(AbstractSpan<?> parent, long epochMicros);

void activate(ElasticContext<?> context);

void deactivate(ElasticContext<?> context);

Scope activateInScope(ElasticContext<?> context);
}
20 changes: 18 additions & 2 deletions apm-agent-core/src/main/java/co/elastic/apm/agent/impl/Tracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import co.elastic.apm.agent.impl.transaction.Span;
import co.elastic.apm.agent.impl.transaction.TextHeaderGetter;
import co.elastic.apm.agent.impl.transaction.Transaction;
import co.elastic.apm.agent.objectpool.ObjectPoolFactory;
import org.stagemonitor.configuration.ConfigurationOptionProvider;

import javax.annotation.Nullable;

Expand Down Expand Up @@ -151,8 +153,6 @@ <C> Transaction startChildTransaction(@Nullable C headerCarrier, BinaryHeaderGet
@Nullable
Span getActiveExitSpan();

TracerState getState();

@Nullable
ServiceInfo getServiceInfoForClassLoader(@Nullable ClassLoader classLoader);

Expand All @@ -176,9 +176,25 @@ <C> Transaction startChildTransaction(@Nullable C headerCarrier, BinaryHeaderGet

boolean isRunning();

TracerState getState();

@Nullable
Span createExitChildSpan();

void recycle(Transaction transaction);

void recycle(ErrorCapture errorCapture);

void endSpan(Span span);

void endTransaction(Transaction transaction);

void endError(ErrorCapture errorCapture);

<T extends ConfigurationOptionProvider> T getConfig(Class<T> configuration);

ObjectPoolFactory getObjectPoolFactory();

/**
* An enumeration used to represent the current tracer state.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
package co.elastic.apm.agent.impl.error;

import co.elastic.apm.agent.configuration.CoreConfiguration;
import co.elastic.apm.agent.impl.ElasticApmTracer;
import co.elastic.apm.agent.impl.Tracer;
import co.elastic.apm.agent.impl.context.TransactionContext;
import co.elastic.apm.agent.impl.stacktrace.StacktraceConfiguration;
import co.elastic.apm.agent.impl.transaction.AbstractSpan;
Expand Down Expand Up @@ -52,7 +52,7 @@ public class ErrorCapture implements Recyclable {
* Any arbitrary contextual information regarding the event, captured by the agent, optionally provided by the user
*/
private final TransactionContext context = new TransactionContext();
private final ElasticApmTracer tracer;
private final Tracer tracer;
/**
* Information about the originally thrown error.
*/
Expand All @@ -71,7 +71,7 @@ public class ErrorCapture implements Recyclable {

private final StringBuilder culprit = new StringBuilder();

public ErrorCapture(ElasticApmTracer tracer) {
public ErrorCapture(Tracer tracer) {
this.tracer = tracer;
traceContext = TraceContext.with128BitId(this.tracer);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@

import co.elastic.apm.agent.collections.LongList;
import co.elastic.apm.agent.configuration.CoreConfiguration;
import co.elastic.apm.agent.impl.ElasticApmTracer;
import co.elastic.apm.agent.impl.Scope;
import co.elastic.apm.agent.impl.SpanAwareTracer;
import co.elastic.apm.agent.impl.context.AbstractContext;
import co.elastic.apm.agent.common.util.WildcardMatcher;
import co.elastic.apm.agent.objectpool.Recyclable;
Expand Down Expand Up @@ -56,7 +56,7 @@ public abstract class AbstractSpan<T extends AbstractSpan<T>> implements Recycla
*/
protected final StringBuilder name = new StringBuilder();
protected final boolean collectBreakdownMetrics;
protected final ElasticApmTracer tracer;
protected final SpanAwareTracer tracer;
protected final AtomicLong timestamp = new AtomicLong();
protected final AtomicLong endTimestamp = new AtomicLong();

Expand Down Expand Up @@ -210,7 +210,7 @@ public long getDuration() {
}
}

public AbstractSpan(ElasticApmTracer tracer) {
public AbstractSpan(SpanAwareTracer tracer) {
this.tracer = tracer;
traceContext = TraceContext.with64BitId(this.tracer);
boolean selfTimeCollectionEnabled = !WildcardMatcher.isAnyMatch(tracer.getConfig(ReporterConfiguration.class).getDisableMetrics(), "span.self_time");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* 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.
*/
package co.elastic.apm.agent.impl.transaction;

import co.elastic.apm.agent.impl.MetricsAwareTracer;
import co.elastic.apm.agent.metrics.Labels;
import co.elastic.apm.agent.metrics.MetricRegistry;
import co.elastic.apm.agent.metrics.Timer;
import co.elastic.apm.agent.util.KeyListConcurrentHashMap;

import java.util.List;

public class MetricsAwareTransaction extends Transaction {

private static final ThreadLocal<Labels.Mutable> labelsThreadLocal = new ThreadLocal<Labels.Mutable>() {
@Override
protected Labels.Mutable initialValue() {
return Labels.Mutable.of();
}
};

public MetricsAwareTransaction(MetricsAwareTracer tracer) {
super(tracer);
}

protected void trackMetrics() {
try {
phaser.readerLock();
phaser.flipPhase();
// timers are guaranteed to be stable now
// - no concurrent updates possible as finished is true
// - no other thread is running the incrementTimer method,
// as flipPhase only returns when all threads have exited that method

final String type = getType();
if (type == null) {
return;
}
final Labels.Mutable labels = labelsThreadLocal.get();
labels.resetState();
labels.serviceName(getTraceContext().getServiceName())
.serviceVersion(getTraceContext().getServiceVersion())
.transactionName(name)
.transactionType(type); // TODO:
final MetricRegistry metricRegistry = ((MetricsAwareTracer) tracer).getMetricRegistry();
long criticalValueAtEnter = metricRegistry.writerCriticalSectionEnter();
try {
if (collectBreakdownMetrics) {
List<String> types = timerBySpanTypeAndSubtype.keyList();
for (int i = 0; i < types.size(); i++) {
String spanType = types.get(i);
KeyListConcurrentHashMap<String, Timer> timerBySubtype = timerBySpanTypeAndSubtype.get(spanType);
List<String> subtypes = timerBySubtype.keyList();
for (int j = 0; j < subtypes.size(); j++) {
String subtype = subtypes.get(j);
final Timer timer = timerBySubtype.get(subtype);
if (timer.getCount() > 0) {
if (subtype.equals("")) {
subtype = null;
}
labels.spanType(spanType).spanSubType(subtype);
metricRegistry.updateTimer("span.self_time", labels, timer.getTotalTimeUs(), timer.getCount());
timer.resetState();
}
}
}
}
} finally {
metricRegistry.writerCriticalSectionExit(criticalValueAtEnter);
}
} finally {
phaser.readerUnlock();
}
}
}
Loading

0 comments on commit 53e70e0

Please sign in to comment.