diff --git a/apm-agent-builds/apm-agent/src/test/java/co/elastic/apm/agent/configuration/ConfigurationExporter.java b/apm-agent-builds/apm-agent/src/test/java/co/elastic/apm/agent/configuration/ConfigurationExporter.java index 811054c294..50687d38f2 100644 --- a/apm-agent-builds/apm-agent/src/test/java/co/elastic/apm/agent/configuration/ConfigurationExporter.java +++ b/apm-agent-builds/apm-agent/src/test/java/co/elastic/apm/agent/configuration/ConfigurationExporter.java @@ -21,6 +21,7 @@ import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.impl.Tracer; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import org.stagemonitor.configuration.ConfigurationOptionProvider; import org.stagemonitor.configuration.ConfigurationRegistry; @@ -38,7 +39,7 @@ public class ConfigurationExporter { public static void main(String[] args) throws Exception { ElasticApmTracer tracer = mock(ElasticApmTracer.class); - doReturn(tracer).when(tracer).require(ElasticApmTracer.class); + doReturn(tracer).when(tracer).require(ReportingTracer.class); doReturn(Tracer.TracerState.UNINITIALIZED).when(tracer).getState(); GlobalTracer.init(tracer); try { diff --git a/apm-agent-builds/apm-agent/src/test/java/co/elastic/apm/agent/configuration/ConfigurationExporterTest.java b/apm-agent-builds/apm-agent/src/test/java/co/elastic/apm/agent/configuration/ConfigurationExporterTest.java index 22e8534486..81800ec1de 100644 --- a/apm-agent-builds/apm-agent/src/test/java/co/elastic/apm/agent/configuration/ConfigurationExporterTest.java +++ b/apm-agent-builds/apm-agent/src/test/java/co/elastic/apm/agent/configuration/ConfigurationExporterTest.java @@ -23,6 +23,7 @@ import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.impl.Tracer; import co.elastic.apm.agent.sdk.ElasticApmInstrumentation; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import co.elastic.apm.agent.util.DependencyInjectingServiceLoader; import freemarker.template.Configuration; import freemarker.template.Template; @@ -53,6 +54,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * This is not an actual test. @@ -88,7 +90,7 @@ class ConfigurationExporterTest { void setUp() { renderedDocumentationPath = Paths.get("../../docs/configuration.asciidoc"); ElasticApmTracer tracer = mock(ElasticApmTracer.class); - doReturn(tracer).when(tracer).require(ElasticApmTracer.class); + doReturn(tracer).when(tracer).require(ReportingTracer.class); doReturn(Tracer.TracerState.UNINITIALIZED).when(tracer).getState(); GlobalTracer.init(tracer); configurationRegistry = ConfigurationRegistry.builder() diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/InstrumentationStatsLifecycleListener.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/InstrumentationStatsLifecycleListener.java index a7f096ad59..1429e79ae1 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/InstrumentationStatsLifecycleListener.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/InstrumentationStatsLifecycleListener.java @@ -19,15 +19,16 @@ package co.elastic.apm.agent.bci; import co.elastic.apm.agent.bci.bytebuddy.MatcherTimer; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.context.InitializableLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import java.util.ArrayList; import java.util.Collections; -public class InstrumentationStatsLifecycleListener extends AbstractLifecycleListener { +public class InstrumentationStatsLifecycleListener extends AbstractLifecycleListener implements InitializableLifecycleListener { private static final Logger logger = LoggerFactory.getLogger(InstrumentationStatsLifecycleListener.class); @Override diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/collections/WeakMapCleaner.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/collections/WeakMapCleaner.java index 3755d8b26b..8143045ddf 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/collections/WeakMapCleaner.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/collections/WeakMapCleaner.java @@ -18,8 +18,7 @@ */ package co.elastic.apm.agent.collections; -import co.elastic.apm.agent.context.AbstractLifecycleListener; -import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.util.ExecutorUtils; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; @@ -41,7 +40,7 @@ public WeakMapCleaner() { } @Override - public void start(ElasticApmTracer tracer) { + public void start() { scheduler.scheduleWithFixedDelay(this, 1, 1, TimeUnit.SECONDS); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/ApmServerConfigurationSource.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/ApmServerConfigurationSource.java index 662810e4b7..604bb59f52 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/ApmServerConfigurationSource.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/ApmServerConfigurationSource.java @@ -18,7 +18,7 @@ */ package co.elastic.apm.agent.configuration; -import co.elastic.apm.agent.context.LifecycleListener; +import co.elastic.apm.agent.context.InitializableLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.report.ApmServerClient; import co.elastic.apm.agent.report.serialize.DslJsonSerializer; @@ -44,7 +44,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class ApmServerConfigurationSource extends AbstractConfigurationSource implements LifecycleListener { +public class ApmServerConfigurationSource extends AbstractConfigurationSource implements InitializableLifecycleListener { // log correlation is enabled by default in Java agent, thus removing it from warnings private static final Set IGNORED_REMOTE_KEYS = Collections.singleton("enable_log_correlation"); @@ -62,6 +62,9 @@ public class ApmServerConfigurationSource extends AbstractConfigurationSource im private final byte[] buffer = new byte[4096]; private final DslJsonSerializer.Writer payloadSerializer; private final ApmServerClient apmServerClient; + + @Nullable + private ElasticApmTracer tracer; @Nullable private String etag; private volatile Map config = Collections.emptyMap(); @@ -111,12 +114,12 @@ public void reload() { } @Override - public void init(ElasticApmTracer tracer) throws Exception { - // noop + public void init(ElasticApmTracer tracer) { + this.tracer = tracer; } @Override - public void start(final ElasticApmTracer tracer) { + public void start() { threadPool = ExecutorUtils.createSingleThreadDaemonPool("remote-config-poller", 1); threadPool.execute(new Runnable() { @Override diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java index 7200f1ab4f..188949066f 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java @@ -876,6 +876,7 @@ public ConfigurationOption getServiceNameConfig() { } @Nullable + @Override public String getServiceNodeName() { String nodeName = serviceNodeName.get(); if (nodeName == null || nodeName.trim().isEmpty()) { @@ -889,6 +890,7 @@ public long getDelayTracerStartMs() { } @Nullable + @Override public String getServiceVersion() { return serviceVersion.get(); } @@ -899,6 +901,7 @@ public String getHostname() { } @Nullable + @Override public String getEnvironment() { return environment.get(); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/ServerlessConfiguration.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/ServerlessConfiguration.java index 36875fbf04..7856019607 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/ServerlessConfiguration.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/ServerlessConfiguration.java @@ -22,11 +22,16 @@ import org.stagemonitor.configuration.ConfigurationOption; import org.stagemonitor.configuration.ConfigurationOptionProvider; +import javax.annotation.Nullable; + public class ServerlessConfiguration extends ConfigurationOptionProvider implements co.elastic.apm.agent.tracer.configuration.ServerlessConfiguration { public static final String SERVERLESS_CATEGORY = "Serverless"; private final boolean runsOnAwsLambda; + @Nullable + private final String awsLambdaLogStreamName = PrivilegedActionUtils.getEnv("AWS_LAMBDA_LOG_STREAM_NAME"); + public ServerlessConfiguration() { String lambdaName = PrivilegedActionUtils.getEnv("AWS_LAMBDA_FUNCTION_NAME"); this.runsOnAwsLambda = null != lambdaName && !lambdaName.isEmpty(); @@ -65,4 +70,9 @@ public boolean runsOnAwsLambda() { return runsOnAwsLambda; } + @Override + @Nullable + public String awsLambdaLogStreamName() { + return awsLambdaLogStreamName; + } } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/StartupInfo.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/StartupInfo.java index f75d4807ab..9033a82c35 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/StartupInfo.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/StartupInfo.java @@ -18,8 +18,9 @@ */ package co.elastic.apm.agent.configuration; +import co.elastic.apm.agent.context.InitializableLifecycleListener; import co.elastic.apm.agent.tracer.configuration.TimeDuration; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.impl.stacktrace.StacktraceConfiguration; import co.elastic.apm.agent.util.VersionUtils; @@ -38,7 +39,7 @@ * under Apache license 2.0. *

*/ -public class StartupInfo extends AbstractLifecycleListener { +public class StartupInfo extends AbstractLifecycleListener implements InitializableLifecycleListener { private static final Logger logger = LoggerFactory.getLogger(StartupInfo.class); private final String elasticApmVersion; diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/context/ClosableLifecycleListenerAdapter.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/context/ClosableLifecycleListenerAdapter.java index 10ba08a7ed..fd4d752b57 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/context/ClosableLifecycleListenerAdapter.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/context/ClosableLifecycleListenerAdapter.java @@ -18,6 +18,9 @@ */ package co.elastic.apm.agent.context; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.LifecycleListener; + import java.io.Closeable; public class ClosableLifecycleListenerAdapter extends AbstractLifecycleListener { diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/context/InitializableLifecycleListener.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/context/InitializableLifecycleListener.java new file mode 100644 index 0000000000..47c3f6e33d --- /dev/null +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/context/InitializableLifecycleListener.java @@ -0,0 +1,33 @@ +/* + * 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.context; + +import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.LifecycleListener; + +public interface InitializableLifecycleListener extends LifecycleListener { + + /** + * Callback for tracer initialization. As opposed to {@link LifecycleListener#start()}, which may + * be called in a delay, this callback is called at the bootstrap of the JVM, before anything else start. + * This may be useful for listeners that need to operate very early on, for example such that setup class loading + * requirement to support OSGi systems. + */ + void init(ElasticApmTracer tracer) throws Exception; +} diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracer.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracer.java index 586511857e..4426dc812f 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracer.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracer.java @@ -26,16 +26,21 @@ import co.elastic.apm.agent.configuration.CoreConfiguration; import co.elastic.apm.agent.configuration.MetricsConfiguration; import co.elastic.apm.agent.configuration.ServerlessConfiguration; +import co.elastic.apm.agent.context.InitializableLifecycleListener; +import co.elastic.apm.agent.report.serialize.DslJsonDataWriter; +import co.elastic.apm.agent.tracer.reporting.DataWriter; +import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.configuration.SpanConfiguration; import co.elastic.apm.agent.context.ClosableLifecycleListenerAdapter; -import co.elastic.apm.agent.context.LifecycleListener; +import co.elastic.apm.agent.tracer.LifecycleListener; import co.elastic.apm.agent.impl.baggage.Baggage; import co.elastic.apm.agent.impl.baggage.W3CBaggagePropagation; import co.elastic.apm.agent.impl.error.ErrorCapture; import co.elastic.apm.agent.impl.metadata.MetaDataFuture; -import co.elastic.apm.agent.impl.sampling.ProbabilitySampler; -import co.elastic.apm.agent.impl.sampling.Sampler; +import co.elastic.apm.agent.tracer.direct.ProbabilitySampler; +import co.elastic.apm.agent.tracer.direct.Sampler; import co.elastic.apm.agent.impl.stacktrace.StacktraceConfiguration; import co.elastic.apm.agent.impl.transaction.AbstractSpan; import co.elastic.apm.agent.impl.transaction.ElasticContext; @@ -62,6 +67,7 @@ import co.elastic.apm.agent.tracer.reference.ReferenceCountedMap; import co.elastic.apm.agent.util.DependencyInjectingServiceLoader; import co.elastic.apm.agent.util.ExecutorUtils; +import com.dslplatform.json.DslJson; import org.stagemonitor.configuration.ConfigurationOption; import org.stagemonitor.configuration.ConfigurationOptionProvider; import org.stagemonitor.configuration.ConfigurationRegistry; @@ -106,6 +112,8 @@ public class ElasticApmTracer implements Tracer { private static volatile boolean classloaderCheckOk = false; + private final DslJson dslJson = new DslJson<>(new DslJson.Settings<>()); + private final ConfigurationRegistry configurationRegistry; private final StacktraceConfiguration stacktraceConfiguration; private final ApmServerClient apmServerClient; @@ -299,6 +307,16 @@ public Transaction startChildTransaction(@Nullable C headerCarrier, Heade return startChildTransaction(headerCarrier, headersGetter, sampler, epochMicros, initiatingClassLoader); } + @Nullable + @Override + public co.elastic.apm.agent.tracer.TraceContext startChildTransaction(@Nullable C headerCarrier, HeaderGetter textHeadersGetter) { + TraceContext childTraceContext = TraceContext.with64BitId(this); + if (childTraceContext.asChildOf(headerCarrier, textHeadersGetter)) { + return childTraceContext; + } + return null; + } + @Override @Nullable public Transaction startChildTransaction(@Nullable C headerCarrier, HeaderGetter headersGetter, Sampler sampler, @@ -672,10 +690,12 @@ public List getActivationListeners() { void init(List lifecycleListeners) { this.lifecycleListeners.addAll(lifecycleListeners); for (LifecycleListener lifecycleListener : lifecycleListeners) { - try { - lifecycleListener.init(this); - } catch (Exception e) { - logger.error("Failed to init " + lifecycleListener.getClass().getName(), e); + if (lifecycleListener instanceof InitializableLifecycleListener) { + try { + ((InitializableLifecycleListener) lifecycleListener).init(this); + } catch (Exception e) { + logger.error("Failed to init " + lifecycleListener.getClass().getName(), e); + } } } } @@ -732,7 +752,7 @@ private synchronized void startSync() { reporter.start(); for (LifecycleListener lifecycleListener : lifecycleListeners) { try { - lifecycleListener.start(this); + lifecycleListener.start(); } catch (Exception e) { logger.error("Failed to start " + lifecycleListener.getClass().getName(), e); } @@ -944,10 +964,37 @@ public MetaDataFuture getMetaDataFuture() { return metaDataFuture; } + @Override + public void addMetric(String name, Labels labels, DoubleSupplier metric) { + metricRegistry.add(name, labels, metric); + } + + @Override + public void removeMetric(String name, Labels labels) { + metricRegistry.removeGauge(name, labels); + } + + @Override + public void reportLog(String log) { + reporter.reportLog(log); + } + + @Override + public void reportLog(byte[] log) { + reporter.reportLog(log); + } + + @Override + public DataWriter newWriter(int maxSerializedSize) { + return new DslJsonDataWriter(dslJson.newWriter(maxSerializedSize), reporter); + } + + @Override public ScheduledThreadPoolExecutor getSharedSingleThreadedPool() { return sharedPool; } + @Override public void addShutdownHook(Closeable closeable) { lifecycleListeners.add(ClosableLifecycleListenerAdapter.of(closeable)); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracerBuilder.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracerBuilder.java index 86c93a3353..b68faae5dd 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracerBuilder.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracerBuilder.java @@ -26,7 +26,7 @@ import co.elastic.apm.agent.configuration.source.ConfigSources; import co.elastic.apm.agent.configuration.source.SystemPropertyConfigurationSource; import co.elastic.apm.agent.context.ClosableLifecycleListenerAdapter; -import co.elastic.apm.agent.context.LifecycleListener; +import co.elastic.apm.agent.tracer.LifecycleListener; import co.elastic.apm.agent.impl.metadata.MetaData; import co.elastic.apm.agent.impl.metadata.MetaDataFuture; import co.elastic.apm.agent.impl.stacktrace.StacktraceConfiguration; diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/Tracer.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/Tracer.java index f645420cd9..c893c041c1 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/Tracer.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/Tracer.java @@ -21,7 +21,7 @@ import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.impl.baggage.Baggage; import co.elastic.apm.agent.impl.error.ErrorCapture; -import co.elastic.apm.agent.impl.sampling.Sampler; +import co.elastic.apm.agent.tracer.direct.Sampler; import co.elastic.apm.agent.impl.transaction.AbstractSpan; import co.elastic.apm.agent.impl.transaction.ElasticContext; import co.elastic.apm.agent.impl.transaction.Span; @@ -30,7 +30,10 @@ import javax.annotation.Nullable; -public interface Tracer extends co.elastic.apm.agent.tracer.service.ServiceAwareTracer, co.elastic.apm.agent.tracer.Tracer { +public interface Tracer extends co.elastic.apm.agent.tracer.Tracer, + co.elastic.apm.agent.tracer.reporting.ReportingTracer, + co.elastic.apm.agent.tracer.direct.DirectTracer, + co.elastic.apm.agent.tracer.service.ServiceAwareTracer { @Nullable @Override diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/circuitbreaker/CircuitBreaker.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/circuitbreaker/CircuitBreaker.java index f17e20876c..ab8953256a 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/circuitbreaker/CircuitBreaker.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/circuitbreaker/CircuitBreaker.java @@ -18,7 +18,7 @@ */ package co.elastic.apm.agent.impl.circuitbreaker; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.util.ExecutorUtils; import co.elastic.apm.agent.sdk.logging.Logger; @@ -50,7 +50,7 @@ public CircuitBreaker(ElasticApmTracer tracer) { } @Override - public void start(ElasticApmTracer tracer) { + public void start() { // failsafe loading of stress monitors in isolation loadGCStressMonitor(tracer); loadSystemCpuStressMonitor(tracer); diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/AbstractSpan.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/AbstractSpan.java index 96de90c4c0..123ca06b05 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/AbstractSpan.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/AbstractSpan.java @@ -29,6 +29,7 @@ import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.tracer.Outcome; +import co.elastic.apm.agent.tracer.direct.AbstractDirectSpan; import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; import co.elastic.apm.agent.tracer.pooling.Recyclable; @@ -40,7 +41,9 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -public abstract class AbstractSpan> extends ElasticContext implements Recyclable, co.elastic.apm.agent.tracer.AbstractSpan { +public abstract class AbstractSpan> extends ElasticContext implements Recyclable, + co.elastic.apm.agent.tracer.direct.AbstractDirectSpan, + co.elastic.apm.agent.tracer.AbstractSpan { private static final Logger logger = LoggerFactory.getLogger(AbstractSpan.class); private static final Logger oneTimeDuplicatedEndLogger = LoggerUtils.logOnce(logger); private static final Logger oneTimeMaxSpanLinksLogger = LoggerUtils.logOnce(logger); @@ -509,6 +512,15 @@ public T captureException(@Nullable Throwable t) { return thiz(); } + @Override + public T captureException(@Nullable Throwable t, long epochMicros) { + if (t != null) { + captureExceptionAndGetErrorId(epochMicros, t); + } + return thiz(); + + } + public void endExceptionally(@Nullable Throwable t) { captureException(t).end(); } @@ -518,19 +530,22 @@ public String captureExceptionAndGetErrorId(@Nullable Throwable t) { return captureExceptionAndGetErrorId(getTraceContext().getClock().getEpochMicros(), t); } - public void addLabel(String key, String value) { + + @Override + public void addLabel(String key, Boolean value) { if (isSampled()) { getContext().addLabel(key, value); } } + @Override public void addLabel(String key, Number value) { if (isSampled()) { getContext().addLabel(key, value); } } - - public void addLabel(String key, Boolean value) { + @Override + public void addLabel(String key, String value) { if (isSampled()) { getContext().addLabel(key, value); } @@ -557,6 +572,7 @@ public void end() { end(traceContext.getClock().getEpochMicros()); } + @Override public final void end(long epochMicros) { if (!finished) { this.endTimestamp.set(epochMicros); @@ -792,4 +808,14 @@ private String normalizeType(@Nullable String type) { public boolean addLink(HeaderGetter headerGetter, @Nullable C carrier) { return addSpanLink(headerGetter, carrier); } + + @Override + public Span spanChild() { + return tracer.startSpan(TraceContext.fromParent(), this, baggage); + } + + @Override + public Span spanChild(long microseconds) { + return tracer.startSpan(TraceContext.fromParent(), this, baggage, microseconds); + } } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Id.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Id.java index 27aa8289b7..698df85011 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Id.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Id.java @@ -187,6 +187,7 @@ public void writeAsHex(StringBuilder sb) { * @see W3C trace context spec * @return the last 8 bytes of this id as a {@code long} */ + @Override public long getLeastSignificantBits() { return readLong(data.length - 8); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Span.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Span.java index 7b214ddbd8..c2bb72e45a 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Span.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Span.java @@ -26,6 +26,7 @@ import co.elastic.apm.agent.impl.context.ServiceTarget; import co.elastic.apm.agent.impl.context.SpanContext; import co.elastic.apm.agent.impl.context.Url; +import co.elastic.apm.agent.tracer.direct.DirectSpan; import co.elastic.apm.agent.tracer.util.ResultUtil; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; @@ -38,7 +39,9 @@ import java.util.Objects; import java.util.concurrent.TimeUnit; -public class Span extends AbstractSpan implements Recyclable, co.elastic.apm.agent.tracer.Span { +public class Span extends AbstractSpan implements Recyclable, + co.elastic.apm.agent.tracer.Span, + co.elastic.apm.agent.tracer.direct.DirectSpan { private static final Logger logger = LoggerFactory.getLogger(Span.class); public static final long MAX_LOG_INTERVAL_MICRO_SECS = TimeUnit.MINUTES.toMicros(5); @@ -177,6 +180,7 @@ public Span withAction(@Nullable String action) { * TODO: remove in 2.0 - no need for that once we decide to drop support for old agent usages */ @Deprecated + @Override public void setType(@Nullable String type, @Nullable String subtype, @Nullable String action) { if (type != null && (subtype == null || subtype.isEmpty()) && (action == null || action.isEmpty())) { // hierarchical typing - pre 1.4; we need to split diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/TraceContext.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/TraceContext.java index f8854468f0..1d8b2f6388 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/TraceContext.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/TraceContext.java @@ -21,7 +21,7 @@ import co.elastic.apm.agent.configuration.CoreConfiguration; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.impl.baggage.Baggage; -import co.elastic.apm.agent.impl.sampling.Sampler; +import co.elastic.apm.agent.tracer.direct.Sampler; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; @@ -335,13 +335,22 @@ private void addTraceStateHeader(@Nullable T tracestateHeaderValue, CharAcce } } + private double cachedSampleRate = 0; + @Nullable + private String cachedHeader; + public void asRootSpan(Sampler sampler) { traceId.setToRandomValue(); id.setToRandomValue(); transactionId.copyFrom(id); if (sampler.isSampled(traceId)) { flags = FLAG_RECORDED; - traceState.set(sampler.getSampleRate(), sampler.getTraceStateHeader()); + double rate = sampler.getSampleRate(); + if (cachedHeader == null || cachedSampleRate != rate) { + cachedSampleRate = rate; + cachedHeader = TraceState.getHeaderValue(rate); + } + traceState.set(rate, cachedHeader); } clock.init(); onMutation(); diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Transaction.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Transaction.java index aabac69aed..44cd613293 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Transaction.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Transaction.java @@ -26,8 +26,9 @@ import co.elastic.apm.agent.impl.baggage.W3CBaggagePropagation; import co.elastic.apm.agent.impl.context.Response; import co.elastic.apm.agent.impl.context.TransactionContext; -import co.elastic.apm.agent.impl.sampling.Sampler; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.direct.Sampler; +import co.elastic.apm.agent.tracer.pooling.Recyclable; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.metrics.Timer; import co.elastic.apm.agent.tracer.Outcome; @@ -46,7 +47,9 @@ /** * Data captured by an agent representing an event occurring in a monitored service */ -public class Transaction extends AbstractSpan implements co.elastic.apm.agent.tracer.Transaction { +public class Transaction extends AbstractSpan implements Recyclable, + co.elastic.apm.agent.tracer.Transaction, + co.elastic.apm.agent.tracer.direct.DirectTransaction { /** * Mutable labels instance used when reporting transaction metrics. diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/logging/ApmServerLogAppender.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/logging/ApmServerLogAppender.java index 59328be609..a7d35ac1fb 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/logging/ApmServerLogAppender.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/logging/ApmServerLogAppender.java @@ -18,8 +18,9 @@ */ package co.elastic.apm.agent.logging; -import co.elastic.apm.agent.context.AbstractLifecycleListener; -import co.elastic.apm.agent.context.LifecycleListener; +import co.elastic.apm.agent.context.InitializableLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.LifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.report.Reporter; import co.elastic.logging.log4j2.EcsLayout; @@ -100,13 +101,14 @@ public void append(LogEvent event) { sendLogEvent(event); } - public LifecycleListener getInitListener() { - return new AbstractLifecycleListener() { + public InitializableLifecycleListener getInitListener() { + class InitListener extends AbstractLifecycleListener implements InitializableLifecycleListener { @Override - public void init(ElasticApmTracer tracer) throws Exception { + public void init(ElasticApmTracer tracer) { initStreaming(tracer.getConfig(LoggingConfiguration.class), tracer.getReporter()); } - }; + } + return new InitListener(); } private void initStreaming(LoggingConfiguration config, Reporter reporter) { diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/MetricCollector.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/MetricCollector.java index b8ccd561f4..e7dadaa2c6 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/MetricCollector.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/MetricCollector.java @@ -18,6 +18,8 @@ */ package co.elastic.apm.agent.metrics; +import co.elastic.apm.agent.tracer.reporting.Labels; + public interface MetricCollector { void addMetricValue(String metric, Labels labels, double value); diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/MetricRegistry.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/MetricRegistry.java index 2df93faa7f..f0378cbbe2 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/MetricRegistry.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/MetricRegistry.java @@ -23,6 +23,8 @@ import co.elastic.apm.agent.report.ReporterConfiguration; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; +import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; +import co.elastic.apm.agent.tracer.reporting.Labels; import org.HdrHistogram.WriterReaderPhaser; import javax.annotation.Nonnull; diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/MetricSet.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/MetricSet.java index 474a3827be..07d8b354d5 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/MetricSet.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/MetricSet.java @@ -19,6 +19,8 @@ package co.elastic.apm.agent.metrics; import co.elastic.apm.agent.tracer.pooling.Recyclable; +import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; +import co.elastic.apm.agent.tracer.reporting.Labels; import javax.annotation.Nullable; import java.util.Map; diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/AgentOverheadMetrics.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/AgentOverheadMetrics.java index c0a06ab921..08bd932169 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/AgentOverheadMetrics.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/AgentOverheadMetrics.java @@ -19,12 +19,13 @@ package co.elastic.apm.agent.metrics.builtin; import co.elastic.apm.agent.configuration.MetricsConfiguration; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricCollector; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.metrics.MetricsProvider; +import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.util.ElasticThreadStateListener; import co.elastic.apm.agent.util.ExecutorUtils; import co.elastic.apm.agent.util.JmxUtils; @@ -77,6 +78,7 @@ private ThreadInfo(String threadPurpose) { } } + private final ElasticApmTracer tracer; private final ThreadMXBean threadBean; private final OperatingSystemMXBean osBean; @@ -93,7 +95,8 @@ private ThreadInfo(String threadPurpose) { private final long processCpuTimeScalingFactor; - public AgentOverheadMetrics() { + public AgentOverheadMetrics(ElasticApmTracer tracer) { + this.tracer = tracer; osBean = ManagementFactory.getOperatingSystemMXBean(); getProcessCpuLoad = JmxUtils.getOperatingSystemMBeanMethod(osBean, "getProcessCpuLoad"); getProcessCpuTime = JmxUtils.getOperatingSystemMBeanMethod(osBean, "getProcessCpuTime"); @@ -113,7 +116,7 @@ public AgentOverheadMetrics() { } @Override - public void start(ElasticApmTracer tracer) throws Exception { + public void start() throws Exception { MetricRegistry metricRegistry = tracer.getMetricRegistry(); MetricsConfiguration config = tracer.getConfig(MetricsConfiguration.class); bindTo(metricRegistry, config); diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/AgentReporterMetrics.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/AgentReporterMetrics.java index 6970d114ae..ff8818968d 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/AgentReporterMetrics.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/AgentReporterMetrics.java @@ -19,7 +19,7 @@ package co.elastic.apm.agent.metrics.builtin; import co.elastic.apm.agent.configuration.MetricsConfiguration; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricCollector; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.metrics.MetricsProvider; diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/CGroupMetrics.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/CGroupMetrics.java index 9f64ed14cc..a37ce90ee5 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/CGroupMetrics.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/CGroupMetrics.java @@ -18,10 +18,10 @@ */ package co.elastic.apm.agent.metrics.builtin; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.metrics.DoubleSupplier; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; @@ -60,15 +60,17 @@ public class CGroupMetrics extends AbstractLifecycleListener { private static final Logger logger = LoggerFactory.getLogger(CGroupMetrics.class); + private final ElasticApmTracer tracer; @Nullable private final CgroupFiles cgroupFiles; - public CGroupMetrics() { - this(new File(PROC_SELF_CGROUP), new File(PROC_SELF_MOUNTINFO)); + public CGroupMetrics(ElasticApmTracer tracer) { + this(tracer, new File(PROC_SELF_CGROUP), new File(PROC_SELF_MOUNTINFO)); } - CGroupMetrics(File procSelfCgroup, File mountInfo) { + CGroupMetrics(ElasticApmTracer tracer, File procSelfCgroup, File mountInfo) { + this.tracer = tracer; cgroupFiles = findCgroupFiles(procSelfCgroup, mountInfo); } @@ -213,7 +215,7 @@ private File getMaxMemoryFile(File maxMemoryFile, String cgroupUnlimitedConstant } @Override - public void start(ElasticApmTracer tracer) { + public void start() { bindTo(tracer.getMetricRegistry()); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/JvmFdMetrics.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/JvmFdMetrics.java index 4a0764fe35..4ba2f16931 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/JvmFdMetrics.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/JvmFdMetrics.java @@ -18,10 +18,10 @@ */ package co.elastic.apm.agent.metrics.builtin; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.metrics.DoubleSupplier; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import javax.annotation.Nullable; @@ -39,8 +39,14 @@ public class JvmFdMetrics extends AbstractLifecycleListener { private static final MethodHandle getOpenFileDescriptorCount = getMethodHandle("getOpenFileDescriptorCount"); private static final MethodHandle getMaxFileDescriptorCount = getMethodHandle("getMaxFileDescriptorCount"); + private final ElasticApmTracer tracer; + + public JvmFdMetrics(ElasticApmTracer tracer) { + this.tracer = tracer; + } + @Override - public void start(ElasticApmTracer tracer) { + public void start() { bindTo(tracer.getMetricRegistry()); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/JvmGcMetrics.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/JvmGcMetrics.java index 4cd140aced..1ad0fb24b0 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/JvmGcMetrics.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/JvmGcMetrics.java @@ -18,10 +18,10 @@ */ package co.elastic.apm.agent.metrics.builtin; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.metrics.DoubleSupplier; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import com.sun.management.ThreadMXBean; import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; @@ -32,10 +32,16 @@ public class JvmGcMetrics extends AbstractLifecycleListener { + private final ElasticApmTracer tracer; + private final List garbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans(); + public JvmGcMetrics(ElasticApmTracer tracer) { + this.tracer = tracer; + } + @Override - public void start(ElasticApmTracer tracer) { + public void start() { bindTo(tracer.getMetricRegistry()); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/JvmMemoryMetrics.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/JvmMemoryMetrics.java index b83fbf2eff..7add5f4d11 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/JvmMemoryMetrics.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/JvmMemoryMetrics.java @@ -18,10 +18,10 @@ */ package co.elastic.apm.agent.metrics.builtin; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.metrics.DoubleSupplier; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; @@ -35,8 +35,14 @@ public class JvmMemoryMetrics extends AbstractLifecycleListener { private static final Logger logger = LoggerFactory.getLogger(JvmMemoryMetrics.class); + private final ElasticApmTracer tracer; + + public JvmMemoryMetrics(ElasticApmTracer tracer) { + this.tracer = tracer; + } + @Override - public void start(ElasticApmTracer tracer) { + public void start() { bindTo(tracer.getMetricRegistry()); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/SystemMetrics.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/SystemMetrics.java index 3659938a5f..61d1a8b876 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/SystemMetrics.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/SystemMetrics.java @@ -18,12 +18,13 @@ */ package co.elastic.apm.agent.metrics.builtin; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.common.util.WildcardMatcher; -import co.elastic.apm.agent.metrics.DoubleSupplier; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; +import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.util.JmxUtils; import org.stagemonitor.util.StringUtils; @@ -55,6 +56,8 @@ */ public class SystemMetrics extends AbstractLifecycleListener { + private final ElasticApmTracer tracer; + private final OperatingSystemMXBean operatingSystemBean; @Nullable @@ -73,11 +76,12 @@ public class SystemMetrics extends AbstractLifecycleListener { private final Method virtualProcessMemory; private final File memInfoFile; - public SystemMetrics() { - this(new File("/proc/meminfo")); + public SystemMetrics(ElasticApmTracer tracer) { + this(tracer, new File("/proc/meminfo")); } - SystemMetrics(File memInfoFile) { + SystemMetrics(ElasticApmTracer tracer, File memInfoFile) { + this.tracer = tracer; this.operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); this.systemCpuUsage = JmxUtils.getOperatingSystemMBeanMethod(operatingSystemBean, "getSystemCpuLoad"); this.processCpuUsage = JmxUtils.getOperatingSystemMBeanMethod(operatingSystemBean, "getProcessCpuLoad"); @@ -88,7 +92,7 @@ public SystemMetrics() { } @Override - public void start(ElasticApmTracer tracer) { + public void start() { bindTo(tracer.getMetricRegistry()); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/ThreadMetrics.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/ThreadMetrics.java index 52c5203555..9be546121f 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/ThreadMetrics.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/ThreadMetrics.java @@ -18,10 +18,10 @@ */ package co.elastic.apm.agent.metrics.builtin; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.metrics.DoubleSupplier; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import java.lang.management.ManagementFactory; @@ -29,8 +29,14 @@ public class ThreadMetrics extends AbstractLifecycleListener { + private final ElasticApmTracer tracer; + + public ThreadMetrics(ElasticApmTracer tracer) { + this.tracer = tracer; + } + @Override - public void start(ElasticApmTracer tracer) { + public void start() { bindTo(tracer.getMetricRegistry()); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/DslJsonDataWriter.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/DslJsonDataWriter.java new file mode 100644 index 0000000000..235c7cd76d --- /dev/null +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/DslJsonDataWriter.java @@ -0,0 +1,145 @@ +/* + * 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.report.serialize; + +import co.elastic.apm.agent.report.Reporter; +import co.elastic.apm.agent.tracer.reporting.DataWriter; +import com.dslplatform.json.BoolConverter; +import com.dslplatform.json.JsonWriter; +import com.dslplatform.json.NumberConverter; + +import javax.annotation.Nullable; + +public class DslJsonDataWriter implements DataWriter { + + private final JsonWriter jw; + + private final Reporter reporter; + + private final StringBuilder replaceBuilder = new StringBuilder(); + + public DslJsonDataWriter(JsonWriter jw, Reporter reporter) { + this.jw = jw; + this.reporter = reporter; + } + + @Override + public void writeStructure(StructureType type) { + switch (type) { + case OBJECT_START: + jw.writeByte(JsonWriter.OBJECT_START); + break; + case OBJECT_END: + jw.writeByte(JsonWriter.OBJECT_END); + break; + case ARRAY_START: + jw.writeByte(JsonWriter.ARRAY_START); + break; + case ARRAY_END: + jw.writeByte(JsonWriter.ARRAY_END); + break; + case NEXT: + jw.writeByte(JsonWriter.COMMA); + break; + case NEW: + jw.writeByte((byte) '\n'); + break; + default: + throw new IllegalArgumentException(); + } + } + + @Override + public void writeKey(CharSequence name) { + jw.writeString(name); + jw.writeByte(JsonWriter.SEMI); + } + + @Override + public void writeKey(CharSequence name, boolean sanitized) { + if (sanitized) { + DslJsonSerializer.writeStringValue(DslJsonSerializer.sanitizePropertyName(name.toString(), replaceBuilder), replaceBuilder, jw); + jw.writeByte(JsonWriter.SEMI); + } else { + writeKey(name); + } + } + + @Override + public void writeKey(CharSequence name, boolean sanitized, @Nullable String suffix) { + replaceBuilder.setLength(0); + if (sanitized) { + DslJsonSerializer.sanitizePropertyName(name.toString(), replaceBuilder); + } else { + replaceBuilder.append(name); + } + if (suffix != null) { + if (replaceBuilder.length() == 0) { + replaceBuilder.append(name); + } + replaceBuilder.append(suffix); + } + jw.writeString(replaceBuilder); + jw.writeByte(JsonWriter.SEMI); + } + + @Override + public void writeValue(boolean value) { + BoolConverter.serialize(value, jw); + } + + @Override + public void writeValue(long value) { + NumberConverter.serialize(value, jw); + } + + @Override + public void writeValue(double value) { + NumberConverter.serialize(value, jw); + } + + @Override + public void writeValue(CharSequence value) { + jw.writeString(value); + } + + @Override + public void writeValue(CharSequence value, boolean trimmed) { + if (trimmed) { + DslJsonSerializer.writeStringValue(value, replaceBuilder, jw); + } else { + writeValue(value); + } + } + + @Override + public int size() { + return jw.size(); + } + + @Override + public void report() { + reporter.reportMetrics(jw); + } + + @Override + public String toString() { + return jw.toString(); + } +} diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/DslJsonSerializer.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/DslJsonSerializer.java index 6ec3676c4b..05c91a4e29 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/DslJsonSerializer.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/DslJsonSerializer.java @@ -59,7 +59,7 @@ import co.elastic.apm.agent.impl.transaction.StackFrame; import co.elastic.apm.agent.impl.transaction.TraceContext; import co.elastic.apm.agent.impl.transaction.Transaction; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.report.ApmServerClient; import co.elastic.apm.agent.sdk.internal.collections.LongList; import co.elastic.apm.agent.sdk.logging.Logger; diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporter.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporter.java index aa1a9347a9..369fca596d 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporter.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporter.java @@ -19,9 +19,9 @@ package co.elastic.apm.agent.report.serialize; import co.elastic.apm.agent.tracer.service.ServiceInfo; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.metrics.MetricSet; import co.elastic.apm.agent.report.Reporter; @@ -47,7 +47,7 @@ public MetricRegistryReporter(ElasticApmTracer tracer) { } @Override - public void start(ElasticApmTracer tracer) { + public void start() { long intervalMs = tracer.getConfig(ReporterConfiguration.class).getMetricsIntervalMs(); if (intervalMs > 0) { tracer.getSharedSingleThreadedPool().scheduleAtFixedRate(this, intervalMs, intervalMs, TimeUnit.MILLISECONDS); diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistrySerializer.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistrySerializer.java index e5b3700f39..70391123b4 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistrySerializer.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistrySerializer.java @@ -19,7 +19,7 @@ package co.elastic.apm.agent.report.serialize; import co.elastic.apm.agent.tracer.service.ServiceInfo; -import co.elastic.apm.agent.metrics.DoubleSupplier; +import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; import co.elastic.apm.agent.metrics.MetricSet; import co.elastic.apm.agent.metrics.Timer; import com.dslplatform.json.DslJson; diff --git a/apm-agent-core/src/main/resources/META-INF/services/co.elastic.apm.agent.context.LifecycleListener b/apm-agent-core/src/main/resources/META-INF/services/co.elastic.apm.agent.tracer.LifecycleListener similarity index 100% rename from apm-agent-core/src/main/resources/META-INF/services/co.elastic.apm.agent.context.LifecycleListener rename to apm-agent-core/src/main/resources/META-INF/services/co.elastic.apm.agent.tracer.LifecycleListener diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/TransactionUtils.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/TransactionUtils.java index 637915aea1..0fc94bdc14 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/TransactionUtils.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/TransactionUtils.java @@ -21,7 +21,7 @@ import co.elastic.apm.agent.impl.baggage.Baggage; import co.elastic.apm.agent.impl.context.Request; import co.elastic.apm.agent.impl.context.TransactionContext; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; import co.elastic.apm.agent.impl.transaction.Span; import co.elastic.apm.agent.impl.transaction.TraceContext; import co.elastic.apm.agent.impl.transaction.Transaction; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/ElasticApmTracerTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/ElasticApmTracerTest.java index 5283795cf5..a61899135a 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/ElasticApmTracerTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/ElasticApmTracerTest.java @@ -27,14 +27,14 @@ import co.elastic.apm.agent.configuration.source.ConfigSources; import co.elastic.apm.agent.impl.baggage.Baggage; import co.elastic.apm.agent.impl.error.ErrorCapture; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; import co.elastic.apm.agent.impl.stacktrace.StacktraceConfiguration; 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; import co.elastic.apm.agent.impl.transaction.Transaction; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.objectpool.TestObjectPoolFactory; import co.elastic.apm.agent.report.ApmServerClient; import co.elastic.apm.agent.tracer.Outcome; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/LifecycleTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/LifecycleTest.java index 9ba0dbc469..2281ae3cab 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/LifecycleTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/LifecycleTest.java @@ -21,7 +21,8 @@ import co.elastic.apm.agent.MockReporter; import co.elastic.apm.agent.bci.ElasticApmAgent; import co.elastic.apm.agent.configuration.SpyConfiguration; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.context.InitializableLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.objectpool.TestObjectPoolFactory; import net.bytebuddy.agent.ByteBuddyAgent; import org.junit.jupiter.api.AfterEach; @@ -138,22 +139,23 @@ void testStartInactive() throws IOException { @Test void testStartDisabled() throws Exception { ConfigurationRegistry configRegistry = SpyConfiguration.createSpyConfig(SimpleSource.forTest("enabled", "false")); - AtomicBoolean initialized = new AtomicBoolean(); - AtomicBoolean started = new AtomicBoolean(); + final AtomicBoolean initialized = new AtomicBoolean(); + final AtomicBoolean started = new AtomicBoolean(); + class TestListener extends AbstractLifecycleListener implements InitializableLifecycleListener { + @Override + public void init(ElasticApmTracer tracer) { + initialized.set(true); + } + + @Override + public void start() { + started.set(true); + } + } ElasticApmTracer tracer = new ElasticApmTracerBuilder() .configurationRegistry(configRegistry) .reporter(new MockReporter()) - .withLifecycleListener(new AbstractLifecycleListener() { - @Override - public void init(ElasticApmTracer tracer) { - initialized.set(true); - } - - @Override - public void start(ElasticApmTracer tracer) throws Exception { - started.set(true); - } - }) + .withLifecycleListener(new TestListener()) .build(); ElasticApmAgent.initInstrumentation(tracer, ByteBuddyAgent.install()); assertThat(tracer.isRunning()).isFalse(); @@ -163,7 +165,7 @@ public void start(ElasticApmTracer tracer) throws Exception { /* * Has an entry in - * src/test/resources/META-INF/services/co.elastic.apm.agent.context.LifecycleListener + * src/test/resources/META-INF/services/co.elastic.apm.agent.tracer.LifecycleListener */ public static class TestLifecycleListener extends AbstractLifecycleListener { @@ -178,7 +180,7 @@ public TestLifecycleListener() { } @Override - public void start(ElasticApmTracer tracer) { + public void start() { start.incrementAndGet(); } diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/SpanTypeBreakdownTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/SpanTypeBreakdownTest.java index a090c71566..c6938a5474 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/SpanTypeBreakdownTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/SpanTypeBreakdownTest.java @@ -22,11 +22,11 @@ import co.elastic.apm.agent.MockTracer; import co.elastic.apm.agent.configuration.CoreConfiguration; import co.elastic.apm.agent.configuration.SpyConfiguration; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; import co.elastic.apm.agent.impl.transaction.AbstractSpan; import co.elastic.apm.agent.impl.transaction.Span; import co.elastic.apm.agent.impl.transaction.Transaction; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricSet; import co.elastic.apm.agent.metrics.Timer; import org.junit.jupiter.api.AfterEach; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/SpanTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/SpanTest.java index 7b7bbae19b..3cf609730a 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/SpanTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/SpanTest.java @@ -23,7 +23,7 @@ import co.elastic.apm.agent.impl.TextHeaderMapAccessor; import co.elastic.apm.agent.impl.Utf8HeaderMapAccessor; import co.elastic.apm.agent.impl.baggage.Baggage; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; import co.elastic.apm.agent.objectpool.TestObjectPoolFactory; import co.elastic.apm.agent.tracer.Outcome; import org.junit.jupiter.api.BeforeEach; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TraceContextTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TraceContextTest.java index e1f5c0a1d1..2042067555 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TraceContextTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TraceContextTest.java @@ -26,8 +26,8 @@ import co.elastic.apm.agent.impl.ElasticApmTracerBuilder; import co.elastic.apm.agent.impl.TextHeaderMapAccessor; import co.elastic.apm.agent.impl.Utf8HeaderMapAccessor; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; -import co.elastic.apm.agent.impl.sampling.Sampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.Sampler; import co.elastic.apm.agent.objectpool.TestObjectPoolFactory; import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; import co.elastic.apm.agent.tracer.dispatch.HeaderSetter; @@ -422,7 +422,6 @@ private TraceContext createRootSpan(double sampleRate) { Sampler sampler = mock(Sampler.class); doReturn(true).when(sampler).isSampled(any(Id.class)); doReturn(sampleRate).when(sampler).getSampleRate(); - doReturn(TraceState.getHeaderValue(sampleRate)).when(sampler).getTraceStateHeader(); traceContext.asRootSpan(sampler); return traceContext; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TraceContinuationStrategyTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TraceContinuationStrategyTest.java index 5b42855a11..44bfb6ba83 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TraceContinuationStrategyTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TraceContinuationStrategyTest.java @@ -25,7 +25,7 @@ import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.impl.ElasticApmTracerBuilder; import co.elastic.apm.agent.impl.TextHeaderMapAccessor; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; import co.elastic.apm.agent.objectpool.TestObjectPoolFactory; import co.elastic.apm.agent.report.ApmServerClient; import org.junit.jupiter.api.BeforeAll; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TransactionTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TransactionTest.java index 8035ef3a0d..f5c4420594 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TransactionTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TransactionTest.java @@ -24,7 +24,7 @@ import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.impl.baggage.Baggage; import co.elastic.apm.agent.impl.metadata.MetaDataMock; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; import co.elastic.apm.agent.impl.stacktrace.StacktraceConfiguration; import co.elastic.apm.agent.report.ApmServerClient; import co.elastic.apm.agent.report.serialize.DslJsonSerializer; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/MetricRegistryTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/MetricRegistryTest.java index 2b445c9e54..1b8fe9174f 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/MetricRegistryTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/MetricRegistryTest.java @@ -21,6 +21,8 @@ import co.elastic.apm.agent.configuration.MetricsConfiguration; import co.elastic.apm.agent.common.util.WildcardMatcher; import co.elastic.apm.agent.report.ReporterConfiguration; +import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; +import co.elastic.apm.agent.tracer.reporting.Labels; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/AgentOverheadMetricsTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/AgentOverheadMetricsTest.java index 814bc84cfc..21f37585e0 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/AgentOverheadMetricsTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/AgentOverheadMetricsTest.java @@ -20,7 +20,8 @@ import co.elastic.apm.agent.configuration.MetricsConfiguration; import co.elastic.apm.agent.common.util.WildcardMatcher; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.metrics.MetricSet; import co.elastic.apm.agent.report.ReporterConfiguration; @@ -49,6 +50,7 @@ import static org.awaitility.Awaitility.await; import static org.hamcrest.Matchers.equalTo; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; public class AgentOverheadMetricsTest { @@ -65,7 +67,7 @@ public void setUp() { spyReporterConfig = spy(ReporterConfiguration.class); spyMetricsConfig = spy(MetricsConfiguration.class); - overheadMetrics = new AgentOverheadMetrics(); + overheadMetrics = new AgentOverheadMetrics(mock(ElasticApmTracer.class)); metricRegistry = new MetricRegistry(spyReporterConfig, spyMetricsConfig); } @@ -384,10 +386,11 @@ public void testDisableMetric(String metric) throws InterruptedException { } private static void awaitNonZeroProcessCpuLoad() { + ElasticApmTracer tracer = mock(ElasticApmTracer.class); long start = System.nanoTime(); Double load = null; while ((System.nanoTime() - start) < 5_000_000_000L) { - load = new AgentOverheadMetrics().getProcessCpuLoad(); + load = new AgentOverheadMetrics(tracer).getProcessCpuLoad(); if (load != null && load > 0.0) break; } assertThat(load).isGreaterThan(0.0); diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/AgentReporterMetricsTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/AgentReporterMetricsTest.java index bc86fd0cda..c9b2cea731 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/AgentReporterMetricsTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/AgentReporterMetricsTest.java @@ -20,7 +20,7 @@ import co.elastic.apm.agent.configuration.MetricsConfiguration; import co.elastic.apm.agent.common.util.WildcardMatcher; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.metrics.MetricSet; import co.elastic.apm.agent.report.ReporterConfiguration; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/CGroupMetricsTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/CGroupMetricsTest.java index a8d80db1e0..85ad8c8446 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/CGroupMetricsTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/CGroupMetricsTest.java @@ -19,7 +19,8 @@ package co.elastic.apm.agent.metrics.builtin; import co.elastic.apm.agent.configuration.MetricsConfiguration; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.report.ReporterConfiguration; import org.junit.jupiter.api.Test; @@ -48,7 +49,9 @@ private CGroupMetrics createUnlimitedSystemMetrics() throws URISyntaxException, fw.write("39 30 0:35 / " + mountInfo.getAbsolutePath() + " rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,seclabel,memory\n"); fw.close(); - return new CGroupMetrics(new File(getClass().getResource("/proc/cgroup").toURI()), + return new CGroupMetrics( + mock(ElasticApmTracer.class), + new File(getClass().getResource("/proc/cgroup").toURI()), fileTmp ); } @@ -73,7 +76,9 @@ void testFreeCgroupMemory(long value, String selfCGroup, String sysFsGroup, Stri } fw.close(); - CGroupMetrics cgroupMetrics = new CGroupMetrics(new File(getClass().getResource(selfCGroup).toURI()), + CGroupMetrics cgroupMetrics = new CGroupMetrics( + mock(ElasticApmTracer.class), + new File(getClass().getResource(selfCGroup).toURI()), fileTmp ); cgroupMetrics.bindTo(metricRegistry); diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/JvmFdMetricsTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/JvmFdMetricsTest.java index dc15f3874c..707a0eb50b 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/JvmFdMetricsTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/JvmFdMetricsTest.java @@ -19,7 +19,8 @@ package co.elastic.apm.agent.metrics.builtin; import co.elastic.apm.agent.configuration.MetricsConfiguration; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.report.ReporterConfiguration; import org.junit.jupiter.api.condition.DisabledOnOs; @@ -34,8 +35,7 @@ class JvmFdMetricsTest { - private final JvmFdMetrics jvmFdMetrics = new JvmFdMetrics(); - + private final JvmFdMetrics jvmFdMetrics = new JvmFdMetrics(mock(ElasticApmTracer.class)); @ParameterizedTest(name = "{0}") @ValueSource(strings = { diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/JvmGcMetricsTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/JvmGcMetricsTest.java index 434df65c8d..22820fb14a 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/JvmGcMetricsTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/JvmGcMetricsTest.java @@ -18,6 +18,7 @@ */ package co.elastic.apm.agent.metrics.builtin; +import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.metrics.MetricRegistry; import org.junit.jupiter.api.Test; @@ -30,7 +31,7 @@ class JvmGcMetricsTest { - private final JvmGcMetrics jvmGcMetrics = new JvmGcMetrics(); + private final JvmGcMetrics jvmGcMetrics = new JvmGcMetrics(mock(ElasticApmTracer.class)); private MetricRegistry registry = mock(MetricRegistry.class); @Test diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/JvmMemoryMetricsTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/JvmMemoryMetricsTest.java index 05c4fe4348..1e04d3bb45 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/JvmMemoryMetricsTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/JvmMemoryMetricsTest.java @@ -19,7 +19,8 @@ package co.elastic.apm.agent.metrics.builtin; import co.elastic.apm.agent.configuration.MetricsConfiguration; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.report.ReporterConfiguration; import org.assertj.core.api.AbstractDoubleAssert; @@ -38,7 +39,7 @@ class JvmMemoryMetricsTest { - private final JvmMemoryMetrics jvmMemoryMetrics = new JvmMemoryMetrics(); + private final JvmMemoryMetrics jvmMemoryMetrics = new JvmMemoryMetrics(mock(ElasticApmTracer.class)); @Test void testMetrics() { diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/SystemMetricsTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/SystemMetricsTest.java index dea7de26c2..b72eb4c289 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/SystemMetricsTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/SystemMetricsTest.java @@ -19,7 +19,8 @@ package co.elastic.apm.agent.metrics.builtin; import co.elastic.apm.agent.configuration.MetricsConfiguration; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.report.ReporterConfiguration; import org.junit.jupiter.api.Test; @@ -37,7 +38,7 @@ class SystemMetricsTest { private MetricRegistry metricRegistry = new MetricRegistry(mock(ReporterConfiguration.class), spy(MetricsConfiguration.class)); - private SystemMetrics systemMetrics = new SystemMetrics(); + private SystemMetrics systemMetrics = new SystemMetrics(mock(ElasticApmTracer.class)); @Test @DisabledOnOs(OS.MAC) @@ -59,7 +60,9 @@ void testSystemMetrics() throws InterruptedException { "/proc/meminfo-3.14, 556630016" }) void testFreeMemoryMeminfo(String file, long value) throws Exception { - SystemMetrics systemMetrics = new SystemMetrics(new File(getClass().getResource(file).toURI())); + SystemMetrics systemMetrics = new SystemMetrics( + mock(ElasticApmTracer.class), + new File(getClass().getResource(file).toURI())); systemMetrics.bindTo(metricRegistry); assertThat(metricRegistry.getGaugeValue("system.memory.actual.free", Labels.EMPTY)).isEqualTo(value); assertThat(metricRegistry.getGaugeValue("system.memory.total", Labels.EMPTY)).isEqualTo(7964778496L); diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/ThreadMetricsTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/ThreadMetricsTest.java index 287047b2ea..488449ecdc 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/ThreadMetricsTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/ThreadMetricsTest.java @@ -19,7 +19,8 @@ package co.elastic.apm.agent.metrics.builtin; import co.elastic.apm.agent.configuration.MetricsConfiguration; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.report.ReporterConfiguration; import org.junit.jupiter.api.Test; @@ -31,7 +32,7 @@ class ThreadMetricsTest { private static final double NUM_ADDED_THREADS = 12.0; - private final ThreadMetrics threadMetrics = new ThreadMetrics(); + private final ThreadMetrics threadMetrics = new ThreadMetrics(mock(ElasticApmTracer.class)); private MetricRegistry registry = new MetricRegistry(mock(ReporterConfiguration.class), spy(MetricsConfiguration.class)); @Test diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/DslJsonSerializerTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/DslJsonSerializerTest.java index 86def7f803..efac6760e6 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/DslJsonSerializerTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/DslJsonSerializerTest.java @@ -44,8 +44,8 @@ import co.elastic.apm.agent.impl.metadata.ProcessInfo; import co.elastic.apm.agent.impl.metadata.Service; import co.elastic.apm.agent.impl.metadata.SystemInfo; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; -import co.elastic.apm.agent.impl.sampling.Sampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.Sampler; import co.elastic.apm.agent.impl.stacktrace.StacktraceConfiguration; import co.elastic.apm.agent.impl.transaction.AbstractSpan; import co.elastic.apm.agent.impl.transaction.Id; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/MetricSetSerializationTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/MetricSetSerializationTest.java index 7f696af5f1..1399acf058 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/MetricSetSerializationTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/MetricSetSerializationTest.java @@ -20,7 +20,7 @@ import co.elastic.apm.agent.configuration.MetricsConfiguration; import co.elastic.apm.agent.tracer.service.ServiceInfo; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricCollector; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.metrics.MetricsProvider; diff --git a/apm-agent-core/src/test/resources/META-INF/services/co.elastic.apm.agent.context.LifecycleListener b/apm-agent-core/src/test/resources/META-INF/services/co.elastic.apm.agent.tracer.LifecycleListener similarity index 100% rename from apm-agent-core/src/test/resources/META-INF/services/co.elastic.apm.agent.context.LifecycleListener rename to apm-agent-core/src/test/resources/META-INF/services/co.elastic.apm.agent.tracer.LifecycleListener diff --git a/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml b/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml index e61eda6307..d7e58d8a3b 100644 --- a/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml +++ b/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml @@ -16,13 +16,6 @@ - - - ${project.groupId} - apm-agent-core - ${project.version} - - co.elastic.logging diff --git a/apm-agent-plugins/apm-jms-plugin/apm-jms-jakarta/src/test/java/co/elastic/apm/agent/jms/jakarta/JmsInstrumentationIT.java b/apm-agent-plugins/apm-jms-plugin/apm-jms-jakarta/src/test/java/co/elastic/apm/agent/jms/jakarta/JmsInstrumentationIT.java index 8e57ce385b..af97224947 100644 --- a/apm-agent-plugins/apm-jms-plugin/apm-jms-jakarta/src/test/java/co/elastic/apm/agent/jms/jakarta/JmsInstrumentationIT.java +++ b/apm-agent-plugins/apm-jms-plugin/apm-jms-jakarta/src/test/java/co/elastic/apm/agent/jms/jakarta/JmsInstrumentationIT.java @@ -24,8 +24,8 @@ import co.elastic.apm.agent.configuration.CoreConfiguration; import co.elastic.apm.agent.impl.TracerInternalApiUtils; import co.elastic.apm.agent.impl.context.Headers; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; -import co.elastic.apm.agent.impl.sampling.Sampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.Sampler; import co.elastic.apm.agent.impl.transaction.Id; import co.elastic.apm.agent.impl.transaction.Span; import co.elastic.apm.agent.impl.transaction.TraceContext; diff --git a/apm-agent-plugins/apm-jms-plugin/apm-jms-javax/src/test/java/co/elastic/apm/agent/jms/javax/JmsInstrumentationIT.java b/apm-agent-plugins/apm-jms-plugin/apm-jms-javax/src/test/java/co/elastic/apm/agent/jms/javax/JmsInstrumentationIT.java index b7d4d4df51..969ef2717e 100644 --- a/apm-agent-plugins/apm-jms-plugin/apm-jms-javax/src/test/java/co/elastic/apm/agent/jms/javax/JmsInstrumentationIT.java +++ b/apm-agent-plugins/apm-jms-plugin/apm-jms-javax/src/test/java/co/elastic/apm/agent/jms/javax/JmsInstrumentationIT.java @@ -24,8 +24,8 @@ import co.elastic.apm.agent.configuration.CoreConfiguration; import co.elastic.apm.agent.impl.TracerInternalApiUtils; import co.elastic.apm.agent.impl.context.Headers; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; -import co.elastic.apm.agent.impl.sampling.Sampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.Sampler; import co.elastic.apm.agent.impl.transaction.Id; import co.elastic.apm.agent.impl.transaction.Span; import co.elastic.apm.agent.impl.transaction.TraceContext; diff --git a/apm-agent-plugins/apm-jmx-plugin/pom.xml b/apm-agent-plugins/apm-jmx-plugin/pom.xml index db560509a5..989ddb4d36 100644 --- a/apm-agent-plugins/apm-jmx-plugin/pom.xml +++ b/apm-agent-plugins/apm-jmx-plugin/pom.xml @@ -15,13 +15,4 @@ ${project.basedir}/../.. - - - - ${project.groupId} - apm-agent-core - ${project.version} - - - diff --git a/apm-agent-plugins/apm-jmx-plugin/src/main/java/co/elastic/apm/agent/jmx/JmxMetric.java b/apm-agent-plugins/apm-jmx-plugin/src/main/java/co/elastic/apm/agent/jmx/JmxMetric.java index 7427494bad..84bbcc5b59 100644 --- a/apm-agent-plugins/apm-jmx-plugin/src/main/java/co/elastic/apm/agent/jmx/JmxMetric.java +++ b/apm-agent-plugins/apm-jmx-plugin/src/main/java/co/elastic/apm/agent/jmx/JmxMetric.java @@ -18,12 +18,11 @@ */ package co.elastic.apm.agent.jmx; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.Labels; import org.stagemonitor.configuration.converter.AbstractValueConverter; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import java.util.ArrayList; diff --git a/apm-agent-plugins/apm-jmx-plugin/src/main/java/co/elastic/apm/agent/jmx/JmxMetricTracker.java b/apm-agent-plugins/apm-jmx-plugin/src/main/java/co/elastic/apm/agent/jmx/JmxMetricTracker.java index 300cbb22de..d1c862ffb6 100644 --- a/apm-agent-plugins/apm-jmx-plugin/src/main/java/co/elastic/apm/agent/jmx/JmxMetricTracker.java +++ b/apm-agent-plugins/apm-jmx-plugin/src/main/java/co/elastic/apm/agent/jmx/JmxMetricTracker.java @@ -18,15 +18,14 @@ */ package co.elastic.apm.agent.jmx; -import co.elastic.apm.agent.context.AbstractLifecycleListener; -import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.metrics.DoubleSupplier; -import co.elastic.apm.agent.metrics.Labels; -import co.elastic.apm.agent.metrics.MetricRegistry; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.tracer.GlobalLocks; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import org.stagemonitor.configuration.ConfigurationOption; import javax.annotation.Nullable; @@ -60,18 +59,18 @@ public class JmxMetricTracker extends AbstractLifecycleListener { private volatile Thread logManagerPropertyPoller; @Nullable private volatile MBeanServer server; + private final ReportingTracer tracer; private final JmxConfiguration jmxConfiguration; - private final MetricRegistry metricRegistry; @Nullable private volatile NotificationListener listener; - public JmxMetricTracker(ElasticApmTracer tracer) { + public JmxMetricTracker(ReportingTracer tracer) { + this.tracer = tracer; jmxConfiguration = tracer.getConfig(JmxConfiguration.class); - metricRegistry = tracer.getMetricRegistry(); } @Override - public void start(ElasticApmTracer tracer) { + public void start() { ConfigurationOption.ChangeListener> captureJmxListener = new ConfigurationOption.ChangeListener>() { @Override public void onChange(ConfigurationOption configurationOption, List oldValue, List newValue) { @@ -176,10 +175,10 @@ public void onChange(ConfigurationOption configurationOption, List List newRegistrations = compileJmxMetricRegistrations(newValue, platformMBeanServer); for (JmxMetricRegistration addedRegistration : removeAll(oldRegistrations, newRegistrations)) { - addedRegistration.register(platformMBeanServer, metricRegistry); + addedRegistration.register(platformMBeanServer, tracer); } for (JmxMetricRegistration deletedRegistration : removeAll(newRegistrations, oldRegistrations)) { - deletedRegistration.unregister(metricRegistry); + deletedRegistration.unregister(tracer); } } @@ -279,7 +278,7 @@ private static List removeAll(List removeFromThis, List toRemove) { private void register(List jmxMetrics, MBeanServer server) { for (JmxMetricRegistration registration : compileJmxMetricRegistrations(jmxMetrics, server)) { - registration.register(server, metricRegistry); + registration.register(server, tracer); } } @@ -360,9 +359,9 @@ private JmxMetricRegistration(String metricName, Labels labels, String jmxAttrib } - void register(final MBeanServer server, final MetricRegistry metricRegistry) { + void register(final MBeanServer server, final ReportingTracer tracer) { logger.debug("Registering JMX metric {} {}.{} as metric_name: {} labels: {}", objectName, jmxAttribute, compositeDataKey, metricName, labels); - metricRegistry.add(metricName, labels, new DoubleSupplier() { + tracer.addMetric(metricName, labels, new DoubleSupplier() { @Override public double get() { try { @@ -372,7 +371,7 @@ public double get() { return ((Number) ((CompositeData) server.getAttribute(objectName, jmxAttribute)).get(compositeDataKey)).doubleValue(); } } catch (InstanceNotFoundException | AttributeNotFoundException e) { - unregister(metricRegistry); + unregister(tracer); return Double.NaN; } catch (Exception e) { return Double.NaN; @@ -381,9 +380,9 @@ public double get() { }); } - void unregister(MetricRegistry metricRegistry) { + void unregister(ReportingTracer tracer) { logger.debug("Unregistering JMX metric {} {}.{} metric_name: {} labels: {}", objectName, jmxAttribute, compositeDataKey, metricName, labels); - metricRegistry.removeGauge(metricName, labels); + tracer.removeMetric(metricName, labels); } @Override diff --git a/apm-agent-plugins/apm-jmx-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.context.LifecycleListener b/apm-agent-plugins/apm-jmx-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.tracer.LifecycleListener similarity index 100% rename from apm-agent-plugins/apm-jmx-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.context.LifecycleListener rename to apm-agent-plugins/apm-jmx-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.tracer.LifecycleListener diff --git a/apm-agent-plugins/apm-jmx-plugin/src/test/java/co/elastic/apm/agent/jmx/JmxMetricTrackerTest.java b/apm-agent-plugins/apm-jmx-plugin/src/test/java/co/elastic/apm/agent/jmx/JmxMetricTrackerTest.java index 17fa88bae5..cc7aebbd30 100644 --- a/apm-agent-plugins/apm-jmx-plugin/src/test/java/co/elastic/apm/agent/jmx/JmxMetricTrackerTest.java +++ b/apm-agent-plugins/apm-jmx-plugin/src/test/java/co/elastic/apm/agent/jmx/JmxMetricTrackerTest.java @@ -21,7 +21,7 @@ import co.elastic.apm.agent.MockTracer; import co.elastic.apm.agent.configuration.SpyConfiguration; import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.metrics.Labels; +import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.report.serialize.MetricRegistrySerializer; import org.junit.jupiter.api.AfterEach; diff --git a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/test/java/co/elastic/apm/agent/kafka/KafkaIT.java b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/test/java/co/elastic/apm/agent/kafka/KafkaIT.java index 48508ca34c..de2b196fec 100644 --- a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/test/java/co/elastic/apm/agent/kafka/KafkaIT.java +++ b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/test/java/co/elastic/apm/agent/kafka/KafkaIT.java @@ -28,8 +28,8 @@ import co.elastic.apm.agent.impl.context.Message; import co.elastic.apm.agent.impl.context.SpanContext; import co.elastic.apm.agent.impl.context.TransactionContext; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; -import co.elastic.apm.agent.impl.sampling.Sampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.Sampler; import co.elastic.apm.agent.impl.transaction.Span; import co.elastic.apm.agent.impl.transaction.TraceContext; import co.elastic.apm.agent.impl.transaction.Transaction; diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/error/JulLoggerErrorCapturingInstrumentation.java b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/error/JulLoggerErrorCapturingInstrumentation.java index 744956f7c4..7357599636 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/error/JulLoggerErrorCapturingInstrumentation.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/error/JulLoggerErrorCapturingInstrumentation.java @@ -18,7 +18,6 @@ */ package co.elastic.apm.agent.jul.error; -import co.elastic.apm.agent.impl.Tracer; import co.elastic.apm.agent.loginstr.error.AbstractLoggerErrorCapturingInstrumentation; import co.elastic.apm.agent.loginstr.error.LoggerErrorHelper; import net.bytebuddy.asm.Advice; diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/reformatting/AbstractJulEcsReformattingHelper.java b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/reformatting/AbstractJulEcsReformattingHelper.java index 7e0eb6fd25..a9434394ad 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/reformatting/AbstractJulEcsReformattingHelper.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/reformatting/AbstractJulEcsReformattingHelper.java @@ -21,10 +21,10 @@ import co.elastic.apm.agent.jul.sending.JulLogSenderHandler; import co.elastic.apm.agent.loginstr.correlation.CorrelationIdMapAdapter; import co.elastic.apm.agent.loginstr.reformatting.AbstractEcsReformattingHelper; -import co.elastic.apm.agent.report.Reporter; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.sdk.internal.util.LoggerUtils; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import co.elastic.logging.AdditionalField; import co.elastic.logging.jul.EcsFormatter; @@ -151,8 +151,8 @@ private static FileHandler doCreateFileHandler(String pattern, int maxLogFileSiz protected abstract boolean isFileHandler(Handler originalHandler); @Override - protected T createAndStartLogSendingAppender(Reporter reporter, Formatter formatter) { - return (T) new JulLogSenderHandler(reporter, formatter); + protected T createAndStartLogSendingAppender(ReportingTracer tracer, Formatter formatter) { + return (T) new JulLogSenderHandler(tracer, formatter); } @Override diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/sending/JulLogSenderHandler.java b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/sending/JulLogSenderHandler.java index 58fcf82b81..08922e9640 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/sending/JulLogSenderHandler.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/src/main/java/co/elastic/apm/agent/jul/sending/JulLogSenderHandler.java @@ -18,24 +18,24 @@ */ package co.elastic.apm.agent.jul.sending; -import co.elastic.apm.agent.report.Reporter; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import java.util.logging.Formatter; import java.util.logging.Handler; import java.util.logging.LogRecord; public class JulLogSenderHandler extends Handler { - private final Reporter reporter; + private final ReportingTracer tracer; private final Formatter formatter; - public JulLogSenderHandler(Reporter reporter, Formatter formatter) { - this.reporter = reporter; + public JulLogSenderHandler(ReportingTracer tracer, Formatter formatter) { + this.tracer = tracer; this.formatter = formatter; } @Override public void publish(LogRecord record) { - reporter.reportLog(formatter.format(record)); + tracer.reportLog(formatter.format(record)); } @Override diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/src/main/java/co/elastic/apm/agent/log4j1/reformatting/Log4J1EcsReformattingHelper.java b/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/src/main/java/co/elastic/apm/agent/log4j1/reformatting/Log4J1EcsReformattingHelper.java index f70bbd550b..33bebb273b 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/src/main/java/co/elastic/apm/agent/log4j1/reformatting/Log4J1EcsReformattingHelper.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/src/main/java/co/elastic/apm/agent/log4j1/reformatting/Log4J1EcsReformattingHelper.java @@ -22,9 +22,9 @@ import co.elastic.apm.agent.loginstr.reformatting.AbstractEcsReformattingHelper; import co.elastic.apm.agent.loginstr.reformatting.Utils; -import co.elastic.apm.agent.report.Reporter; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import co.elastic.logging.log4j.EcsLayout; import org.apache.log4j.Appender; import org.apache.log4j.FileAppender; @@ -112,8 +112,8 @@ protected void closeShadeAppender(WriterAppender shadeAppender) { } @Override - protected Appender createAndStartLogSendingAppender(Reporter reporter, Layout formatter) { - return new LogSenderAppender(reporter, formatter); + protected Appender createAndStartLogSendingAppender(ReportingTracer tracer, Layout formatter) { + return new LogSenderAppender(tracer, formatter); } @Override diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/src/main/java/co/elastic/apm/agent/log4j1/sending/LogSenderAppender.java b/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/src/main/java/co/elastic/apm/agent/log4j1/sending/LogSenderAppender.java index ae1c66987f..f82fb4043a 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/src/main/java/co/elastic/apm/agent/log4j1/sending/LogSenderAppender.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/src/main/java/co/elastic/apm/agent/log4j1/sending/LogSenderAppender.java @@ -18,17 +18,17 @@ */ package co.elastic.apm.agent.log4j1.sending; -import co.elastic.apm.agent.report.Reporter; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.Layout; import org.apache.log4j.spi.LoggingEvent; public class LogSenderAppender extends AppenderSkeleton { - private final Reporter reporter; + private final ReportingTracer tracer; private final Layout formatter; - public LogSenderAppender(Reporter reporter, Layout formatter) { - this.reporter = reporter; + public LogSenderAppender(ReportingTracer tracer, Layout formatter) { + this.tracer = tracer; this.formatter = formatter; } @@ -39,7 +39,7 @@ public synchronized void doAppend(LoggingEvent event) { @Override protected void append(LoggingEvent event) { - reporter.reportLog(formatter.format(event)); + tracer.reportLog(formatter.format(event)); } @Override diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/Log4j2_7PlusLogCorrelationHelper.java b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/Log4j2_7PlusLogCorrelationHelper.java index 0551af209a..fd0b2ac813 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/Log4j2_7PlusLogCorrelationHelper.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/Log4j2_7PlusLogCorrelationHelper.java @@ -19,7 +19,6 @@ package co.elastic.apm.agent.log4j2.correlation; import co.elastic.apm.agent.tracer.GlobalTracer; -import co.elastic.apm.agent.impl.error.ErrorCapture; import co.elastic.apm.agent.loginstr.correlation.AbstractLogCorrelationHelper; import co.elastic.apm.agent.loginstr.correlation.CorrelationIdMapAdapter; import co.elastic.apm.agent.tracer.Tracer; diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/reformatting/Log4J2EcsReformattingHelper.java b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/reformatting/Log4J2EcsReformattingHelper.java index a9c7f519bc..c5871947b3 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/reformatting/Log4J2EcsReformattingHelper.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/reformatting/Log4J2EcsReformattingHelper.java @@ -21,9 +21,9 @@ import co.elastic.apm.agent.log4j2.sending.Log4j2LogSenderAppender; import co.elastic.apm.agent.loginstr.reformatting.AbstractEcsReformattingHelper; import co.elastic.apm.agent.loginstr.reformatting.Utils; -import co.elastic.apm.agent.report.Reporter; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import co.elastic.logging.log4j2.EcsLayout; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Layout; @@ -155,8 +155,8 @@ protected void closeShadeAppender(Appender shadeAppender) { } @Override - protected Appender createAndStartLogSendingAppender(Reporter reporter, Layout ecsLayout) { - Log4j2LogSenderAppender appender = new Log4j2LogSenderAppender(reporter, (StringLayout) ecsLayout); + protected Appender createAndStartLogSendingAppender(ReportingTracer tracer, Layout ecsLayout) { + Log4j2LogSenderAppender appender = new Log4j2LogSenderAppender(tracer, (StringLayout) ecsLayout); appender.start(); return appender; } diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/sending/Log4j2LogSenderAppender.java b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/sending/Log4j2LogSenderAppender.java index 652d30de3a..6d31e4e892 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/sending/Log4j2LogSenderAppender.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/sending/Log4j2LogSenderAppender.java @@ -18,25 +18,25 @@ */ package co.elastic.apm.agent.log4j2.sending; -import co.elastic.apm.agent.report.Reporter; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.StringLayout; import org.apache.logging.log4j.core.appender.AbstractAppender; public class Log4j2LogSenderAppender extends AbstractAppender { - private final Reporter reporter; + private final ReportingTracer tracer; private final StringLayout ecsLayout; - public Log4j2LogSenderAppender(Reporter reporter, StringLayout ecsLayout) { + public Log4j2LogSenderAppender(ReportingTracer tracer, StringLayout ecsLayout) { super("ElasticApmAppender", null, ecsLayout, true, null); - this.reporter = reporter; + this.tracer = tracer; this.ecsLayout = ecsLayout; } @Override public void append(LogEvent event) { - reporter.reportLog(ecsLayout.toSerializable(event)); + tracer.reportLog(ecsLayout.toSerializable(event)); } } diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-impl/src/main/java/co/elastic/apm/agent/logback/reformatting/LogbackEcsReformattingHelper.java b/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-impl/src/main/java/co/elastic/apm/agent/logback/reformatting/LogbackEcsReformattingHelper.java index 6ebb056352..67c1120486 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-impl/src/main/java/co/elastic/apm/agent/logback/reformatting/LogbackEcsReformattingHelper.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-impl/src/main/java/co/elastic/apm/agent/logback/reformatting/LogbackEcsReformattingHelper.java @@ -32,9 +32,9 @@ import co.elastic.apm.agent.loginstr.reformatting.AbstractEcsReformattingHelper; import co.elastic.apm.agent.loginstr.reformatting.Utils; import co.elastic.apm.agent.common.util.WildcardMatcher; -import co.elastic.apm.agent.report.Reporter; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import co.elastic.logging.AdditionalField; import co.elastic.logging.logback.EcsEncoder; @@ -158,8 +158,8 @@ protected void closeShadeAppender(OutputStreamAppender shadeAppen } @Override - protected Appender createAndStartLogSendingAppender(Reporter reporter, Encoder formatter) { - LogbackLogSenderAppender appender = new LogbackLogSenderAppender(reporter, formatter); + protected Appender createAndStartLogSendingAppender(ReportingTracer tracer, Encoder formatter) { + LogbackLogSenderAppender appender = new LogbackLogSenderAppender(tracer, formatter); appender.start(); return appender; } diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-impl/src/main/java/co/elastic/apm/agent/logback/sending/LogbackLogSenderAppender.java b/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-impl/src/main/java/co/elastic/apm/agent/logback/sending/LogbackLogSenderAppender.java index 3e2e3fea2f..e8e260be47 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-impl/src/main/java/co/elastic/apm/agent/logback/sending/LogbackLogSenderAppender.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-impl/src/main/java/co/elastic/apm/agent/logback/sending/LogbackLogSenderAppender.java @@ -21,15 +21,15 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.UnsynchronizedAppenderBase; import ch.qos.logback.core.encoder.Encoder; -import co.elastic.apm.agent.report.Reporter; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import co.elastic.logging.logback.EcsEncoder; public class LogbackLogSenderAppender extends UnsynchronizedAppenderBase { - private final Reporter reporter; + private final ReportingTracer tracer; private final EcsEncoder formatter; - public LogbackLogSenderAppender(Reporter reporter, Encoder formatter) { - this.reporter = reporter; + public LogbackLogSenderAppender(ReportingTracer tracer, Encoder formatter) { + this.tracer = tracer; // Due to API compatibility (see below in 'append'), we have to use our own formatter type rather than the // base/interface class from logback. if (!(formatter instanceof EcsEncoder)) { @@ -42,6 +42,6 @@ public LogbackLogSenderAppender(Reporter reporter, Encoder format protected void append(ILoggingEvent eventObject) { // the Formatter interface was changed in logback 1.x, but our ECS implementation is compatible with both // older and newer versions of the API so we can rely on the more recent version of the API - reporter.reportLog(formatter.encode(eventObject)); + tracer.reportLog(formatter.encode(eventObject)); } } diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/reformatting/AbstractEcsReformattingHelper.java b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/reformatting/AbstractEcsReformattingHelper.java index 75af126a95..9a1ccb23b9 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/reformatting/AbstractEcsReformattingHelper.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/reformatting/AbstractEcsReformattingHelper.java @@ -18,23 +18,19 @@ */ package co.elastic.apm.agent.loginstr.reformatting; -import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.tracer.GlobalTracer; -import co.elastic.apm.agent.impl.metadata.Service; -import co.elastic.apm.agent.impl.metadata.ServiceFactory; import co.elastic.apm.agent.tracer.configuration.LogEcsReformatting; import co.elastic.apm.agent.common.util.WildcardMatcher; -import co.elastic.apm.agent.report.Reporter; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.sdk.state.CallDepth; import co.elastic.apm.agent.sdk.state.GlobalState; import co.elastic.apm.agent.sdk.weakconcurrent.WeakConcurrent; import co.elastic.apm.agent.sdk.weakconcurrent.WeakMap; -import co.elastic.apm.agent.tracer.Tracer; import co.elastic.apm.agent.tracer.configuration.CoreConfiguration; import co.elastic.apm.agent.tracer.configuration.LoggingConfiguration; import co.elastic.apm.agent.tracer.configuration.ServerlessConfiguration; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import javax.annotation.Nullable; import java.util.List; @@ -152,6 +148,8 @@ public abstract class AbstractEcsReformattingHelper { */ private static final ThreadLocal configForCurrentLogEvent = new ThreadLocal<>(); + private final ReportingTracer tracer; + private final LoggingConfiguration loggingConfiguration; @Nullable @@ -168,26 +166,22 @@ public abstract class AbstractEcsReformattingHelper { @Nullable private final Map additionalFields; - private final Reporter reporter; public AbstractEcsReformattingHelper() { - Tracer tracer = GlobalTracer.get(); + tracer = GlobalTracer.get().require(ReportingTracer.class); loggingConfiguration = tracer.getConfig(LoggingConfiguration.class); additionalFields = loggingConfiguration.getLogEcsReformattingAdditionalFields(); - Service service = new ServiceFactory().createService( - tracer.getConfig(CoreConfiguration.class), - "", - tracer.getConfig(ServerlessConfiguration.class).runsOnAwsLambda() - ); - globalServiceName = service.getName(); - globalServiceVersion = service.getVersion(); - if (service.getNode() != null) { - configuredServiceNodeName = service.getNode().getName(); + CoreConfiguration config = tracer.getConfig(CoreConfiguration.class); + globalServiceName = config.getServiceName(); + globalServiceVersion = config.getServiceVersion(); + String configuredServiceNodeName = config.getServiceNodeName(); + if (configuredServiceNodeName == null) { + ServerlessConfiguration serverlessConfiguration = tracer.getConfig(ServerlessConfiguration.class); + this.configuredServiceNodeName = serverlessConfiguration.awsLambdaLogStreamName(); } else { - configuredServiceNodeName = null; + this.configuredServiceNodeName = configuredServiceNodeName; } - environment = service.getEnvironment(); - reporter = tracer.require(ElasticApmTracer.class).getReporter(); + environment = config.getEnvironment(); } /** @@ -330,7 +324,7 @@ private Object createAndMapSendingAppenderFor(final A originalAppender) { } sendingAppender = NULL_APPENDER; try { - sendingAppender = createAndStartLogSendingAppender(reporter, createEcsFormatter(originalAppender)); + sendingAppender = createAndStartLogSendingAppender(tracer, createEcsFormatter(originalAppender)); originalAppender2sendingAppender.put(originalAppender, sendingAppender); } catch (Throwable throwable) { logger.warn(String.format("Failed to create ECS shipper appender for log appender %s.%s. " + @@ -538,7 +532,7 @@ protected long getDefaultMaxLogFileSize() { protected abstract void closeShadeAppender(A shadeAppender); - protected abstract B createAndStartLogSendingAppender(Reporter reporter, F formatter); + protected abstract B createAndStartLogSendingAppender(ReportingTracer tracer, F formatter); protected abstract void append(L logEvent, B appender); } diff --git a/apm-agent-plugins/apm-logging-plugin/pom.xml b/apm-agent-plugins/apm-logging-plugin/pom.xml index 760825e2e5..db4083919e 100644 --- a/apm-agent-plugins/apm-logging-plugin/pom.xml +++ b/apm-agent-plugins/apm-logging-plugin/pom.xml @@ -27,13 +27,4 @@ apm-jul-plugin - - - - ${project.groupId} - apm-agent-core - ${project.version} - - - diff --git a/apm-agent-plugins/apm-micrometer-plugin/pom.xml b/apm-agent-plugins/apm-micrometer-plugin/pom.xml index 1939b8ca2f..61b8f25b10 100644 --- a/apm-agent-plugins/apm-micrometer-plugin/pom.xml +++ b/apm-agent-plugins/apm-micrometer-plugin/pom.xml @@ -20,12 +20,6 @@ - - - ${project.groupId} - apm-agent-core - ${project.version} - io.micrometer micrometer-core diff --git a/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/AbstractMicrometerInstrumentation.java b/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/AbstractMicrometerInstrumentation.java index f9ac5ef254..2675ea1937 100644 --- a/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/AbstractMicrometerInstrumentation.java +++ b/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/AbstractMicrometerInstrumentation.java @@ -18,10 +18,10 @@ */ package co.elastic.apm.agent.micrometer; -import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.sdk.ElasticApmInstrumentation; import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import java.util.Collection; import java.util.Collections; @@ -30,7 +30,7 @@ public abstract class AbstractMicrometerInstrumentation extends ElasticApmInstru private static final Tracer tracer = GlobalTracer.get(); - static final MicrometerMetricsReporter reporter = new MicrometerMetricsReporter(tracer.require(ElasticApmTracer.class)); + static final MicrometerMetricsReporter reporter = new MicrometerMetricsReporter(tracer.require(ReportingTracer.class)); public Collection getInstrumentationGroupNames() { return Collections.singletonList("micrometer"); diff --git a/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/MicrometerMeterRegistrySerializer.java b/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/MicrometerMeterRegistrySerializer.java index 683df9632f..2bd44e23ed 100644 --- a/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/MicrometerMeterRegistrySerializer.java +++ b/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/MicrometerMeterRegistrySerializer.java @@ -18,16 +18,14 @@ */ package co.elastic.apm.agent.micrometer; -import co.elastic.apm.agent.report.serialize.DslJsonSerializer; import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.sdk.weakconcurrent.WeakConcurrent; import co.elastic.apm.agent.sdk.weakconcurrent.WeakSet; import co.elastic.apm.agent.tracer.configuration.MetricsConfiguration; -import com.dslplatform.json.DslJson; -import com.dslplatform.json.JsonWriter; -import com.dslplatform.json.NumberConverter; +import co.elastic.apm.agent.tracer.reporting.DataWriter; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.DistributionSummary; import io.micrometer.core.instrument.FunctionCounter; @@ -46,35 +44,35 @@ import java.util.Map; import java.util.concurrent.TimeUnit; -import static com.dslplatform.json.JsonWriter.COMMA; -import static com.dslplatform.json.JsonWriter.OBJECT_END; -import static com.dslplatform.json.JsonWriter.OBJECT_START; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.ARRAY_END; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.ARRAY_START; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.NEXT; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.NEW; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.OBJECT_END; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.OBJECT_START; public class MicrometerMeterRegistrySerializer { - private static final byte NEW_LINE = (byte) '\n'; - private static final int BUFFER_SIZE_LIMIT = 2048; private static final Logger logger = LoggerFactory.getLogger(MicrometerMeterRegistrySerializer.class); - - private final DslJson dslJson = new DslJson<>(new DslJson.Settings<>()); - private final StringBuilder replaceBuilder = new StringBuilder(); private final MetricsConfiguration config; + private final ReportingTracer tracer; private final WeakSet internallyDisabledMeters = WeakConcurrent.buildSet(); private int maxSerializedSize = 512; - public MicrometerMeterRegistrySerializer(MetricsConfiguration config) { + public MicrometerMeterRegistrySerializer(MetricsConfiguration config, ReportingTracer tracer) { this.config = config; + this.tracer = tracer; } Iterable getFailedMeters() { return internallyDisabledMeters; } - public List serialize(final Map metersById, final long epochMicros) { - List serializedMeters = new ArrayList<>(); + public List serialize(final Map metersById, final long epochMicros) { + List serializedMeters = new ArrayList<>(); final Map, List> metersGroupedByTags = new HashMap<>(); for (Map.Entry entry : metersById.entrySet()) { List tags = entry.getKey().getTags(); @@ -86,29 +84,29 @@ public List serialize(final Map metersById, final l meters.add(entry.getValue()); } for (Map.Entry, List> entry : metersGroupedByTags.entrySet()) { - JsonWriter jw = dslJson.newWriter(maxSerializedSize); - if (serializeMetricSet(entry.getKey(), entry.getValue(), epochMicros, replaceBuilder, jw)) { - serializedMeters.add(jw); - maxSerializedSize = Math.max(Math.min(jw.size(), BUFFER_SIZE_LIMIT), maxSerializedSize); + DataWriter writer = tracer.newWriter(maxSerializedSize); + if (serializeMetricSet(entry.getKey(), entry.getValue(), epochMicros, writer)) { + serializedMeters.add(writer); + maxSerializedSize = Math.max(Math.min(writer.size(), BUFFER_SIZE_LIMIT), maxSerializedSize); } } return serializedMeters; } - boolean serializeMetricSet(List tags, List meters, long epochMicros, StringBuilder replaceBuilder, JsonWriter jw) { + boolean serializeMetricSet(List tags, List meters, long epochMicros, DataWriter writer) { boolean hasSamples = false; boolean dedotMetricName = config.isDedotCustomMetrics(); - jw.writeByte(JsonWriter.OBJECT_START); + writer.writeStructure(OBJECT_START); { - DslJsonSerializer.writeFieldName("metricset", jw); - jw.writeByte(JsonWriter.OBJECT_START); + writer.writeKey("metricset"); + writer.writeStructure(OBJECT_START); { - DslJsonSerializer.writeFieldName("timestamp", jw); - NumberConverter.serialize(epochMicros, jw); - jw.writeByte(JsonWriter.COMMA); - serializeTags(tags, replaceBuilder, jw); - DslJsonSerializer.writeFieldName("samples", jw); - jw.writeByte(JsonWriter.OBJECT_START); + writer.writeKey("timestamp"); + writer.writeValue(epochMicros); + writer.writeStructure(NEXT); + serializeTags(tags, writer); + writer.writeKey("samples"); + writer.writeStructure(OBJECT_START); ClassLoader originalContextCL = PrivilegedActionUtils.getContextClassLoader(Thread.currentThread()); try { @@ -122,25 +120,25 @@ boolean serializeMetricSet(List tags, List meters, long epochMicros, PrivilegedActionUtils.setContextClassLoader(Thread.currentThread(), PrivilegedActionUtils.getClassLoader(meter.getClass())); if (meter instanceof Timer) { Timer timer = (Timer) meter; - hasSamples = serializeTimer(jw, timer.takeSnapshot(), timer.getId(), timer.count(), timer.totalTime(TimeUnit.MICROSECONDS), hasSamples, replaceBuilder, dedotMetricName); + hasSamples = serializeTimer(writer, timer.takeSnapshot(), timer.getId(), timer.count(), timer.totalTime(TimeUnit.MICROSECONDS), hasSamples, dedotMetricName); } else if (meter instanceof FunctionTimer) { FunctionTimer timer = (FunctionTimer) meter; - hasSamples = serializeTimer(jw, null, timer.getId(), (long) timer.count(), timer.totalTime(TimeUnit.MICROSECONDS), hasSamples, replaceBuilder, dedotMetricName); + hasSamples = serializeTimer(writer, null, timer.getId(), (long) timer.count(), timer.totalTime(TimeUnit.MICROSECONDS), hasSamples, dedotMetricName); } else if (meter instanceof LongTaskTimer) { LongTaskTimer timer = (LongTaskTimer) meter; - hasSamples = serializeTimer(jw, timer.takeSnapshot(), timer.getId(), timer.activeTasks(), timer.duration(TimeUnit.MICROSECONDS), hasSamples, replaceBuilder, dedotMetricName); + hasSamples = serializeTimer(writer, timer.takeSnapshot(), timer.getId(), timer.activeTasks(), timer.duration(TimeUnit.MICROSECONDS), hasSamples, dedotMetricName); } else if (meter instanceof DistributionSummary) { DistributionSummary summary = (DistributionSummary) meter; - hasSamples = serializeDistributionSummary(jw, summary.takeSnapshot(), summary.getId(), summary.count(), summary.totalAmount(), hasSamples, replaceBuilder, dedotMetricName); + hasSamples = serializeDistributionSummary(writer, summary.takeSnapshot(), summary.getId(), summary.count(), summary.totalAmount(), hasSamples, dedotMetricName); } else if (meter instanceof Gauge) { Gauge gauge = (Gauge) meter; - hasSamples = serializeValue(gauge.getId(), gauge.value(), hasSamples, jw, replaceBuilder, dedotMetricName); + hasSamples = serializeValue(gauge.getId(), gauge.value(), hasSamples, writer, dedotMetricName); } else if (meter instanceof Counter) { Counter counter = (Counter) meter; - hasSamples = serializeValue(counter.getId(), counter.count(), hasSamples, jw, replaceBuilder, dedotMetricName); + hasSamples = serializeValue(counter.getId(), counter.count(), hasSamples, writer, dedotMetricName); } else if (meter instanceof FunctionCounter) { FunctionCounter counter = (FunctionCounter) meter; - hasSamples = serializeValue(counter.getId(), counter.count(), hasSamples, jw, replaceBuilder, dedotMetricName); + hasSamples = serializeValue(counter.getId(), counter.count(), hasSamples, writer, dedotMetricName); } } catch (Throwable throwable) { String meterName = meter.getId().getName(); @@ -154,56 +152,54 @@ boolean serializeMetricSet(List tags, List meters, long epochMicros, } finally { PrivilegedActionUtils.setContextClassLoader(Thread.currentThread(), originalContextCL); } - jw.writeByte(JsonWriter.OBJECT_END); + writer.writeStructure(OBJECT_END); } - jw.writeByte(JsonWriter.OBJECT_END); + writer.writeStructure(OBJECT_END); } - jw.writeByte(JsonWriter.OBJECT_END); - jw.writeByte(NEW_LINE); + writer.writeStructure(OBJECT_END); + writer.writeStructure(NEW); return hasSamples; } - private static void serializeTags(List tags, StringBuilder replaceBuilder, JsonWriter jw) { + private static void serializeTags(List tags, DataWriter writer) { if (tags.isEmpty()) { return; } - DslJsonSerializer.writeFieldName("tags", jw); - jw.writeByte(OBJECT_START); + writer.writeKey("tags"); + writer.writeStructure(OBJECT_START); for (int i = 0, tagsSize = tags.size(); i < tagsSize; i++) { Tag tag = tags.get(i); if (i > 0) { - jw.writeByte(COMMA); + writer.writeStructure(NEXT); } - DslJsonSerializer.writeStringValue(DslJsonSerializer.sanitizePropertyName(tag.getKey(), replaceBuilder), replaceBuilder, jw); - jw.writeByte(JsonWriter.SEMI); - DslJsonSerializer.writeStringValue(tag.getValue(), replaceBuilder, jw); + writer.writeKey(tag.getKey(), true); + writer.writeValue(tag.getValue(), true); } - jw.writeByte(OBJECT_END); - jw.writeByte(COMMA); + writer.writeStructure(OBJECT_END); + writer.writeStructure(NEXT); } /** * Conditionally serializes a {@link Timer} if the total time is valid, i.e. neither Double.NaN nor +/-Infinite * - * @param jw writer + * @param writer writer * @param histogramSnapshot * @param id meter ID * @param count count * @param totalTime total time * @param hasValue whether a value has already been written - * @param replaceBuilder * @param dedotMetricName * @return true if a value has been written before, including this one; false otherwise */ - private static boolean serializeTimer(JsonWriter jw, HistogramSnapshot histogramSnapshot, Meter.Id id, long count, double totalTime, boolean hasValue, StringBuilder replaceBuilder, boolean dedotMetricName) { + private static boolean serializeTimer(DataWriter writer, HistogramSnapshot histogramSnapshot, Meter.Id id, long count, double totalTime, boolean hasValue, boolean dedotMetricName) { if (isValidValue(totalTime)) { - if (hasValue) jw.writeByte(JsonWriter.COMMA); - serializeValue(id, ".count", count, jw, replaceBuilder, dedotMetricName); - jw.writeByte(JsonWriter.COMMA); - serializeValue(id, ".sum.us", totalTime, jw, replaceBuilder, dedotMetricName); + if (hasValue) writer.writeStructure(NEXT); + serializeValue(id, ".count", count, writer, dedotMetricName); + writer.writeStructure(NEXT); + serializeValue(id, ".sum.us", totalTime, writer, dedotMetricName); if (histogramSnapshot != null && histogramSnapshot.histogramCounts().length > 0) { - jw.writeByte(JsonWriter.COMMA); - serializeHistogram(id, histogramSnapshot, jw, replaceBuilder, dedotMetricName); + writer.writeStructure(NEXT); + serializeHistogram(id, histogramSnapshot, writer, dedotMetricName); } return true; } @@ -213,78 +209,75 @@ private static boolean serializeTimer(JsonWriter jw, HistogramSnapshot histogram /** * Conditionally serializes a {@link DistributionSummary} if the total amount is valid, i.e. neither Double.NaN nor +/-Infinite * - * @param jw writer + * @param writer writer * @param histogramSnapshot * @param id meter ID * @param count count * @param totalAmount total amount of recorded events * @param hasValue whether a value has already been written - * @param replaceBuilder * @param dedotMetricName * @return true if a value has been written before, including this one; false otherwise */ - private static boolean serializeDistributionSummary(JsonWriter jw, HistogramSnapshot histogramSnapshot, Meter.Id id, long count, double totalAmount, boolean hasValue, StringBuilder replaceBuilder, boolean dedotMetricName) { + private static boolean serializeDistributionSummary(DataWriter writer, HistogramSnapshot histogramSnapshot, Meter.Id id, long count, double totalAmount, boolean hasValue, boolean dedotMetricName) { if (isValidValue(totalAmount)) { - if (hasValue) jw.writeByte(JsonWriter.COMMA); - serializeValue(id, ".count", count, jw, replaceBuilder, dedotMetricName); - jw.writeByte(JsonWriter.COMMA); - serializeValue(id, ".sum", totalAmount, jw, replaceBuilder, dedotMetricName); + if (hasValue) writer.writeStructure(NEXT); + serializeValue(id, ".count", count, writer, dedotMetricName); + writer.writeStructure(NEXT); + serializeValue(id, ".sum", totalAmount, writer, dedotMetricName); if (histogramSnapshot != null && histogramSnapshot.histogramCounts().length > 0) { - jw.writeByte(JsonWriter.COMMA); - serializeHistogram(id, histogramSnapshot, jw, replaceBuilder, dedotMetricName); + writer.writeStructure(NEXT); + serializeHistogram(id, histogramSnapshot, writer, dedotMetricName); } return true; } return hasValue; } - private static void serializeHistogram(Meter.Id id, HistogramSnapshot histogramSnapshot, JsonWriter jw, StringBuilder replaceBuilder, boolean dedotMetricName) { + private static void serializeHistogram(Meter.Id id, HistogramSnapshot histogramSnapshot, DataWriter writer, boolean dedotMetricName) { if (histogramSnapshot == null) { return; } String suffix = ".histogram"; CountAtBucket[] bucket = histogramSnapshot.histogramCounts(); - serializeObjectStart(id.getName(), "values", suffix, jw, replaceBuilder, dedotMetricName); - jw.writeByte(JsonWriter.ARRAY_START); + serializeObjectStart(id.getName(), "values", suffix, writer, dedotMetricName); + writer.writeStructure(ARRAY_START); if (bucket.length > 0) { - NumberConverter.serialize(bucket[0].bucket(), jw); + writer.writeValue(bucket[0].bucket()); for (int i = 1; i < bucket.length; i++) { - jw.writeByte(JsonWriter.COMMA); - NumberConverter.serialize(bucket[i].bucket(), jw); + writer.writeStructure(NEXT); + writer.writeValue(bucket[i].bucket()); } } - jw.writeByte(JsonWriter.ARRAY_END); - jw.writeByte(JsonWriter.COMMA); - jw.writeByte(JsonWriter.QUOTE); - jw.writeAscii("counts"); - jw.writeByte(JsonWriter.QUOTE); - jw.writeByte(JsonWriter.SEMI); - jw.writeByte(JsonWriter.ARRAY_START); + writer.writeStructure(ARRAY_END); + writer.writeStructure(NEXT); + writer.writeKey("counts"); + writer.writeStructure(ARRAY_START); // Micrometer bucket counts are cumulative: E.g. the count at bucket with upper // boundary X is the total number of observations smaller than X // including values which have already been counted for smaller buckets. // Elastic however expects non-cumulative bucket counts if (bucket.length > 0) { - NumberConverter.serialize((long) bucket[0].count(), jw); + writer.writeValue((long) bucket[0].count()); double prevBucketCount = bucket[0].count(); for (int i = 1; i < bucket.length; i++) { - jw.writeByte(JsonWriter.COMMA); - NumberConverter.serialize((long) (bucket[i].count() - prevBucketCount), jw); + writer.writeStructure(NEXT); + writer.writeValue((long) (bucket[i].count() - prevBucketCount)); prevBucketCount = bucket[i].count(); } } - jw.writeByte(JsonWriter.ARRAY_END); + writer.writeStructure(ARRAY_END); - jw.writeByte(JsonWriter.COMMA); - jw.writeAscii("\"type\":\"histogram\""); + writer.writeStructure(NEXT); + writer.writeKey("type"); + writer.writeValue("histogram"); - jw.writeByte(JsonWriter.OBJECT_END); + writer.writeStructure(OBJECT_END); } - private static void serializeValue(Meter.Id id, String suffix, long value, JsonWriter jw, StringBuilder replaceBuilder, boolean dedotMetricName) { - serializeValueStart(id.getName(), suffix, jw, replaceBuilder, dedotMetricName); - NumberConverter.serialize(value, jw); - jw.writeByte(JsonWriter.OBJECT_END); + private static void serializeValue(Meter.Id id, String suffix, long value, DataWriter writer, boolean dedotMetricName) { + serializeValueStart(id.getName(), suffix, writer, dedotMetricName); + writer.writeValue(value); + writer.writeStructure(OBJECT_END); } /** @@ -293,51 +286,33 @@ private static void serializeValue(Meter.Id id, String suffix, long value, JsonW * @param id meter ID * @param value meter value * @param hasValue whether a value has already been written - * @param jw writer - * @param replaceBuilder + * @param writer writer * @param dedotMetricName * @return true if a value has been written before, including this one; false otherwise */ - private static boolean serializeValue(Meter.Id id, double value, boolean hasValue, JsonWriter jw, StringBuilder replaceBuilder, boolean dedotMetricName) { + private static boolean serializeValue(Meter.Id id, double value, boolean hasValue, DataWriter writer, boolean dedotMetricName) { if (isValidValue(value)) { - if (hasValue) jw.writeByte(JsonWriter.COMMA); - serializeValue(id, "", value, jw, replaceBuilder, dedotMetricName); + if (hasValue) writer.writeStructure(NEXT); + serializeValue(id, "", value, writer, dedotMetricName); return true; } return hasValue; } - private static void serializeValue(Meter.Id id, String suffix, double value, JsonWriter jw, StringBuilder replaceBuilder, boolean dedotMetricName) { - serializeValueStart(id.getName(), suffix, jw, replaceBuilder, dedotMetricName); - NumberConverter.serialize(value, jw); - jw.writeByte(JsonWriter.OBJECT_END); + private static void serializeValue(Meter.Id id, String suffix, double value, DataWriter writer, boolean dedotMetricName) { + serializeValueStart(id.getName(), suffix, writer, dedotMetricName); + writer.writeValue(value); + writer.writeStructure(OBJECT_END); } - private static void serializeValueStart(String key, String suffix, JsonWriter jw, StringBuilder replaceBuilder, boolean dedotMetricName) { - serializeObjectStart(key, "value", suffix, jw, replaceBuilder, dedotMetricName); + private static void serializeValueStart(String key, String suffix, DataWriter writer, boolean dedotMetricName) { + serializeObjectStart(key, "value", suffix, writer, dedotMetricName); } - private static void serializeObjectStart(String key, String objectName, String suffix, JsonWriter jw, StringBuilder replaceBuilder, boolean dedotMetricName) { - replaceBuilder.setLength(0); - if (dedotMetricName) { - DslJsonSerializer.sanitizePropertyName(key, replaceBuilder); - } else { - replaceBuilder.append(key); - } - if (suffix != null) { - if (replaceBuilder.length() == 0) { - replaceBuilder.append(key); - } - replaceBuilder.append(suffix); - } - jw.writeString(replaceBuilder); - - jw.writeByte(JsonWriter.SEMI); - jw.writeByte(JsonWriter.OBJECT_START); - jw.writeByte(JsonWriter.QUOTE); - jw.writeAscii(objectName); - jw.writeByte(JsonWriter.QUOTE); - jw.writeByte(JsonWriter.SEMI); + private static void serializeObjectStart(String key, String objectName, String suffix, DataWriter writer, boolean dedotMetricName) { + writer.writeKey(key, dedotMetricName, suffix); + writer.writeStructure(OBJECT_START); + writer.writeKey(objectName); } private static boolean isValidValue(double value) { diff --git a/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/MicrometerMetricsReporter.java b/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/MicrometerMetricsReporter.java index 3379ce66cd..c18ec24a47 100644 --- a/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/MicrometerMetricsReporter.java +++ b/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/MicrometerMetricsReporter.java @@ -18,17 +18,15 @@ */ package co.elastic.apm.agent.micrometer; -import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.impl.Tracer; import co.elastic.apm.agent.common.util.WildcardMatcher; -import co.elastic.apm.agent.report.Reporter; import co.elastic.apm.agent.sdk.logging.Logger; 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.configuration.MetricsConfiguration; import co.elastic.apm.agent.tracer.configuration.ReporterConfiguration; -import com.dslplatform.json.JsonWriter; +import co.elastic.apm.agent.tracer.reporting.DataWriter; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.composite.CompositeMeterRegistry; @@ -90,21 +88,19 @@ public class MicrometerMetricsReporter implements Runnable, Closeable { private final WeakMap meterRegistries = WeakConcurrent.buildMap(); private final WeakMap configMap = WeakConcurrent.buildMap(); private final MicrometerMeterRegistrySerializer serializer; - private final Reporter reporter; - private final ElasticApmTracer tracer; + private final ReportingTracer tracer; private final AtomicBoolean scheduledReporting = new AtomicBoolean(); private final boolean disableScheduler; - public MicrometerMetricsReporter(ElasticApmTracer tracer) { + public MicrometerMetricsReporter(ReportingTracer tracer) { this(tracer, false); } //constructor split up to have this available for testing - MicrometerMetricsReporter(ElasticApmTracer tracer, boolean disableSchedulerThread) { + MicrometerMetricsReporter(ReportingTracer tracer, boolean disableSchedulerThread) { this.tracer = tracer; - this.reporter = tracer.getReporter(); tracer.addShutdownHook(this); - serializer = new MicrometerMeterRegistrySerializer(tracer.getConfig(MetricsConfiguration.class)); + serializer = new MicrometerMeterRegistrySerializer(tracer.getConfig(MetricsConfiguration.class), tracer); this.disableScheduler = disableSchedulerThread; } @@ -147,7 +143,7 @@ public void run() { //run split up to have this available for testing void run(final long now) { - if (tracer.getState() != Tracer.TracerState.RUNNING) { + if (!tracer.isRunning()) { return; } long metricsIntervalMs = tracer.getConfig(ReporterConfiguration.class).getMetricsIntervalMs(); @@ -189,8 +185,8 @@ void run(final long now) { registry.forEachMeter(meterConsumer); } logger.debug("Reporting {} meters", meterConsumer.meters.size()); - for (JsonWriter serializedMetricSet : serializer.serialize(meterConsumer.meters, now * 1000)) { - reporter.reportMetrics(serializedMetricSet); + for (DataWriter serializedMetricSet : serializer.serialize(meterConsumer.meters, now * 1000)) { + serializedMetricSet.report(); } } diff --git a/apm-agent-plugins/apm-micrometer-plugin/src/test/java/co/elastic/apm/agent/micrometer/MicrometerMeterRegistrySerializerTest.java b/apm-agent-plugins/apm-micrometer-plugin/src/test/java/co/elastic/apm/agent/micrometer/MicrometerMeterRegistrySerializerTest.java index 026936f4fc..f47dc58f5b 100644 --- a/apm-agent-plugins/apm-micrometer-plugin/src/test/java/co/elastic/apm/agent/micrometer/MicrometerMeterRegistrySerializerTest.java +++ b/apm-agent-plugins/apm-micrometer-plugin/src/test/java/co/elastic/apm/agent/micrometer/MicrometerMeterRegistrySerializerTest.java @@ -19,7 +19,11 @@ package co.elastic.apm.agent.micrometer; import co.elastic.apm.agent.configuration.MetricsConfiguration; -import com.dslplatform.json.JsonWriter; +import co.elastic.apm.agent.report.Reporter; +import co.elastic.apm.agent.report.serialize.DslJsonDataWriter; +import co.elastic.apm.agent.tracer.reporting.DataWriter; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; +import com.dslplatform.json.DslJson; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -35,6 +39,8 @@ import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import java.util.ArrayList; import java.util.Collections; @@ -43,7 +49,9 @@ import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class MicrometerMeterRegistrySerializerTest { static MicrometerMeterRegistrySerializer serializer; @@ -51,12 +59,22 @@ public class MicrometerMeterRegistrySerializerTest { @BeforeAll static void setup() { MetricsConfiguration config = mock(MetricsConfiguration.class); - serializer = new MicrometerMeterRegistrySerializer(config); + ReportingTracer tracer = mock(ReportingTracer.class); + Reporter reporter = mock(Reporter.class); + DslJson dslJson = new DslJson<>(new DslJson.Settings<>()); + when(tracer.newWriter(anyInt())).thenAnswer(new Answer() { + @Override + public DataWriter answer(InvocationOnMock invocationOnMock) { + int maxSerializedSize = invocationOnMock.getArgument(0); + return new DslJsonDataWriter(dslJson.newWriter(maxSerializedSize), reporter); + } + }); + serializer = new MicrometerMeterRegistrySerializer(config, tracer); } @Test void serializeEmpty() { - List serialized = serializer.serialize(Collections.emptyMap(), 0); + List serialized = serializer.serialize(Collections.emptyMap(), 0); assertThat(serialized).isEmpty(); } @@ -104,7 +122,7 @@ void serializeOneMeter(TestMeter testMeter) { SimpleMeterRegistry registry = new SimpleMeterRegistry(); testMeter.addToMeterRegistry(registry); testMeter.populateValues(); - List serialized = serializer.serialize(Map.of(testMeter.meter().getId(), testMeter.meter()), 0); + List serialized = serializer.serialize(Map.of(testMeter.meter().getId(), testMeter.meter()), 0); assertThat(serialized.size()).isEqualTo(1); JsonNode jsonNode = readJsonString(serialized.get(0).toString()); testMeter.checkSerialization(jsonNode); @@ -121,7 +139,7 @@ void serializeTwoMeters(TestMeter testMeter1, TestMeter testMeter2) { testMeter2.addToMeterRegistry(registry); testMeter1.populateValues(); testMeter2.populateValues(); - List serialized = serializer.serialize(Map.of( + List serialized = serializer.serialize(Map.of( testMeter1.meter().getId(), testMeter1.meter(), testMeter2.meter().getId(), testMeter2.meter() ), 0); diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/src/main/java/co/elastic/apm/agent/embeddedotel/EmbeddedSdkManager.java b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/src/main/java/co/elastic/apm/agent/embeddedotel/EmbeddedSdkManager.java index 9793bbbe76..0974fdcb06 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/src/main/java/co/elastic/apm/agent/embeddedotel/EmbeddedSdkManager.java +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/src/main/java/co/elastic/apm/agent/embeddedotel/EmbeddedSdkManager.java @@ -18,11 +18,11 @@ */ package co.elastic.apm.agent.embeddedotel; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.embeddedotel.proxy.ProxyMeterProvider; -import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; +import co.elastic.apm.agent.tracer.Tracer; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; @@ -39,15 +39,13 @@ public class EmbeddedSdkManager extends AbstractLifecycleListener { private static final Logger logger = LoggerFactory.getLogger(EmbeddedSdkManager.class); - @Nullable - private ElasticApmTracer tracer; + private final Tracer tracer; @Nullable private volatile SdkMeterProvider sdkInstance; private boolean isShutdown = false; - @Override - public synchronized void start(ElasticApmTracer tracer) throws Exception { + public EmbeddedSdkManager(Tracer tracer) { this.tracer = tracer; } diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/src/main/resources/META-INF/services/co.elastic.apm.agent.context.LifecycleListener b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/src/main/resources/META-INF/services/co.elastic.apm.agent.tracer.LifecycleListener similarity index 100% rename from apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/src/main/resources/META-INF/services/co.elastic.apm.agent.context.LifecycleListener rename to apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/src/main/resources/META-INF/services/co.elastic.apm.agent.tracer.LifecycleListener diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/ElasticOtelMetricsExporter.java b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/ElasticOtelMetricsExporter.java index 941cf14f05..631ac30ad8 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/ElasticOtelMetricsExporter.java +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/ElasticOtelMetricsExporter.java @@ -18,13 +18,12 @@ */ package co.elastic.apm.agent.otelmetricsdk; -import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.report.Reporter; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.sdk.internal.util.ExecutorUtils; import co.elastic.apm.agent.tracer.configuration.MetricsConfiguration; import co.elastic.apm.agent.tracer.configuration.ReporterConfiguration; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.metrics.Aggregation; import io.opentelemetry.sdk.metrics.InstrumentType; @@ -48,13 +47,11 @@ public class ElasticOtelMetricsExporter implements MetricExporter { private final OtelMetricSerializer serializer; - private final Reporter reporter; - - public static void createAndRegisterOn(SdkMeterProviderBuilder builder, ElasticApmTracer tracer) { + public static void createAndRegisterOn(SdkMeterProviderBuilder builder, ReportingTracer tracer) { MetricsConfiguration metricsConfig = tracer.getConfig(MetricsConfiguration.class); ReporterConfiguration reporterConfig = tracer.getConfig(ReporterConfiguration.class); - ElasticOtelMetricsExporter exporter = new ElasticOtelMetricsExporter(tracer.getReporter(), metricsConfig, reporterConfig); + ElasticOtelMetricsExporter exporter = new ElasticOtelMetricsExporter(tracer, metricsConfig, reporterConfig); PeriodicMetricReader metricReader = PeriodicMetricReader.builder(exporter) .setExecutor(ExecutorUtils.createSingleThreadSchedulingDaemonPool("otel-metrics-exporter")) @@ -64,9 +61,8 @@ public static void createAndRegisterOn(SdkMeterProviderBuilder builder, ElasticA builder.registerMetricReader(metricReader); } - private ElasticOtelMetricsExporter(Reporter reporter, MetricsConfiguration metricsConfig, ReporterConfiguration reporterConfig) { - serializer = new OtelMetricSerializer(reporterConfig); - this.reporter = reporter; + private ElasticOtelMetricsExporter(ReportingTracer tracer, MetricsConfiguration metricsConfig, ReporterConfiguration reporterConfig) { + serializer = new OtelMetricSerializer(reporterConfig, tracer); this.defaultHistogramAggregation = Aggregation.explicitBucketHistogram(metricsConfig.getCustomMetricsHistogramBoundaries()); } @@ -79,7 +75,7 @@ public CompletableResultCode export(Collection metrics) { serializer.addValues(metric); } - serializer.flushAndReset(reporter); + serializer.flushAndReset(); return CompletableResultCode.ofSuccess(); } diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/MetricSetSerializer.java b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/MetricSetSerializer.java index de8021c3bd..1ae06fd81e 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/MetricSetSerializer.java +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/MetricSetSerializer.java @@ -18,53 +18,44 @@ */ package co.elastic.apm.agent.otelmetricsdk; -import co.elastic.apm.agent.report.Reporter; -import co.elastic.apm.agent.report.serialize.DslJsonSerializer; -import com.dslplatform.json.BoolConverter; -import com.dslplatform.json.DslJson; -import com.dslplatform.json.JsonWriter; -import com.dslplatform.json.Nullable; -import com.dslplatform.json.NumberConverter; +import co.elastic.apm.agent.tracer.reporting.DataWriter; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.AttributeType; import io.opentelemetry.api.common.Attributes; +import javax.annotation.Nullable; import java.util.List; import java.util.Map; -import static com.dslplatform.json.JsonWriter.ARRAY_END; -import static com.dslplatform.json.JsonWriter.ARRAY_START; -import static com.dslplatform.json.JsonWriter.COMMA; -import static com.dslplatform.json.JsonWriter.OBJECT_END; -import static com.dslplatform.json.JsonWriter.OBJECT_START; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.ARRAY_END; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.ARRAY_START; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.NEXT; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.NEW; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.OBJECT_END; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.OBJECT_START; class MetricSetSerializer { - private static final byte NEW_LINE = '\n'; - private static final int INITIAL_BUFFER_SIZE = 2048; - private static final DslJson DSL_JSON = new DslJson<>(new DslJson.Settings<>()); - - private final StringBuilder replaceBuilder; - private final JsonWriter jw; + private final DataWriter writer; private boolean anySamplesWritten; - public MetricSetSerializer(Attributes attributes, CharSequence instrumentationScopeName, long epochMicros, StringBuilder replaceBuilder) { - this.replaceBuilder = replaceBuilder; + public MetricSetSerializer(ReportingTracer tracer, Attributes attributes, CharSequence instrumentationScopeName, long epochMicros) { anySamplesWritten = false; - jw = DSL_JSON.newWriter(INITIAL_BUFFER_SIZE); - jw.writeByte(JsonWriter.OBJECT_START); + writer = tracer.newWriter(INITIAL_BUFFER_SIZE); + writer.writeStructure(OBJECT_START); { - DslJsonSerializer.writeFieldName("metricset", jw); - jw.writeByte(JsonWriter.OBJECT_START); + writer.writeKey("metricset"); + writer.writeStructure(OBJECT_START); { - DslJsonSerializer.writeFieldName("timestamp", jw); - NumberConverter.serialize(epochMicros, jw); - jw.writeByte(JsonWriter.COMMA); + writer.writeKey("timestamp"); + writer.writeValue(epochMicros); + writer.writeStructure(NEXT); serializeAttributes(instrumentationScopeName, attributes); - DslJsonSerializer.writeFieldName("samples", jw); - jw.writeByte(JsonWriter.OBJECT_START); + writer.writeKey("samples"); + writer.writeStructure(OBJECT_START); } } } @@ -79,19 +70,19 @@ public void addValue(CharSequence metricName, long value) { private void addValue(CharSequence metricName, boolean isDouble, long longVal, double doubleVal) { if (anySamplesWritten) { - jw.writeByte(COMMA); + writer.writeStructure(NEXT); } - serializeFieldKey(metricName); - jw.writeByte(JsonWriter.OBJECT_START); + writer.writeKey(metricName); + writer.writeStructure(OBJECT_START); { - serializeFieldKeyAscii("value"); + writer.writeKey("value"); if (isDouble) { - NumberConverter.serialize(doubleVal, jw); + writer.writeValue(doubleVal); } else { - NumberConverter.serialize(longVal, jw); + writer.writeValue(longVal); } } - jw.writeByte(JsonWriter.OBJECT_END); + writer.writeStructure(OBJECT_END); anySamplesWritten = true; } @@ -101,20 +92,21 @@ public void addExplicitBucketHistogram(CharSequence metricName, List bou return; } if (anySamplesWritten) { - jw.writeByte(COMMA); + writer.writeStructure(NEXT); } - serializeFieldKey(metricName); - jw.writeByte(JsonWriter.OBJECT_START); + writer.writeKey(metricName); + writer.writeStructure(OBJECT_START); { - serializeFieldKeyAscii("values"); + writer.writeKey("values"); convertAndSerializeHistogramBucketBoundaries(boundaries, counts); - jw.writeByte(COMMA); - serializeFieldKeyAscii("counts"); + writer.writeStructure(NEXT); + writer.writeKey("counts"); convertAndSerializeHistogramBucketCounts(counts); - jw.writeByte(COMMA); - jw.writeAscii("\"type\":\"histogram\""); + writer.writeStructure(NEXT); + writer.writeKey("type"); + writer.writeValue("histogram"); } - jw.writeByte(JsonWriter.OBJECT_END); + writer.writeStructure(OBJECT_END); anySamplesWritten = true; } @@ -128,29 +120,29 @@ private boolean isEmptyHistogram(List boundaries, List counts) { } private void convertAndSerializeHistogramBucketCounts(List counts) { - jw.writeByte(ARRAY_START); + writer.writeStructure(ARRAY_START); boolean firstElement = true; for (long count : counts) { if (count != 0) { if (!firstElement) { - jw.writeByte(COMMA); + writer.writeStructure(NEXT); } firstElement = false; - NumberConverter.serialize(count, jw); + writer.writeValue(count); } } - jw.writeByte(ARRAY_END); + writer.writeStructure(ARRAY_END); } private void convertAndSerializeHistogramBucketBoundaries(List boundaries, List counts) { - jw.writeByte(ARRAY_START); + writer.writeStructure(ARRAY_START); boolean firstElement = true; //Bucket boundary conversion algorithm is copied from APM server int bucketCount = counts.size(); for (int i = 0; i < bucketCount; i++) { if (counts.get(i) != 0) { if (!firstElement) { - jw.writeByte(COMMA); + writer.writeStructure(NEXT); } firstElement = false; if (i == 0) { @@ -158,29 +150,17 @@ private void convertAndSerializeHistogramBucketBoundaries(List boundarie if (bounds > 0) { bounds /= 2; } - NumberConverter.serialize(bounds, jw); + writer.writeValue(bounds); } else if (i == bucketCount - 1) { - NumberConverter.serialize(boundaries.get(bucketCount - 2), jw); + writer.writeValue(boundaries.get(bucketCount - 2)); } else { double lower = boundaries.get(i - 1); double upper = boundaries.get(i); - NumberConverter.serialize(lower + (upper - lower) / 2, jw); + writer.writeValue(lower + (upper - lower) / 2); } } } - jw.writeByte(ARRAY_END); - } - - private void serializeFieldKey(CharSequence fieldName) { - jw.writeString(fieldName); - jw.writeByte(JsonWriter.SEMI); - } - - private void serializeFieldKeyAscii(String fieldName) { - jw.writeByte(JsonWriter.QUOTE); - jw.writeAscii(fieldName); - jw.writeByte(JsonWriter.QUOTE); - jw.writeByte(JsonWriter.SEMI); + writer.writeStructure(ARRAY_END); } private void serializeAttributes(CharSequence instrumentationScopeName, Attributes attributes) { @@ -188,12 +168,12 @@ private void serializeAttributes(CharSequence instrumentationScopeName, Attribut if (attributeMap.isEmpty() && instrumentationScopeName.length() == 0) { return; } - DslJsonSerializer.writeFieldName("tags", jw); - jw.writeByte(OBJECT_START); + writer.writeKey("tags"); + writer.writeStructure(OBJECT_START); boolean anyWritten = false; if (instrumentationScopeName.length() > 0) { - jw.writeAscii("\"otel_instrumentation_scope_name\":"); - jw.writeString(instrumentationScopeName); + writer.writeKey("otel_instrumentation_scope_name"); + writer.writeValue(instrumentationScopeName); anyWritten = true; } for (Map.Entry, Object> entry : attributeMap.entrySet()) { @@ -201,31 +181,30 @@ private void serializeAttributes(CharSequence instrumentationScopeName, Attribut Object value = entry.getValue(); anyWritten |= serializeAttribute(key, value, anyWritten); } - jw.writeByte(OBJECT_END); - jw.writeByte(COMMA); + writer.writeStructure(OBJECT_END); + writer.writeStructure(NEXT); } private boolean serializeAttribute(AttributeKey key, @Nullable Object value, boolean prependComma) { if (isValidAttributeValue(key, value)) { if (prependComma) { - jw.writeByte(COMMA); + writer.writeStructure(NEXT); } - DslJsonSerializer.writeStringValue(DslJsonSerializer.sanitizePropertyName(key.getKey(), replaceBuilder), replaceBuilder, jw); - jw.writeByte(JsonWriter.SEMI); + writer.writeKey(key.getKey(), true); AttributeType type = key.getType(); switch (type) { case STRING: - jw.writeString((CharSequence) value); + writer.writeValue((CharSequence) value); return true; case BOOLEAN: - BoolConverter.serialize((Boolean) value, jw); + writer.writeValue((Boolean) value); return true; case LONG: - NumberConverter.serialize(((Number) value).longValue(), jw); + writer.writeValue(((Number) value).longValue()); return true; case DOUBLE: - NumberConverter.serialize(((Number) value).doubleValue(), jw); + writer.writeValue(((Number) value).doubleValue()); return true; case STRING_ARRAY: case BOOLEAN_ARRAY: @@ -266,19 +245,19 @@ private void serializeMetricSetEnd() { { /*"samples":*/ { - jw.writeByte(JsonWriter.OBJECT_END); + writer.writeStructure(OBJECT_END); } } - jw.writeByte(JsonWriter.OBJECT_END); + writer.writeStructure(OBJECT_END); } - jw.writeByte(JsonWriter.OBJECT_END); - jw.writeByte(NEW_LINE); + writer.writeStructure(OBJECT_END); + writer.writeStructure(NEW); } - public void finishAndReport(Reporter reporter) { + public void finishAndReport() { if (anySamplesWritten) { serializeMetricSetEnd(); - reporter.reportMetrics(jw); + writer.report(); } } } diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/OtelMetricSerializer.java b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/OtelMetricSerializer.java index 70b9040fb6..525635315f 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/OtelMetricSerializer.java +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/OtelMetricSerializer.java @@ -19,10 +19,10 @@ package co.elastic.apm.agent.otelmetricsdk; import co.elastic.apm.agent.common.util.WildcardMatcher; -import co.elastic.apm.agent.report.Reporter; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.tracer.configuration.ReporterConfiguration; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.data.Data; @@ -43,8 +43,7 @@ public class OtelMetricSerializer { private static final Logger logger = LoggerFactory.getLogger(OtelMetricSerializer.class); private final ReporterConfiguration reporterConfig; - private final StringBuilder serializationTempBuilder; - + private final ReportingTracer tracer; private final Set metricsWithBadAggregations = Collections.newSetFromMap(new ConcurrentHashMap<>()); private final Map> metricSets; @@ -52,10 +51,10 @@ public class OtelMetricSerializer { @Nullable private InstrumentationScopeAndTimestamp lastCreatedInstrScopeAndTimestamp; - public OtelMetricSerializer(ReporterConfiguration reporterConfig) { + public OtelMetricSerializer(ReporterConfiguration reporterConfig, ReportingTracer tracer) { this.reporterConfig = reporterConfig; + this.tracer = tracer; metricSets = new HashMap<>(); - serializationTempBuilder = new StringBuilder(); } public void addValues(MetricData metric) { @@ -150,16 +149,16 @@ private MetricSetSerializer getOrCreateMetricSet(CharSequence instrScopeName, lo MetricSetSerializer ms = timestampMetricSets.get(attributes); if (ms == null) { - ms = new MetricSetSerializer(attributes, key.instrumentationScopeName, key.timestamp, serializationTempBuilder); + ms = new MetricSetSerializer(tracer, attributes, key.instrumentationScopeName, key.timestamp); timestampMetricSets.put(attributes, ms); } return ms; } - public void flushAndReset(Reporter reporter) { + public void flushAndReset() { for (Map map : metricSets.values()) { for (MetricSetSerializer metricSet : map.values()) { - metricSet.finishAndReport(reporter); + metricSet.finishAndReport(); } } metricSets.clear(); diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/SdkMeterProviderBuilderInstrumentation.java b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/SdkMeterProviderBuilderInstrumentation.java index 2cc64c554c..9763ab10b5 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/SdkMeterProviderBuilderInstrumentation.java +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/SdkMeterProviderBuilderInstrumentation.java @@ -18,7 +18,6 @@ */ package co.elastic.apm.agent.otelmetricsdk; -import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.sdk.ElasticApmInstrumentation; import co.elastic.apm.agent.sdk.internal.util.LoggerUtils; import co.elastic.apm.agent.sdk.logging.Logger; @@ -26,6 +25,7 @@ import co.elastic.apm.agent.sdk.weakconcurrent.WeakConcurrent; import co.elastic.apm.agent.sdk.weakconcurrent.WeakSet; import co.elastic.apm.agent.tracer.GlobalTracer; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; import io.opentelemetry.sdk.metrics.export.MetricExporter; import net.bytebuddy.asm.Advice; @@ -74,7 +74,7 @@ public static class SdkMeterProviderBuilderAdvice { private static final Logger unsupportedVersionLogger = LoggerUtils.logOnce(logger); private static final WeakSet ALREADY_REGISTERED_BUILDERS = WeakConcurrent.buildSet(); - private static final ElasticApmTracer tracer = GlobalTracer.get().require(ElasticApmTracer.class); + private static final ReportingTracer tracer = GlobalTracer.get().require(ReportingTracer.class); @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) public static void onEnter(@Advice.This SdkMeterProviderBuilder thiz) { diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/src/test/java/co/elastic/apm/agent/opentelemetry/tracing/OTelSpanLinkTest.java b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/src/test/java/co/elastic/apm/agent/opentelemetry/tracing/OTelSpanLinkTest.java index ea1a8b10b0..c2913c7d28 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/src/test/java/co/elastic/apm/agent/opentelemetry/tracing/OTelSpanLinkTest.java +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/src/test/java/co/elastic/apm/agent/opentelemetry/tracing/OTelSpanLinkTest.java @@ -20,7 +20,7 @@ import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.impl.ElasticApmTracerBuilder; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; import co.elastic.apm.agent.impl.transaction.TraceContext; import co.elastic.apm.agent.opentelemetry.global.ElasticOpenTelemetry; import io.opentelemetry.api.common.Attributes; diff --git a/apm-agent-plugins/apm-opentracing-plugin/pom.xml b/apm-agent-plugins/apm-opentracing-plugin/pom.xml index 83d1f96d9c..16c40373bc 100644 --- a/apm-agent-plugins/apm-opentracing-plugin/pom.xml +++ b/apm-agent-plugins/apm-opentracing-plugin/pom.xml @@ -15,13 +15,4 @@ ${project.basedir}/../.. - - - - ${project.groupId} - apm-agent-core - ${project.version} - - - diff --git a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ApmScopeInstrumentation.java b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ApmScopeInstrumentation.java index e3becb8cca..a8dce508d2 100644 --- a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ApmScopeInstrumentation.java +++ b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ApmScopeInstrumentation.java @@ -18,7 +18,7 @@ */ package co.elastic.apm.agent.opentracingimpl; -import co.elastic.apm.agent.impl.transaction.AbstractSpan; +import co.elastic.apm.agent.tracer.AbstractSpan; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; diff --git a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ApmSpanBuilderInstrumentation.java b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ApmSpanBuilderInstrumentation.java index b343ba3fe0..087df0e936 100644 --- a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ApmSpanBuilderInstrumentation.java +++ b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ApmSpanBuilderInstrumentation.java @@ -18,13 +18,13 @@ */ package co.elastic.apm.agent.opentracingimpl; -import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; -import co.elastic.apm.agent.impl.sampling.Sampler; -import co.elastic.apm.agent.impl.transaction.AbstractSpan; -import co.elastic.apm.agent.impl.transaction.TraceContext; -import co.elastic.apm.agent.impl.transaction.Transaction; import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; +import co.elastic.apm.agent.tracer.AbstractSpan; +import co.elastic.apm.agent.tracer.Transaction; +import co.elastic.apm.agent.tracer.direct.AbstractDirectSpan; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.DirectTracer; +import co.elastic.apm.agent.tracer.direct.Sampler; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; @@ -76,29 +76,26 @@ public static Object createSpan(@Advice.Argument(value = 0, typing = Assigner.Ty @Advice.FieldValue(value = "operationName") String operationName, @Advice.FieldValue(value = "microseconds") long microseconds, @Advice.Argument(1) @Nullable Iterable> baggage) { - AbstractSpan parent = null; - if (parentContext instanceof AbstractSpan) { - parent = (AbstractSpan) parentContext; + AbstractDirectSpan parent = null; + if (parentContext instanceof AbstractDirectSpan) { + parent = (AbstractDirectSpan) parentContext; } return doCreateTransactionOrSpan(parent, tags, operationName, microseconds, baggage, PrivilegedActionUtils.getClassLoader(spanBuilderClass)); } @Nullable - public static AbstractSpan doCreateTransactionOrSpan(@Nullable AbstractSpan parentContext, + public static AbstractSpan doCreateTransactionOrSpan(@Nullable AbstractDirectSpan parentContext, Map tags, String operationName, long microseconds, @Nullable Iterable> baggage, ClassLoader applicationClassLoader) { - AbstractSpan result = null; - ElasticApmTracer tracer = OpenTracingBridgeInstrumentation.tracer.require(ElasticApmTracer.class); - if (tracer != null) { - if (parentContext == null) { - result = createTransaction(tags, operationName, microseconds, baggage, tracer, applicationClassLoader); + AbstractSpan result; + if (parentContext == null) { + result = createTransaction(tags, operationName, microseconds, baggage, tracer, applicationClassLoader); + } else { + if (microseconds >= 0) { + result = parentContext.spanChild(microseconds); } else { - if (microseconds >= 0) { - result = tracer.startSpan(TraceContext.fromParent(), parentContext, parentContext.getBaggage(), microseconds); - } else { - result = tracer.startSpan(TraceContext.fromParent(), parentContext, parentContext.getBaggage()); - } + result = parentContext.spanChild(); } } if (result != null) { @@ -117,7 +114,7 @@ public static AbstractSpan doCreateTransactionOrSpan(@Nullable AbstractSpan createTransaction(Map tags, String operationName, long microseconds, - @Nullable Iterable> baggage, ElasticApmTracer tracer, ClassLoader classLoader) { + @Nullable Iterable> baggage, DirectTracer tracer, ClassLoader classLoader) { if ("client".equals(tags.get("span.kind"))) { logger.info("Ignoring transaction '{}', as a span.kind client can never be a transaction. " + "Consider creating a span for the whole request.", operationName); @@ -130,7 +127,7 @@ private static AbstractSpan createTransaction(Map tags, Strin } else { sampler = tracer.getSampler(); } - Transaction transaction = tracer.startChildTransaction(baggage, OpenTracingTextMapBridge.instance(), sampler, microseconds, classLoader); + Transaction transaction = tracer.startChildTransaction(baggage, OpenTracingTextMapBridge.instance(), sampler, microseconds, classLoader); if (transaction != null) { transaction.setFrameworkName(FRAMEWORK_NAME); } diff --git a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ApmSpanInstrumentation.java b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ApmSpanInstrumentation.java index 09a7e4c5b7..dd65ed278d 100644 --- a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ApmSpanInstrumentation.java +++ b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ApmSpanInstrumentation.java @@ -18,10 +18,12 @@ */ package co.elastic.apm.agent.opentracingimpl; +import co.elastic.apm.agent.tracer.AbstractSpan; +import co.elastic.apm.agent.tracer.Transaction; +import co.elastic.apm.agent.tracer.direct.AbstractDirectSpan; +import co.elastic.apm.agent.tracer.direct.DirectSpan; +import co.elastic.apm.agent.tracer.direct.DirectTransaction; import co.elastic.apm.agent.tracer.util.ResultUtil; -import co.elastic.apm.agent.impl.transaction.AbstractSpan; -import co.elastic.apm.agent.impl.transaction.Span; -import co.elastic.apm.agent.impl.transaction.Transaction; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; @@ -31,6 +33,8 @@ import co.elastic.apm.agent.sdk.logging.LoggerFactory; import javax.annotation.Nullable; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Map; import static co.elastic.apm.agent.tracer.AbstractSpan.PRIORITY_USER_SUPPLIED; @@ -66,18 +70,18 @@ public static class AdviceClass { @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) public static void finishInternal(@Advice.FieldValue(value = "dispatcher", typing = Assigner.Typing.DYNAMIC) @Nullable Object context, @Advice.Argument(0) long finishMicros) { - if (context instanceof AbstractSpan) { - doFinishInternal((AbstractSpan) context, finishMicros); + if (context instanceof AbstractDirectSpan) { + doFinishInternal((AbstractDirectSpan) context, finishMicros); } } - public static void doFinishInternal(AbstractSpan abstractSpan, long finishMicros) { + public static void doFinishInternal(AbstractDirectSpan abstractSpan, long finishMicros) { abstractSpan.incrementReferences(); - if (abstractSpan instanceof Transaction) { - Transaction transaction = (Transaction) abstractSpan; + if (abstractSpan instanceof Transaction) { + Transaction transaction = (Transaction) abstractSpan; if (transaction.getType() == null) { if (transaction.getContext().getRequest().hasContent()) { - transaction.withType(co.elastic.apm.agent.tracer.Transaction.TYPE_REQUEST); + transaction.withType(Transaction.TYPE_REQUEST); } } } @@ -119,13 +123,13 @@ public static void log(@Advice.FieldValue(value = "dispatcher", typing = Assigne @Advice.Argument(0) long epochTimestampMicros, @Advice.Argument(1) Map fields) { - if (context instanceof AbstractSpan) { - AbstractSpan span = (AbstractSpan) context; + if (context instanceof AbstractDirectSpan) { + AbstractDirectSpan span = (AbstractDirectSpan) context; if ("error".equals(fields.get("event"))) { final Object errorObject = fields.get("error.object"); if (errorObject instanceof Throwable) { if (epochTimestampMicros > 0) { - span.captureExceptionAndGetErrorId(epochTimestampMicros, (Throwable) errorObject); + span.captureException((Throwable) errorObject, epochTimestampMicros); } else { span.captureException((Throwable) errorObject); } @@ -152,28 +156,28 @@ public static void handleTag(@Advice.FieldValue(value = "dispatcher", typing = A if (value == null) { return; } - if (abstractSpanObj instanceof Transaction) { - handleTransactionTag((Transaction) abstractSpanObj, key, value); - } else if (abstractSpanObj instanceof Span) { - handleSpanTag((Span) abstractSpanObj, key, value); + if (abstractSpanObj instanceof DirectTransaction) { + handleTransactionTag((DirectTransaction) abstractSpanObj, key, value); + } else if (abstractSpanObj instanceof DirectSpan) { + handleSpanTag((DirectSpan) abstractSpanObj, key, value); } else { logger.warn("Calling setTag on an already finished span"); } } - private static void handleTransactionTag(Transaction transaction, String key, Object value) { + private static void handleTransactionTag(DirectTransaction transaction, String key, Object value) { if (!handleSpecialTransactionTag(transaction, key, value)) { addTag(transaction, key, value); } } - private static void handleSpanTag(Span span, String key, Object value) { + private static void handleSpanTag(DirectSpan span, String key, Object value) { if (!handleSpecialSpanTag(span, key, value)) { addTag(span, key, value); } } - private static void addTag(AbstractSpan transaction, String key, Object value) { + private static void addTag(AbstractDirectSpan transaction, String key, Object value) { if (value instanceof Number) { transaction.addLabel(key, (Number) value); } else if (value instanceof Boolean) { @@ -185,7 +189,7 @@ private static void addTag(AbstractSpan transaction, String key, Object value // unfortunately, we can't use the constants in io.opentracing.tag.Tags, // as we can't declare a direct dependency on the OT API - private static boolean handleSpecialTransactionTag(Transaction transaction, String key, Object value) { + private static boolean handleSpecialTransactionTag(Transaction transaction, String key, Object value) { if ("type".equals(key)) { transaction.withType(value.toString()); return true; @@ -209,7 +213,12 @@ private static boolean handleSpecialTransactionTag(Transaction transaction, Stri transaction.withType(co.elastic.apm.agent.tracer.Transaction.TYPE_REQUEST); return true; } else if ("http.url".equals(key)) { - transaction.getContext().getRequest().getUrl().withFull(value.toString()); + try { + URI uri = new URI(value.toString()); + transaction.getContext().getRequest().getUrl().fillFrom(uri); + } catch (URISyntaxException ignored) { + transaction.getContext().getRequest().getUrl().fillFrom(null, null, 0, null, null); + } transaction.withType(co.elastic.apm.agent.tracer.Transaction.TYPE_REQUEST); return true; } else if ("sampling.priority".equals(key)) { @@ -228,7 +237,7 @@ private static boolean handleSpecialTransactionTag(Transaction transaction, Stri return false; } - private static boolean handleSpecialSpanTag(Span span, String key, Object value) { + private static boolean handleSpecialSpanTag(DirectSpan span, String key, Object value) { //noinspection IfCanBeSwitch if ("type".equals(key)) { if (span.getSubtype() == null && span.getAction() == null) { diff --git a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ElasticApmTracerInstrumentation.java b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ElasticApmTracerInstrumentation.java index fa9e090e80..81e8f30ff2 100644 --- a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ElasticApmTracerInstrumentation.java +++ b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ElasticApmTracerInstrumentation.java @@ -18,7 +18,6 @@ */ package co.elastic.apm.agent.opentracingimpl; -import co.elastic.apm.agent.impl.Tracer; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; @@ -30,7 +29,7 @@ public class ElasticApmTracerInstrumentation extends OpenTracingBridgeInstrument public static class AdviceClass { @Advice.OnMethodExit(suppress = Throwable.class, inline = false) public static void close() { - tracer.require(Tracer.class).stop(); + tracer.stop(); } } diff --git a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ExternalSpanContextInstrumentation.java b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ExternalSpanContextInstrumentation.java index 30a05603d6..cfaa7ab8a9 100644 --- a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ExternalSpanContextInstrumentation.java +++ b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ExternalSpanContextInstrumentation.java @@ -18,8 +18,7 @@ */ package co.elastic.apm.agent.opentracingimpl; -import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.impl.transaction.TraceContext; +import co.elastic.apm.agent.tracer.TraceContext; import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice.AssignReturned.ToFields.ToField; import net.bytebuddy.description.method.MethodDescription; @@ -116,13 +115,6 @@ public static String onExit(@Advice.FieldValue(value = "childTraceContext", typi @Nullable public static TraceContext parseTextMap(Iterable> textMap) { - ElasticApmTracer tracer = OpenTracingBridgeInstrumentation.tracer.require(ElasticApmTracer.class); - if (tracer != null) { - TraceContext childTraceContext = TraceContext.with64BitId(tracer); - if (childTraceContext.asChildOf(textMap, OpenTracingTextMapBridge.instance())) { - return childTraceContext; - } - } - return null; + return tracer.startChildTransaction(textMap, OpenTracingTextMapBridge.instance()); } } diff --git a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/OpenTracingBridgeInstrumentation.java b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/OpenTracingBridgeInstrumentation.java index 383234a543..20c78798e7 100644 --- a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/OpenTracingBridgeInstrumentation.java +++ b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/OpenTracingBridgeInstrumentation.java @@ -21,13 +21,14 @@ import co.elastic.apm.agent.sdk.ElasticApmInstrumentation; import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.direct.DirectTracer; import java.util.Collection; import java.util.Collections; public abstract class OpenTracingBridgeInstrumentation extends ElasticApmInstrumentation { - static final Tracer tracer = GlobalTracer.get(); + static final DirectTracer tracer = GlobalTracer.get().require(DirectTracer.class); @Override public boolean includeWhenInstrumentationIsDisabled() { diff --git a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ScopeManagerInstrumentation.java b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ScopeManagerInstrumentation.java index f0cdce5070..e73d6606f1 100644 --- a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ScopeManagerInstrumentation.java +++ b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ScopeManagerInstrumentation.java @@ -18,7 +18,7 @@ */ package co.elastic.apm.agent.opentracingimpl; -import co.elastic.apm.agent.impl.transaction.AbstractSpan; +import co.elastic.apm.agent.tracer.AbstractSpan; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; diff --git a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/SpanContextInstrumentation.java b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/SpanContextInstrumentation.java index 9d81be2899..d29b7f66f0 100644 --- a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/SpanContextInstrumentation.java +++ b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/SpanContextInstrumentation.java @@ -18,10 +18,10 @@ */ package co.elastic.apm.agent.opentracingimpl; -import co.elastic.apm.agent.impl.transaction.AbstractSpan; -import co.elastic.apm.agent.impl.transaction.ElasticContext; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; +import co.elastic.apm.agent.tracer.AbstractSpan; +import co.elastic.apm.agent.tracer.ElasticContext; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; diff --git a/apm-agent-plugins/apm-profiling-plugin/src/main/java/co/elastic/apm/agent/profiler/ProfilingFactory.java b/apm-agent-plugins/apm-profiling-plugin/src/main/java/co/elastic/apm/agent/profiler/ProfilingFactory.java index 400e28623c..a9573bc6ba 100644 --- a/apm-agent-plugins/apm-profiling-plugin/src/main/java/co/elastic/apm/agent/profiler/ProfilingFactory.java +++ b/apm-agent-plugins/apm-profiling-plugin/src/main/java/co/elastic/apm/agent/profiler/ProfilingFactory.java @@ -18,7 +18,7 @@ */ package co.elastic.apm.agent.profiler; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; public class ProfilingFactory extends AbstractLifecycleListener { @@ -26,7 +26,10 @@ public class ProfilingFactory extends AbstractLifecycleListener { private final SamplingProfiler profiler; private final NanoClock nanoClock; + private final ElasticApmTracer tracer; + public ProfilingFactory(ElasticApmTracer tracer) { + this.tracer = tracer; boolean envTest = false; // in unit tests, where assertions are enabled, this envTest is true assert envTest = true; @@ -35,8 +38,8 @@ public ProfilingFactory(ElasticApmTracer tracer) { } @Override - public void start(ElasticApmTracer tracer) { - profiler.start(tracer); + public void start() { + profiler.start(); tracer.registerSpanListener(new ProfilingActivationListener(tracer, profiler)); } diff --git a/apm-agent-plugins/apm-profiling-plugin/src/main/java/co/elastic/apm/agent/profiler/SamplingProfiler.java b/apm-agent-plugins/apm-profiling-plugin/src/main/java/co/elastic/apm/agent/profiler/SamplingProfiler.java index 1a33248b5a..09f4f6c854 100644 --- a/apm-agent-plugins/apm-profiling-plugin/src/main/java/co/elastic/apm/agent/profiler/SamplingProfiler.java +++ b/apm-agent-plugins/apm-profiling-plugin/src/main/java/co/elastic/apm/agent/profiler/SamplingProfiler.java @@ -19,7 +19,7 @@ package co.elastic.apm.agent.profiler; import co.elastic.apm.agent.common.util.WildcardMatcher; -import co.elastic.apm.agent.context.AbstractLifecycleListener; +import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.impl.transaction.Span; import co.elastic.apm.agent.impl.transaction.StackFrame; @@ -697,7 +697,7 @@ void copyFromFiles(Path activationEvents, Path traces) throws IOException { } @Override - public void start(ElasticApmTracer tracer) { + public void start() { scheduler.submit(this); } diff --git a/apm-agent-plugins/apm-profiling-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.context.LifecycleListener b/apm-agent-plugins/apm-profiling-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.tracer.LifecycleListener similarity index 100% rename from apm-agent-plugins/apm-profiling-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.context.LifecycleListener rename to apm-agent-plugins/apm-profiling-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.tracer.LifecycleListener diff --git a/apm-agent-plugins/apm-profiling-plugin/src/test/java/co/elastic/apm/agent/profiler/CallTreeTest.java b/apm-agent-plugins/apm-profiling-plugin/src/test/java/co/elastic/apm/agent/profiler/CallTreeTest.java index b256ecdfdc..d55d0ce508 100644 --- a/apm-agent-plugins/apm-profiling-plugin/src/test/java/co/elastic/apm/agent/profiler/CallTreeTest.java +++ b/apm-agent-plugins/apm-profiling-plugin/src/test/java/co/elastic/apm/agent/profiler/CallTreeTest.java @@ -23,7 +23,7 @@ import co.elastic.apm.agent.configuration.SpyConfiguration; import co.elastic.apm.agent.tracer.configuration.TimeDuration; import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.impl.sampling.ConstantSampler; +import co.elastic.apm.agent.tracer.direct.ConstantSampler; import co.elastic.apm.agent.impl.transaction.AbstractSpan; import co.elastic.apm.agent.impl.transaction.Span; import co.elastic.apm.agent.impl.transaction.StackFrame; diff --git a/apm-agent-plugins/apm-profiling-plugin/src/test/java/co/elastic/apm/agent/profiler/SamplingProfilerTest.java b/apm-agent-plugins/apm-profiling-plugin/src/test/java/co/elastic/apm/agent/profiler/SamplingProfilerTest.java index 6e5816777e..6d1626cea4 100644 --- a/apm-agent-plugins/apm-profiling-plugin/src/test/java/co/elastic/apm/agent/profiler/SamplingProfilerTest.java +++ b/apm-agent-plugins/apm-profiling-plugin/src/test/java/co/elastic/apm/agent/profiler/SamplingProfilerTest.java @@ -139,7 +139,7 @@ void shouldNotDeleteProvidedFiles() throws Exception { SamplingProfiler otherProfiler = new SamplingProfiler(tracer, new FixedNanoClock(), tempFile1.toFile(), tempFile2.toFile()); - otherProfiler.start(tracer); + otherProfiler.start(); awaitProfilerStarted(otherProfiler); otherProfiler.stop(); diff --git a/apm-agent-plugins/apm-servlet-plugin/pom.xml b/apm-agent-plugins/apm-servlet-plugin/pom.xml index 4dc94472f6..fd12db82dd 100644 --- a/apm-agent-plugins/apm-servlet-plugin/pom.xml +++ b/apm-agent-plugins/apm-servlet-plugin/pom.xml @@ -16,12 +16,6 @@ - - - ${project.groupId} - apm-agent-core - ${project.version} - ${project.groupId} apm-java-concurrent-plugin diff --git a/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/pom.xml b/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/pom.xml index 278620fef0..744f6460ee 100644 --- a/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/pom.xml +++ b/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/pom.xml @@ -33,12 +33,6 @@ - - - ${project.groupId} - apm-agent-core - ${project.version} - javax.servlet javax.servlet-api diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/context/AbstractLifecycleListener.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/AbstractLifecycleListener.java similarity index 81% rename from apm-agent-core/src/main/java/co/elastic/apm/agent/context/AbstractLifecycleListener.java rename to apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/AbstractLifecycleListener.java index 02c4f0c0be..c2d93adefb 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/context/AbstractLifecycleListener.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/AbstractLifecycleListener.java @@ -16,17 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.apm.agent.context; - -import co.elastic.apm.agent.impl.ElasticApmTracer; +package co.elastic.apm.agent.tracer; public abstract class AbstractLifecycleListener implements LifecycleListener { - @Override - public void init(ElasticApmTracer tracer) throws Exception { - } @Override - public void start(ElasticApmTracer tracer) throws Exception { + public void start() throws Exception { } @Override diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/AbstractSpan.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/AbstractSpan.java index e164291c4d..5b4d7207e6 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/AbstractSpan.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/AbstractSpan.java @@ -35,7 +35,6 @@ public interface AbstractSpan> extends ActivateableInS TraceContext getTraceContext(); - void end(); T captureException(@Nullable Throwable t); @@ -151,6 +150,4 @@ public interface AbstractSpan> extends ActivateableInS void incrementReferences(); void decrementReferences(); - - } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Id.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Id.java index 7024fa50cb..7eee83dfab 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Id.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Id.java @@ -22,4 +22,6 @@ public interface Id { boolean isEmpty(); void setToRandomValue(); + + long getLeastSignificantBits(); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/context/LifecycleListener.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/LifecycleListener.java similarity index 64% rename from apm-agent-core/src/main/java/co/elastic/apm/agent/context/LifecycleListener.java rename to apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/LifecycleListener.java index 3b4716518c..fe905248d1 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/context/LifecycleListener.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/LifecycleListener.java @@ -16,42 +16,34 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.apm.agent.context; +package co.elastic.apm.agent.tracer; -import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.impl.Tracer; +import co.elastic.apm.agent.tracer.reporting.ReportingTracer; /** - * A {@link LifecycleListener} notifies about the start and stop event of the {@link ElasticApmTracer}. + * A {@link LifecycleListener} notifies about the start and stop event of the {@link Tracer}. *

* Implement this interface and register it as a {@linkplain java.util.ServiceLoader service} under - * {@code src/main/resources/META-INF/services/co.elastic.apm.agent.context.LifecycleListener}. + * {@code src/main/resources/META-INF/services/co.elastic.apm.agent.tracer.LifecycleListener}. *

*

- * Implementations may have a constructor with an {@link ElasticApmTracer} argument + * Implementations may have a constructor with a {@link co.elastic.apm.agent.tracer.Tracer} argument + *

+ *

+ * Listeners are instantiated before the {@link GlobalTracer} is initiated. To get hold of an instance, + * it needs to be injected via its constructor as the global tracer might neither be initialized within + * this instance's lifecycle methods. *

*/ public interface LifecycleListener { /** - * Callback for tracer initialization. As opposed to {@link LifecycleListener#start(ElasticApmTracer)}, which may - * be called in a delay, this callback is called at the bootstrap of the JVM, before anything else start. - * This may be useful for listeners that need to operate very early on, for example such that setup class loading - * requirement to support OSGi systems. - * @param tracer the tracer - * @throws Exception - */ - void init(ElasticApmTracer tracer) throws Exception; - - /** - * Callback for when the {@link ElasticApmTracer} starts. - * - * @param tracer The tracer. + * Callback for when the {@link co.elastic.apm.agent.tracer.Tracer} starts. */ - void start(ElasticApmTracer tracer) throws Exception; + void start() throws Exception; /** - * Callback for when {@link ElasticApmTracer#pause()} has been called. + * Callback for when {@link co.elastic.apm.agent.tracer.Tracer} has been paused. *

* Typically, this method is used to reduce overhead on the application to a minimum. This can be done by cleaning * up resources like object pools, as well as by avoiding tracing-related overhead. @@ -65,7 +57,7 @@ public interface LifecycleListener { void pause() throws Exception; /** - * Callback for when {@link ElasticApmTracer#resume()} has been called. + * Callback for when {@link Tracer} is resumed. *

* Typically, used in order to revert the actions taken by the {@link LifecycleListener#pause()} method, allowing * the agent to restore all tracing capabilities @@ -79,7 +71,7 @@ public interface LifecycleListener { void resume() throws Exception; /** - * Callback for when {@link ElasticApmTracer#stop()} has been called. + * Callback for when {@link Tracer} is stopped. *

* Typically, this method is used to clean up resources like thread pools * so that there are no class loader leaks when a webapp is redeployed in an application server. @@ -96,17 +88,14 @@ public interface LifecycleListener { * The order in which lifecycle listeners are called is non-deterministic. * *

  • - * The {@link ElasticApmTracer#getSharedSingleThreadedPool()} is shut down gracefully, + * The {@link ReportingTracer#getSharedSingleThreadedPool()} is shut down gracefully, * waiting a moment for the already scheduled tasks to be completed. * This means that implementations of this method can schedule a last command to this pool that is executed before shutdown. - * The {@link Tracer#getState()} will still be {@link Tracer.TracerState#RUNNING} in the tasks scheduled to - * {@link ElasticApmTracer#getSharedSingleThreadedPool()} within this method. - *
  • - *
  • - * The tracer state is set to {@link co.elastic.apm.agent.impl.Tracer.TracerState#STOPPED}. + * The {@link Tracer#isRunning()} will still be true in the tasks scheduled to + * {@link ReportingTracer#getSharedSingleThreadedPool()} within this method. *
  • *
  • - * The {@link co.elastic.apm.agent.report.Reporter} is closed. + * {@link Tracer#isRunning()} is set to false. *
  • * * diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/configuration/CoreConfiguration.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/configuration/CoreConfiguration.java index 3d166ca595..347bf7b3a0 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/configuration/CoreConfiguration.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/configuration/CoreConfiguration.java @@ -21,6 +21,7 @@ import co.elastic.apm.agent.common.util.WildcardMatcher; import co.elastic.apm.agent.configuration.ActivationMethod; +import javax.annotation.Nullable; import java.util.Collection; import java.util.List; @@ -40,10 +41,13 @@ public interface CoreConfiguration { String getServiceName(); + @Nullable String getServiceVersion(); + @Nullable String getServiceNodeName(); + @Nullable String getEnvironment(); ActivationMethod getActivationMethod(); diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/configuration/ServerlessConfiguration.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/configuration/ServerlessConfiguration.java index cb3a5e3fbe..bb1ba1c347 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/configuration/ServerlessConfiguration.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/configuration/ServerlessConfiguration.java @@ -18,6 +18,8 @@ */ package co.elastic.apm.agent.tracer.configuration; +import javax.annotation.Nullable; + public interface ServerlessConfiguration { String getAwsLambdaHandler(); @@ -25,4 +27,7 @@ public interface ServerlessConfiguration { long getDataFlushTimeout(); boolean runsOnAwsLambda(); + + @Nullable + String awsLambdaLogStreamName(); } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/AbstractDirectSpan.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/AbstractDirectSpan.java new file mode 100644 index 0000000000..e3da31c463 --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/AbstractDirectSpan.java @@ -0,0 +1,40 @@ +/* + * 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.tracer.direct; + +import co.elastic.apm.agent.tracer.AbstractSpan; + +import javax.annotation.Nullable; + +public interface AbstractDirectSpan> extends AbstractSpan { + + DirectSpan spanChild(); + + DirectSpan spanChild(long epochMicros); + + T captureException(@Nullable Throwable t, long epochMicros); + + void end(long epochMicros); + + void addLabel(String key, Boolean value); + + void addLabel(String key, Number value); + + void addLabel(String key, String value); +} diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/sampling/ConstantSampler.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/ConstantSampler.java similarity index 82% rename from apm-agent-core/src/main/java/co/elastic/apm/agent/impl/sampling/ConstantSampler.java rename to apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/ConstantSampler.java index 4a700880f0..85f4f5e2f3 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/sampling/ConstantSampler.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/ConstantSampler.java @@ -16,10 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.apm.agent.impl.sampling; +package co.elastic.apm.agent.tracer.direct; -import co.elastic.apm.agent.impl.transaction.Id; -import co.elastic.apm.agent.impl.transaction.TraceState; +import co.elastic.apm.agent.tracer.Id; /** * This is a implementation of {@link Sampler} which always returns the same sampling decision. @@ -32,12 +31,9 @@ public class ConstantSampler implements Sampler { private final boolean decision; private final double rate; - private final String traceStateHeader; - private ConstantSampler(boolean decision) { this.decision = decision; this.rate = decision ? 1.0d : 0.0d; - this.traceStateHeader = TraceState.getHeaderValue(rate); } public static Sampler of(boolean decision) { @@ -57,9 +53,4 @@ public boolean isSampled(Id traceId) { public double getSampleRate() { return rate; } - - @Override - public String getTraceStateHeader() { - return traceStateHeader; - } } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/DirectSpan.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/DirectSpan.java new file mode 100644 index 0000000000..00fbcc2a48 --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/DirectSpan.java @@ -0,0 +1,29 @@ +/* + * 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.tracer.direct; + +import co.elastic.apm.agent.tracer.Span; + +import javax.annotation.Nullable; + +public interface DirectSpan> extends AbstractDirectSpan, Span { + + @Deprecated + void setType(@Nullable String type, @Nullable String subtype, @Nullable String action); +} diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/DirectTracer.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/DirectTracer.java new file mode 100644 index 0000000000..0a3ce46059 --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/DirectTracer.java @@ -0,0 +1,43 @@ +/* + * 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.tracer.direct; + +import co.elastic.apm.agent.tracer.AbstractSpan; +import co.elastic.apm.agent.tracer.TraceContext; +import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.Transaction; +import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; + +import javax.annotation.Nullable; +import java.util.Map; + +public interface DirectTracer extends Tracer { + + @Nullable + TraceContext startChildTransaction(@Nullable C headerCarrier, HeaderGetter textHeadersGetter); + + @Nullable + Transaction startChildTransaction(@Nullable C headerCarrier, HeaderGetter textHeadersGetter, Sampler sampler, long epochMicros, @Nullable ClassLoader initiatingClassLoader); + + AbstractSpan noopTransaction(); + + Sampler getSampler(); + + void stop(); +} diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/DirectTransaction.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/DirectTransaction.java new file mode 100644 index 0000000000..6af022ab86 --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/DirectTransaction.java @@ -0,0 +1,25 @@ +/* + * 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.tracer.direct; + +import co.elastic.apm.agent.tracer.Transaction; + +public interface DirectTransaction> extends AbstractDirectSpan, Transaction { + +} diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/sampling/ProbabilitySampler.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/ProbabilitySampler.java similarity index 86% rename from apm-agent-core/src/main/java/co/elastic/apm/agent/impl/sampling/ProbabilitySampler.java rename to apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/ProbabilitySampler.java index c146defd20..a9a8d6ba22 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/sampling/ProbabilitySampler.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/ProbabilitySampler.java @@ -16,10 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.apm.agent.impl.sampling; +package co.elastic.apm.agent.tracer.direct; -import co.elastic.apm.agent.impl.transaction.Id; -import co.elastic.apm.agent.impl.transaction.TraceState; +import co.elastic.apm.agent.tracer.Id; /** * This implementation of {@link Sampler} samples based on a sampling probability (or sampling rate) between 0.0 and 1.0. @@ -49,14 +48,10 @@ public class ProbabilitySampler implements Sampler { private final long higherBound; private final double sampleRate; - // Because header value only contains sampling rate, we can cache it here - private final String traceStateHeader; - private ProbabilitySampler(double samplingRate) { this.higherBound = (long) (Long.MAX_VALUE * samplingRate); this.lowerBound = -higherBound; this.sampleRate = samplingRate; - this.traceStateHeader = TraceState.getHeaderValue(samplingRate); } public static Sampler of(double samplingRate) { @@ -79,9 +74,4 @@ public boolean isSampled(Id traceId) { public double getSampleRate() { return sampleRate; } - - @Override - public String getTraceStateHeader() { - return traceStateHeader; - } } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/sampling/Sampler.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/Sampler.java similarity index 73% rename from apm-agent-core/src/main/java/co/elastic/apm/agent/impl/sampling/Sampler.java rename to apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/Sampler.java index 53a48f1b57..3aa23e358f 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/sampling/Sampler.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/Sampler.java @@ -16,11 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.apm.agent.impl.sampling; +package co.elastic.apm.agent.tracer.direct; -import co.elastic.apm.agent.impl.transaction.Id; -import co.elastic.apm.agent.impl.transaction.Span; -import co.elastic.apm.agent.impl.transaction.Transaction; +import co.elastic.apm.agent.tracer.Id; +import co.elastic.apm.agent.tracer.Span; +import co.elastic.apm.agent.tracer.Transaction; /** * A sampler is responsible for determining whether a {@link Transaction} should be sampled. @@ -50,15 +50,4 @@ public interface Sampler { * @return current sample rate */ double getSampleRate(); - - - /** - * @return sample rate as (constant) header for context propagation - * - *

    - * While the {@code tracestate} header is not related to sampler itself, putting this here allows to reuse the same - * {@link String} instance as long as the sample rate does not change to minimize allocation - *

    - */ - String getTraceStateHeader(); } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/User.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/User.java index 3524cd7653..21e29fd962 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/User.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/User.java @@ -37,4 +37,8 @@ public interface User { * The username of the logged in user */ User withUsername(String userName); + + User withId(String id); + + User withEmail(String email); } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/DataWriter.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/DataWriter.java new file mode 100644 index 0000000000..80232a06b1 --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/DataWriter.java @@ -0,0 +1,55 @@ +/* + * 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.tracer.reporting; + +import javax.annotation.Nullable; + +public interface DataWriter { + + void writeStructure(StructureType type); + + void writeKey(CharSequence name); + + void writeKey(CharSequence name, boolean sanitized); + + void writeKey(CharSequence name, boolean sanitized, @Nullable String suffix); + + void writeValue(boolean value); + + void writeValue(long value); + + void writeValue(double value); + + void writeValue(CharSequence value); + + void writeValue(CharSequence value, boolean trimmed); + + int size(); + + void report(); + + enum StructureType { + OBJECT_START, + OBJECT_END, + ARRAY_START, + ARRAY_END, + NEXT, + NEW + } +} diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/DoubleSupplier.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/DoubleSupplier.java similarity index 94% rename from apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/DoubleSupplier.java rename to apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/DoubleSupplier.java index 120a72221d..390dfe97e2 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/DoubleSupplier.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/DoubleSupplier.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.apm.agent.metrics; +package co.elastic.apm.agent.tracer.reporting; public interface DoubleSupplier { diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/Labels.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/Labels.java similarity index 98% rename from apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/Labels.java rename to apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/Labels.java index c6a2e0475d..7bfcee52dc 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/Labels.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/Labels.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.apm.agent.metrics; +package co.elastic.apm.agent.tracer.reporting; import co.elastic.apm.agent.tracer.pooling.Recyclable; @@ -31,10 +31,6 @@ * However, there are also top-level labels which are not nested under the {@code labels} object, * for example {@link #getTransactionName()}, {@link #getTransactionType()}, {@link #getSpanType()} and {@link #getSpanSubType()}. *

    - * Metrics are structured into multiple {@link MetricSet}s. - * For each distinct combination of {@link Labels}, there is one {@link MetricSet}. - *

    - *

    * Labels allow for {@link CharSequence}s as a value, * thus avoiding allocations for {@code transaction.name.toString()} when tracking breakdown metrics for a transaction. * Iterations over the labels also don't allocate an Iterator, in contrast to {@code Map.entrySet().iterator()}. diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/ReportingTracer.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/ReportingTracer.java new file mode 100644 index 0000000000..68caa70f80 --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/ReportingTracer.java @@ -0,0 +1,51 @@ +/* + * 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.tracer.reporting; + +import co.elastic.apm.agent.tracer.Tracer; + +import java.io.Closeable; +import java.util.concurrent.ScheduledExecutorService; + +public interface ReportingTracer extends Tracer { + + void addMetric(String name, Labels labels, DoubleSupplier metric); + + void removeMetric(String name, Labels labels); + + /** + * Reports an ECS-logging formatted log message. + * + * @param log log message generated by ecs-logging + */ + void reportLog(String log); + + /** + * Reports an ECS-logging formatted log message. + * + * @param log log message generated by ecs-logging + */ + void reportLog(byte[] log); + + DataWriter newWriter(int maxSerializedSize); + + ScheduledExecutorService getSharedSingleThreadedPool(); + + void addShutdownHook(Closeable job); +} diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/sampling/ProbabilitySamplerTest.java b/apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/direct/ProbabilitySamplerTest.java similarity index 74% rename from apm-agent-core/src/test/java/co/elastic/apm/agent/impl/sampling/ProbabilitySamplerTest.java rename to apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/direct/ProbabilitySamplerTest.java index 216c593d11..447ab5ecdc 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/sampling/ProbabilitySamplerTest.java +++ b/apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/direct/ProbabilitySamplerTest.java @@ -16,14 +16,10 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.apm.agent.impl.sampling; +package co.elastic.apm.agent.tracer.direct; -import co.elastic.apm.agent.impl.transaction.Id; -import co.elastic.apm.agent.impl.transaction.TraceState; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; import static org.assertj.core.api.Assertions.assertThat; @@ -40,25 +36,10 @@ void setUp() { assertThat(sampler.getSampleRate()).isEqualTo(SAMPLING_RATE); } - @ParameterizedTest - @CsvSource({"0.0","1.0","0.5"}) - void headerCaching(double rate) { - - // will indirectly test ConstantSampler as we delegate to it for 0 and 1 values - sampler = ProbabilitySampler.of(rate); - - String rateHeader = sampler.getTraceStateHeader(); - assertThat(rateHeader).isEqualTo(TraceState.getHeaderValue(rate)); - - assertThat(rateHeader) - .describedAs("sample rate header should return same instance on each call") - .isSameAs(sampler.getTraceStateHeader()); - } - @Test void isSampledEmpiricalTest() { int sampledTransactions = 0; - Id id = Id.new128BitId(); + TestId id = TestId.new128BitId(); for (int i = 0; i < ITERATIONS; i++) { id.setToRandomValue(); if (sampler.isSampled(id)) { @@ -71,7 +52,7 @@ void isSampledEmpiricalTest() { @Test void testSamplingUpperBoundary() { long upperBound = Long.MAX_VALUE / 2; - final Id transactionId = Id.new128BitId(); + final TestId transactionId = TestId.new128BitId(); transactionId.fromLongs((long) 0, upperBound - 1); assertThat(ProbabilitySampler.of(0.5).isSampled(transactionId)).isTrue(); @@ -86,7 +67,7 @@ void testSamplingUpperBoundary() { @Test void testSamplingLowerBoundary() { long lowerBound = -Long.MAX_VALUE / 2; - final Id transactionId = Id.new128BitId(); + final TestId transactionId = TestId.new128BitId(); transactionId.fromLongs((long) 0, lowerBound + 1); assertThat(ProbabilitySampler.of(0.5).isSampled(transactionId)).isTrue(); diff --git a/apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/direct/TestId.java b/apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/direct/TestId.java new file mode 100644 index 0000000000..e0875fe99a --- /dev/null +++ b/apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/direct/TestId.java @@ -0,0 +1,124 @@ +/* + * 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.tracer.direct; + +import co.elastic.apm.agent.tracer.Id; +import co.elastic.apm.agent.tracer.util.HexUtils; + +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +public class TestId implements Id { + + private final byte[] data; + private boolean empty = true; + + public static TestId new128BitId() { + return new TestId(16); + } + + public static TestId new64BitId() { + return new TestId(8); + } + + private TestId(int idLengthBytes) { + data = new byte[idLengthBytes]; + } + + @Override + public void setToRandomValue() { + setToRandomValue(ThreadLocalRandom.current()); + } + + public void setToRandomValue(Random random) { + random.nextBytes(data); + onMutation(false); + } + + public void fromLongs(long... values) { + if (values.length * Long.BYTES != data.length) { + throw new IllegalArgumentException("Invalid number of long values"); + } + final ByteBuffer buffer = ByteBuffer.wrap(data); + for (long value : values) { + buffer.putLong(value); + } + onMutation(); + } + + public void copyFrom(TestId other) { + System.arraycopy(other.data, 0, data, 0, data.length); + this.empty = other.empty; + } + + private void onMutation() { + onMutation(isAllZeros(data)); + } + + private void onMutation(boolean empty) { + this.empty = empty; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TestId that = (TestId) o; + return Arrays.equals(data, that.data); + } + + @Override + public int hashCode() { + return Arrays.hashCode(data); + } + + @Override + public String toString() { + return HexUtils.bytesToHex(data); + } + + @Override + public boolean isEmpty() { + return empty; + } + + private static boolean isAllZeros(byte[] bytes) { + for (byte b : bytes) { + if (b != 0) { + return false; + } + } + return true; + } + + @Override + public long getLeastSignificantBits() { + return readLong(data.length - 8); + } + + private long readLong(int offset) { + long lsb = 0; + for (int i = offset; i < offset + 8; i++) { + lsb = (lsb << 8) | (data[i] & 0xff); + } + return lsb; + } +} diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/LabelsTest.java b/apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/reporting/LabelsTest.java similarity index 99% rename from apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/LabelsTest.java rename to apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/reporting/LabelsTest.java index 21e55850c0..a27919baec 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/LabelsTest.java +++ b/apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/reporting/LabelsTest.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.apm.agent.metrics; +package co.elastic.apm.agent.tracer.reporting; import org.junit.jupiter.api.Test; diff --git a/apm-opentracing/pom.xml b/apm-opentracing/pom.xml index dd19c4819b..ecc1111fc8 100644 --- a/apm-opentracing/pom.xml +++ b/apm-opentracing/pom.xml @@ -39,6 +39,12 @@ ${project.version} test + + ${project.groupId} + apm-agent-core + ${project.version} + test + ${project.groupId} apm-agent-core diff --git a/integration-tests/spring-boot-1-5/pom.xml b/integration-tests/spring-boot-1-5/pom.xml index 5b22443a05..d2f63afae8 100644 --- a/integration-tests/spring-boot-1-5/pom.xml +++ b/integration-tests/spring-boot-1-5/pom.xml @@ -28,6 +28,13 @@ apm-servlet-plugin ${project.version} + + + ${project.groupId} + apm-agent-core + ${project.version} + test + ${project.groupId} apm-agent-core