From bd6bf29acafddba3fb0d776499ecb96cc4cadffe Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Wed, 27 Sep 2023 23:44:48 +0200 Subject: [PATCH 01/21] Factor out lifecycle listener and remove tracer arguments as those can already be read by constructor injection. Add warning to use the global tracer from listeners, and make init method unavailable for regular plugins. --- ...InstrumentationStatsLifecycleListener.java | 5 +- .../apm/agent/collections/WeakMapCleaner.java | 5 +- .../ApmServerConfigurationSource.java | 13 +++-- .../apm/agent/configuration/StartupInfo.java | 5 +- .../ClosableLifecycleListenerAdapter.java | 3 ++ .../InitializableLifecycleListener.java | 33 +++++++++++++ .../apm/agent/impl/ElasticApmTracer.java | 16 +++--- .../agent/impl/ElasticApmTracerBuilder.java | 2 +- .../co/elastic/apm/agent/impl/Tracer.java | 4 +- .../impl/circuitbreaker/CircuitBreaker.java | 4 +- .../agent/logging/ApmServerLogAppender.java | 14 +++--- .../metrics/builtin/AgentOverheadMetrics.java | 9 ++-- .../agent/metrics/builtin/CGroupMetrics.java | 12 +++-- .../agent/metrics/builtin/JvmFdMetrics.java | 10 +++- .../agent/metrics/builtin/JvmGcMetrics.java | 10 +++- .../metrics/builtin/JvmMemoryMetrics.java | 10 +++- .../agent/metrics/builtin/SystemMetrics.java | 14 ++++-- .../agent/metrics/builtin/ThreadMetrics.java | 10 +++- .../serialize/MetricRegistryReporter.java | 4 +- ...lastic.apm.agent.tracer.LifecycleListener} | 0 .../elastic/apm/agent/impl/LifecycleTest.java | 34 +++++++------ .../builtin/AgentOverheadMetricsTest.java | 7 ++- .../metrics/builtin/CGroupMetricsTest.java | 9 +++- .../metrics/builtin/JvmFdMetricsTest.java | 4 +- .../metrics/builtin/JvmGcMetricsTest.java | 3 +- .../metrics/builtin/JvmMemoryMetricsTest.java | 3 +- .../metrics/builtin/SystemMetricsTest.java | 7 ++- .../metrics/builtin/ThreadMetricsTest.java | 3 +- ...lastic.apm.agent.tracer.LifecycleListener} | 0 .../apm/agent/jmx/JmxMetricTracker.java | 4 +- ...lastic.apm.agent.tracer.LifecycleListener} | 0 .../embeddedotel/EmbeddedSdkManager.java | 9 ++-- ...lastic.apm.agent.tracer.LifecycleListener} | 0 .../apm/agent/profiler/ProfilingFactory.java | 9 ++-- .../apm/agent/profiler/SamplingProfiler.java | 4 +- ...lastic.apm.agent.tracer.LifecycleListener} | 0 .../agent/profiler/SamplingProfilerTest.java | 2 +- .../tracer}/AbstractLifecycleListener.java | 9 +--- .../apm/agent/tracer}/LifecycleListener.java | 49 +++++++------------ .../tracer/reporting/ReportingTracer.java | 28 +++++++++++ 40 files changed, 239 insertions(+), 128 deletions(-) create mode 100644 apm-agent-core/src/main/java/co/elastic/apm/agent/context/InitializableLifecycleListener.java rename apm-agent-core/src/main/resources/META-INF/services/{co.elastic.apm.agent.context.LifecycleListener => co.elastic.apm.agent.tracer.LifecycleListener} (100%) rename apm-agent-core/src/test/resources/META-INF/services/{co.elastic.apm.agent.context.LifecycleListener => co.elastic.apm.agent.tracer.LifecycleListener} (100%) rename apm-agent-plugins/apm-jmx-plugin/src/main/resources/META-INF/services/{co.elastic.apm.agent.context.LifecycleListener => co.elastic.apm.agent.tracer.LifecycleListener} (100%) rename apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/src/main/resources/META-INF/services/{co.elastic.apm.agent.context.LifecycleListener => co.elastic.apm.agent.tracer.LifecycleListener} (100%) rename apm-agent-plugins/apm-profiling-plugin/src/main/resources/META-INF/services/{co.elastic.apm.agent.context.LifecycleListener => co.elastic.apm.agent.tracer.LifecycleListener} (100%) rename {apm-agent-core/src/main/java/co/elastic/apm/agent/context => apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer}/AbstractLifecycleListener.java (81%) rename {apm-agent-core/src/main/java/co/elastic/apm/agent/context => apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer}/LifecycleListener.java (64%) create mode 100644 apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/ReportingTracer.java 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/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..6d6ca48506 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,10 +26,11 @@ 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.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; @@ -672,10 +673,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 +735,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,6 +947,7 @@ public MetaDataFuture getMetaDataFuture() { return metaDataFuture; } + @Override public ScheduledThreadPoolExecutor getSharedSingleThreadedPool() { return sharedPool; } 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..61d2c5b899 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 @@ -30,7 +30,9 @@ 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.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/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/builtin/AgentOverheadMetrics.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/AgentOverheadMetrics.java index c0a06ab921..b891e81d28 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.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/CGroupMetrics.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/metrics/builtin/CGroupMetrics.java index 9f64ed14cc..051d37ea44 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,7 +18,7 @@ */ 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; @@ -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..12e36a62ee 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,7 +18,7 @@ */ 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; @@ -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..a77b35f34a 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,7 +18,7 @@ */ 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; @@ -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..c5fea8387f 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,7 +18,7 @@ */ 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; @@ -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..7f69144ce5 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.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..549d840532 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,7 +18,7 @@ */ 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; @@ -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/MetricRegistryReporter.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporter.java index aa1a9347a9..9f9c090346 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,7 +19,7 @@ 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.metrics.MetricRegistry; @@ -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/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/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/metrics/builtin/AgentOverheadMetricsTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/AgentOverheadMetricsTest.java index 814bc84cfc..21e35ce4b5 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,6 +20,7 @@ import co.elastic.apm.agent.configuration.MetricsConfiguration; import co.elastic.apm.agent.common.util.WildcardMatcher; +import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.metrics.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.metrics.MetricSet; @@ -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/CGroupMetricsTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/metrics/builtin/CGroupMetricsTest.java index a8d80db1e0..f7fd1a5501 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,6 +19,7 @@ package co.elastic.apm.agent.metrics.builtin; import co.elastic.apm.agent.configuration.MetricsConfiguration; +import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.metrics.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.report.ReporterConfiguration; @@ -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..eaf982feed 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,6 +19,7 @@ package co.elastic.apm.agent.metrics.builtin; import co.elastic.apm.agent.configuration.MetricsConfiguration; +import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.metrics.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.report.ReporterConfiguration; @@ -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..7694adbebc 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,6 +19,7 @@ package co.elastic.apm.agent.metrics.builtin; import co.elastic.apm.agent.configuration.MetricsConfiguration; +import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.metrics.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.report.ReporterConfiguration; @@ -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..cbc1a962ac 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,6 +19,7 @@ package co.elastic.apm.agent.metrics.builtin; import co.elastic.apm.agent.configuration.MetricsConfiguration; +import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.metrics.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.report.ReporterConfiguration; @@ -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..54976c7452 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,6 +19,7 @@ package co.elastic.apm.agent.metrics.builtin; import co.elastic.apm.agent.configuration.MetricsConfiguration; +import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.metrics.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.report.ReporterConfiguration; @@ -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/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-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..d85cbcba1c 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,7 +18,7 @@ */ package co.elastic.apm.agent.jmx; -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; @@ -71,7 +71,7 @@ public JmxMetricTracker(ElasticApmTracer tracer) { } @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) { 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-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..efd1ae3dc1 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,12 @@ */ 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.GlobalTracer; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; @@ -39,15 +40,13 @@ public class EmbeddedSdkManager extends AbstractLifecycleListener { private static final Logger logger = LoggerFactory.getLogger(EmbeddedSdkManager.class); - @Nullable - private ElasticApmTracer tracer; + private final ElasticApmTracer tracer; @Nullable private volatile SdkMeterProvider sdkInstance; private boolean isShutdown = false; - @Override - public synchronized void start(ElasticApmTracer tracer) throws Exception { + public EmbeddedSdkManager(ElasticApmTracer 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-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/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-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-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/reporting/ReportingTracer.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/ReportingTracer.java new file mode 100644 index 0000000000..50c23f69ab --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/ReportingTracer.java @@ -0,0 +1,28 @@ +/* + * 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.util.concurrent.ScheduledExecutorService; + +public interface ReportingTracer extends Tracer { + + ScheduledExecutorService getSharedSingleThreadedPool(); +} From b37db5885e8b4d41107169a6187c80a67874de03 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 10:30:40 +0200 Subject: [PATCH 02/21] Move metrics and log reporting to ReportingTracer, and remove obsolete dependencies on core module. --- .../configuration/CoreConfiguration.java | 3 ++ .../ServerlessConfiguration.java | 10 ++++++ .../apm/agent/impl/ElasticApmTracer.java | 23 ++++++++++++ .../agent/impl/transaction/Transaction.java | 2 +- .../apm/agent/metrics/MetricCollector.java | 2 ++ .../apm/agent/metrics/MetricRegistry.java | 2 ++ .../elastic/apm/agent/metrics/MetricSet.java | 2 ++ .../metrics/builtin/AgentOverheadMetrics.java | 2 +- .../metrics/builtin/AgentReporterMetrics.java | 2 +- .../agent/metrics/builtin/CGroupMetrics.java | 4 +-- .../agent/metrics/builtin/JvmFdMetrics.java | 4 +-- .../agent/metrics/builtin/JvmGcMetrics.java | 4 +-- .../metrics/builtin/JvmMemoryMetrics.java | 4 +-- .../agent/metrics/builtin/SystemMetrics.java | 4 +-- .../agent/metrics/builtin/ThreadMetrics.java | 4 +-- .../report/serialize/DslJsonSerializer.java | 2 +- .../serialize/MetricRegistryReporter.java | 2 +- .../serialize/MetricRegistrySerializer.java | 2 +- .../apm/agent/impl/ElasticApmTracerTest.java | 2 +- .../apm/agent/impl/SpanTypeBreakdownTest.java | 2 +- .../apm/agent/metrics/MetricRegistryTest.java | 2 ++ .../builtin/AgentOverheadMetricsTest.java | 2 +- .../builtin/AgentReporterMetricsTest.java | 2 +- .../metrics/builtin/CGroupMetricsTest.java | 2 +- .../metrics/builtin/JvmFdMetricsTest.java | 2 +- .../metrics/builtin/JvmMemoryMetricsTest.java | 2 +- .../metrics/builtin/SystemMetricsTest.java | 2 +- .../metrics/builtin/ThreadMetricsTest.java | 2 +- .../serialize/MetricSetSerializationTest.java | 2 +- .../apm-ecs-logging-plugin/pom.xml | 7 ---- apm-agent-plugins/apm-jmx-plugin/pom.xml | 9 ----- .../co/elastic/apm/agent/jmx/JmxMetric.java | 3 +- .../apm/agent/jmx/JmxMetricTracker.java | 29 ++++++++------- .../apm/agent/jmx/JmxMetricTrackerTest.java | 2 +- ...ulLoggerErrorCapturingInstrumentation.java | 1 - .../AbstractJulEcsReformattingHelper.java | 6 ++-- .../jul/sending/JulLogSenderHandler.java | 10 +++--- .../Log4J1EcsReformattingHelper.java | 6 ++-- .../log4j1/sending/LogSenderAppender.java | 10 +++--- .../Log4j2_7PlusLogCorrelationHelper.java | 1 - .../Log4J2EcsReformattingHelper.java | 6 ++-- .../sending/Log4j2LogSenderAppender.java | 10 +++--- .../LogbackEcsReformattingHelper.java | 6 ++-- .../sending/LogbackLogSenderAppender.java | 10 +++--- .../AbstractEcsReformattingHelper.java | 36 ++++++++----------- apm-agent-plugins/apm-logging-plugin/pom.xml | 9 ----- .../micrometer/MicrometerMetricsReporter.java | 2 +- apm-agent-plugins/apm-servlet-plugin/pom.xml | 6 ---- .../apm-spring-webmvc-spring5/pom.xml | 6 ---- .../configuration/CoreConfiguration.java | 4 +++ .../ServerlessConfiguration.java | 5 +++ .../tracer/reporting}/DoubleSupplier.java | 2 +- .../apm/agent/tracer/reporting}/Labels.java | 6 +--- .../tracer/reporting/ReportingTracer.java | 21 +++++++++++ .../agent/tracer/reporting}/LabelsTest.java | 2 +- integration-tests/spring-boot-1-5/pom.xml | 7 ++++ 56 files changed, 176 insertions(+), 146 deletions(-) rename {apm-agent-core/src/main/java/co/elastic/apm/agent/metrics => apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting}/DoubleSupplier.java (94%) rename {apm-agent-core/src/main/java/co/elastic/apm/agent/metrics => apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting}/Labels.java (98%) rename {apm-agent-core/src/test/java/co/elastic/apm/agent/metrics => apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/reporting}/LabelsTest.java (99%) 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/impl/ElasticApmTracer.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracer.java index 6d6ca48506..043ab72165 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 @@ -27,6 +27,8 @@ 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.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; @@ -947,11 +949,32 @@ 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 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/transaction/Transaction.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Transaction.java index aabac69aed..e9f59a6095 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 @@ -27,7 +27,7 @@ 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.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.metrics.Timer; import co.elastic.apm.agent.tracer.Outcome; 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 b891e81d28..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 @@ -21,7 +21,7 @@ import co.elastic.apm.agent.configuration.MetricsConfiguration; 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; 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 051d37ea44..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 @@ -20,8 +20,8 @@ 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; 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 12e36a62ee..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 @@ -20,8 +20,8 @@ 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; 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 a77b35f34a..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 @@ -20,8 +20,8 @@ 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; 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 c5fea8387f..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 @@ -20,8 +20,8 @@ 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; 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 7f69144ce5..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 @@ -21,8 +21,8 @@ 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; 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 549d840532..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 @@ -20,8 +20,8 @@ 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; 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 9f9c090346..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 @@ -21,7 +21,7 @@ import co.elastic.apm.agent.tracer.service.ServiceInfo; 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; 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/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..2b85dc0543 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 @@ -34,7 +34,7 @@ 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/SpanTypeBreakdownTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/SpanTypeBreakdownTest.java index a090c71566..c5bd601ae3 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 @@ -26,7 +26,7 @@ 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/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 21e35ce4b5..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 @@ -21,7 +21,7 @@ import co.elastic.apm.agent.configuration.MetricsConfiguration; import co.elastic.apm.agent.common.util.WildcardMatcher; 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.ReporterConfiguration; 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 f7fd1a5501..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 @@ -20,7 +20,7 @@ import co.elastic.apm.agent.configuration.MetricsConfiguration; 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.ReporterConfiguration; import org.junit.jupiter.api.Test; 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 eaf982feed..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 @@ -20,7 +20,7 @@ import co.elastic.apm.agent.configuration.MetricsConfiguration; 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.ReporterConfiguration; import org.junit.jupiter.api.condition.DisabledOnOs; 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 7694adbebc..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 @@ -20,7 +20,7 @@ import co.elastic.apm.agent.configuration.MetricsConfiguration; 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.ReporterConfiguration; import org.assertj.core.api.AbstractDoubleAssert; 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 cbc1a962ac..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 @@ -20,7 +20,7 @@ import co.elastic.apm.agent.configuration.MetricsConfiguration; 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.ReporterConfiguration; import org.junit.jupiter.api.Test; 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 54976c7452..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 @@ -20,7 +20,7 @@ import co.elastic.apm.agent.configuration.MetricsConfiguration; 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.ReporterConfiguration; import org.junit.jupiter.api.Test; 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-plugins/apm-ecs-logging-plugin/pom.xml b/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml index e42851bd73..708e1762cb 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-jmx-plugin/pom.xml b/apm-agent-plugins/apm-jmx-plugin/pom.xml index a8a83b1333..a2949f3642 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 d85cbcba1c..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 @@ -19,14 +19,13 @@ package co.elastic.apm.agent.jmx; 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.metrics.MetricRegistry; +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,14 +59,14 @@ 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 @@ -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/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-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 67328e4065..8ac34527bc 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/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..a443ff3932 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 @@ -147,7 +147,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(); diff --git a/apm-agent-plugins/apm-servlet-plugin/pom.xml b/apm-agent-plugins/apm-servlet-plugin/pom.xml index b42be23d57..5b211fd95e 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 f7c45d6d34..c490eadda8 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-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-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 index 50c23f69ab..9c8577abd4 100644 --- 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 @@ -20,9 +20,30 @@ 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); + ScheduledExecutorService getSharedSingleThreadedPool(); + + void addShutdownHook(Closeable job); } 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/integration-tests/spring-boot-1-5/pom.xml b/integration-tests/spring-boot-1-5/pom.xml index fc7bd94d42..7f5000cee3 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 From f92b941711f60a00ced98c728b094ceda2ed359a Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 11:50:59 +0200 Subject: [PATCH 03/21] Add data writer abstraction to decouple plugins from Json writer implementation. --- .../apm/agent/impl/ElasticApmTracer.java | 10 + .../report/serialize/DslJsonDataWriter.java | 117 ++++++++++ .../AbstractMicrometerInstrumentation.java | 4 +- .../MicrometerMeterRegistrySerializer.java | 215 +++++++++--------- .../micrometer/MicrometerMetricsReporter.java | 20 +- ...MicrometerMeterRegistrySerializerTest.java | 28 ++- .../embeddedotel/EmbeddedSdkManager.java | 7 +- .../ElasticOtelMetricsExporter.java | 16 +- .../otelmetricsdk/MetricSetSerializer.java | 141 ++++++------ .../otelmetricsdk/OtelMetricSerializer.java | 12 +- ...dkMeterProviderBuilderInstrumentation.java | 4 +- .../agent/tracer/reporting/DataWriter.java | 55 +++++ .../tracer/reporting/ReportingTracer.java | 2 + 13 files changed, 411 insertions(+), 220 deletions(-) create mode 100644 apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/DslJsonDataWriter.java create mode 100644 apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/reporting/DataWriter.java 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 043ab72165..7ce38364cc 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 @@ -27,6 +27,8 @@ 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; @@ -65,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; @@ -109,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; @@ -969,6 +974,11 @@ 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; 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..b17cf31b98 --- /dev/null +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/DslJsonDataWriter.java @@ -0,0 +1,117 @@ +/* + * 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; + +public class DslJsonDataWriter implements DataWriter { + + private final JsonWriter jw; + + private final Reporter reporter; + + public DslJsonDataWriter(JsonWriter jw, Reporter reporter) { + this.jw = jw; + this.reporter = reporter; + } + + @Override + public void write(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 COMMA: + jw.writeByte(JsonWriter.COMMA); + break; + case SEMI: + jw.writeByte(JsonWriter.SEMI); + break; + case QUOTE: + jw.writeByte(JsonWriter.QUOTE); + break; + case NEW_LINE: + jw.writeByte((byte) '\n'); + break; + } + } + + @Override + public void writeFieldName(String name) { + DslJsonSerializer.writeFieldName(name, jw); + } + + @Override + public void serialize(boolean value) { + BoolConverter.serialize(value, jw); + } + + @Override + public void serialize(long value) { + NumberConverter.serialize(value, jw); + } + + @Override + public void serialize(double value) { + NumberConverter.serialize(value, jw); + } + + @Override + public void writeAscii(String value) { + jw.writeAscii(value); + } + + @Override + public void writeString(CharSequence replaceBuilder) { + jw.writeString(replaceBuilder); + } + + @Override + public void writeStringValue(CharSequence value, StringBuilder replaceBuilder) { + DslJsonSerializer.writeStringValue(value, replaceBuilder, jw); + } + + @Override + public CharSequence sanitizePropertyName(String key, StringBuilder replaceBuilder) { + return DslJsonSerializer.sanitizePropertyName(key, replaceBuilder); + } + + @Override + public int size() { + return jw.size(); + } + + @Override + public void report() { + reporter.reportMetrics(jw); + } +} 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..f794f78ccb 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,38 @@ 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.COMMA; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.NEW_LINE; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.OBJECT_END; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.OBJECT_START; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.QUOTE; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.SEMI; 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 +87,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, replaceBuilder, 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, StringBuilder replaceBuilder, DataWriter writer) { boolean hasSamples = false; boolean dedotMetricName = config.isDedotCustomMetrics(); - jw.writeByte(JsonWriter.OBJECT_START); + writer.write(OBJECT_START); { - DslJsonSerializer.writeFieldName("metricset", jw); - jw.writeByte(JsonWriter.OBJECT_START); + writer.writeFieldName("metricset"); + writer.write(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.writeFieldName("timestamp"); + writer.serialize(epochMicros); + writer.write(COMMA); + serializeTags(tags, replaceBuilder, writer); + writer.writeFieldName("samples"); + writer.write(OBJECT_START); ClassLoader originalContextCL = PrivilegedActionUtils.getContextClassLoader(Thread.currentThread()); try { @@ -122,25 +123,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, replaceBuilder, 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, replaceBuilder, 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, replaceBuilder, 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, replaceBuilder, 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, replaceBuilder, 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, replaceBuilder, 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, replaceBuilder, dedotMetricName); } } catch (Throwable throwable) { String meterName = meter.getId().getName(); @@ -154,38 +155,38 @@ boolean serializeMetricSet(List tags, List meters, long epochMicros, } finally { PrivilegedActionUtils.setContextClassLoader(Thread.currentThread(), originalContextCL); } - jw.writeByte(JsonWriter.OBJECT_END); + writer.write(OBJECT_END); } - jw.writeByte(JsonWriter.OBJECT_END); + writer.write(OBJECT_END); } - jw.writeByte(JsonWriter.OBJECT_END); - jw.writeByte(NEW_LINE); + writer.write(OBJECT_END); + writer.write(NEW_LINE); return hasSamples; } - private static void serializeTags(List tags, StringBuilder replaceBuilder, JsonWriter jw) { + private static void serializeTags(List tags, StringBuilder replaceBuilder, DataWriter writer) { if (tags.isEmpty()) { return; } - DslJsonSerializer.writeFieldName("tags", jw); - jw.writeByte(OBJECT_START); + writer.writeFieldName("tags"); + writer.write(OBJECT_START); for (int i = 0, tagsSize = tags.size(); i < tagsSize; i++) { Tag tag = tags.get(i); if (i > 0) { - jw.writeByte(COMMA); + writer.write(COMMA); } - DslJsonSerializer.writeStringValue(DslJsonSerializer.sanitizePropertyName(tag.getKey(), replaceBuilder), replaceBuilder, jw); - jw.writeByte(JsonWriter.SEMI); - DslJsonSerializer.writeStringValue(tag.getValue(), replaceBuilder, jw); + writer.writeStringValue(writer.sanitizePropertyName(tag.getKey(), replaceBuilder), replaceBuilder); + writer.write(SEMI); + writer.writeStringValue(tag.getValue(), replaceBuilder); } - jw.writeByte(OBJECT_END); - jw.writeByte(COMMA); + writer.write(OBJECT_END); + writer.write(COMMA); } /** * 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 @@ -195,15 +196,15 @@ private static void serializeTags(List tags, StringBuilder 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, StringBuilder replaceBuilder, 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.write(COMMA); + serializeValue(id, ".count", count, writer, replaceBuilder, dedotMetricName); + writer.write(COMMA); + serializeValue(id, ".sum.us", totalTime, writer, replaceBuilder, dedotMetricName); if (histogramSnapshot != null && histogramSnapshot.histogramCounts().length > 0) { - jw.writeByte(JsonWriter.COMMA); - serializeHistogram(id, histogramSnapshot, jw, replaceBuilder, dedotMetricName); + writer.write(COMMA); + serializeHistogram(id, histogramSnapshot, writer, replaceBuilder, dedotMetricName); } return true; } @@ -213,7 +214,7 @@ 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 @@ -223,68 +224,68 @@ private static boolean serializeTimer(JsonWriter jw, HistogramSnapshot histogram * @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, StringBuilder replaceBuilder, 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.write(COMMA); + serializeValue(id, ".count", count, writer, replaceBuilder, dedotMetricName); + writer.write(COMMA); + serializeValue(id, ".sum", totalAmount, writer, replaceBuilder, dedotMetricName); if (histogramSnapshot != null && histogramSnapshot.histogramCounts().length > 0) { - jw.writeByte(JsonWriter.COMMA); - serializeHistogram(id, histogramSnapshot, jw, replaceBuilder, dedotMetricName); + writer.write(COMMA); + serializeHistogram(id, histogramSnapshot, writer, replaceBuilder, 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, StringBuilder replaceBuilder, 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, replaceBuilder, dedotMetricName); + writer.write(ARRAY_START); if (bucket.length > 0) { - NumberConverter.serialize(bucket[0].bucket(), jw); + writer.serialize(bucket[0].bucket()); for (int i = 1; i < bucket.length; i++) { - jw.writeByte(JsonWriter.COMMA); - NumberConverter.serialize(bucket[i].bucket(), jw); + writer.write(COMMA); + writer.serialize(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.write(ARRAY_END); + writer.write(COMMA); + writer.write(QUOTE); + writer.writeAscii("counts"); + writer.write(QUOTE); + writer.write(SEMI); + writer.write(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.serialize((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.write(COMMA); + writer.serialize((long) (bucket[i].count() - prevBucketCount)); prevBucketCount = bucket[i].count(); } } - jw.writeByte(JsonWriter.ARRAY_END); + writer.write(ARRAY_END); - jw.writeByte(JsonWriter.COMMA); - jw.writeAscii("\"type\":\"histogram\""); + writer.write(COMMA); + writer.writeAscii("\"type\":\"histogram\""); - jw.writeByte(JsonWriter.OBJECT_END); + writer.write(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, StringBuilder replaceBuilder, boolean dedotMetricName) { + serializeValueStart(id.getName(), suffix, writer, replaceBuilder, dedotMetricName); + writer.serialize(value); + writer.write(OBJECT_END); } /** @@ -293,34 +294,34 @@ 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 writer writer * @param replaceBuilder * @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, StringBuilder replaceBuilder, boolean dedotMetricName) { if (isValidValue(value)) { - if (hasValue) jw.writeByte(JsonWriter.COMMA); - serializeValue(id, "", value, jw, replaceBuilder, dedotMetricName); + if (hasValue) writer.write(COMMA); + serializeValue(id, "", value, writer, replaceBuilder, 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, StringBuilder replaceBuilder, boolean dedotMetricName) { + serializeValueStart(id.getName(), suffix, writer, replaceBuilder, dedotMetricName); + writer.serialize(value); + writer.write(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, StringBuilder replaceBuilder, boolean dedotMetricName) { + serializeObjectStart(key, "value", suffix, writer, replaceBuilder, dedotMetricName); } - private static void serializeObjectStart(String key, String objectName, String suffix, JsonWriter jw, StringBuilder replaceBuilder, boolean dedotMetricName) { + private static void serializeObjectStart(String key, String objectName, String suffix, DataWriter writer, StringBuilder replaceBuilder, boolean dedotMetricName) { replaceBuilder.setLength(0); if (dedotMetricName) { - DslJsonSerializer.sanitizePropertyName(key, replaceBuilder); + writer.sanitizePropertyName(key, replaceBuilder); } else { replaceBuilder.append(key); } @@ -330,14 +331,14 @@ private static void serializeObjectStart(String key, String objectName, String s } replaceBuilder.append(suffix); } - jw.writeString(replaceBuilder); + writer.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); + writer.write(SEMI); + writer.write(OBJECT_START); + writer.write(QUOTE); + writer.writeAscii(objectName); + writer.write(QUOTE); + writer.write(SEMI); } 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 a443ff3932..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; } @@ -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..5481763853 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 size = invocationOnMock.getArgument(0); + return new DslJsonDataWriter(dslJson.newWriter(size), 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 efd1ae3dc1..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 @@ -20,10 +20,9 @@ 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.GlobalTracer; +import co.elastic.apm.agent.tracer.Tracer; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; @@ -40,13 +39,13 @@ public class EmbeddedSdkManager extends AbstractLifecycleListener { private static final Logger logger = LoggerFactory.getLogger(EmbeddedSdkManager.class); - private final ElasticApmTracer tracer; + private final Tracer tracer; @Nullable private volatile SdkMeterProvider sdkInstance; private boolean isShutdown = false; - public EmbeddedSdkManager(ElasticApmTracer tracer) { + public EmbeddedSdkManager(Tracer tracer) { this.tracer = tracer; } 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..9d86b59c50 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,48 @@ */ 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.COMMA; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.NEW_LINE; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.OBJECT_END; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.OBJECT_START; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.QUOTE; +import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.SEMI; 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) { + public MetricSetSerializer(ReportingTracer tracer, Attributes attributes, CharSequence instrumentationScopeName, long epochMicros, StringBuilder replaceBuilder) { this.replaceBuilder = replaceBuilder; anySamplesWritten = false; - jw = DSL_JSON.newWriter(INITIAL_BUFFER_SIZE); - jw.writeByte(JsonWriter.OBJECT_START); + writer = tracer.newWriter(INITIAL_BUFFER_SIZE); + writer.write(OBJECT_START); { - DslJsonSerializer.writeFieldName("metricset", jw); - jw.writeByte(JsonWriter.OBJECT_START); + writer.writeFieldName("metricset"); + writer.write(OBJECT_START); { - DslJsonSerializer.writeFieldName("timestamp", jw); - NumberConverter.serialize(epochMicros, jw); - jw.writeByte(JsonWriter.COMMA); + writer.writeFieldName("timestamp"); + writer.serialize(epochMicros); + writer.write(COMMA); serializeAttributes(instrumentationScopeName, attributes); - DslJsonSerializer.writeFieldName("samples", jw); - jw.writeByte(JsonWriter.OBJECT_START); + writer.writeFieldName("samples"); + writer.write(OBJECT_START); } } } @@ -79,19 +74,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.write(COMMA); } serializeFieldKey(metricName); - jw.writeByte(JsonWriter.OBJECT_START); + writer.write(OBJECT_START); { serializeFieldKeyAscii("value"); if (isDouble) { - NumberConverter.serialize(doubleVal, jw); + writer.serialize(doubleVal); } else { - NumberConverter.serialize(longVal, jw); + writer.serialize(longVal); } } - jw.writeByte(JsonWriter.OBJECT_END); + writer.write(OBJECT_END); anySamplesWritten = true; } @@ -101,20 +96,20 @@ public void addExplicitBucketHistogram(CharSequence metricName, List bou return; } if (anySamplesWritten) { - jw.writeByte(COMMA); + writer.write(COMMA); } serializeFieldKey(metricName); - jw.writeByte(JsonWriter.OBJECT_START); + writer.write(OBJECT_START); { serializeFieldKeyAscii("values"); convertAndSerializeHistogramBucketBoundaries(boundaries, counts); - jw.writeByte(COMMA); + writer.write(COMMA); serializeFieldKeyAscii("counts"); convertAndSerializeHistogramBucketCounts(counts); - jw.writeByte(COMMA); - jw.writeAscii("\"type\":\"histogram\""); + writer.write(COMMA); + writer.writeAscii("\"type\":\"histogram\""); } - jw.writeByte(JsonWriter.OBJECT_END); + writer.write(OBJECT_END); anySamplesWritten = true; } @@ -128,29 +123,29 @@ private boolean isEmptyHistogram(List boundaries, List counts) { } private void convertAndSerializeHistogramBucketCounts(List counts) { - jw.writeByte(ARRAY_START); + writer.write(ARRAY_START); boolean firstElement = true; for (long count : counts) { if (count != 0) { if (!firstElement) { - jw.writeByte(COMMA); + writer.write(COMMA); } firstElement = false; - NumberConverter.serialize(count, jw); + writer.serialize(count); } } - jw.writeByte(ARRAY_END); + writer.write(ARRAY_END); } private void convertAndSerializeHistogramBucketBoundaries(List boundaries, List counts) { - jw.writeByte(ARRAY_START); + writer.write(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.write(COMMA); } firstElement = false; if (i == 0) { @@ -158,29 +153,29 @@ private void convertAndSerializeHistogramBucketBoundaries(List boundarie if (bounds > 0) { bounds /= 2; } - NumberConverter.serialize(bounds, jw); + writer.serialize(bounds); } else if (i == bucketCount - 1) { - NumberConverter.serialize(boundaries.get(bucketCount - 2), jw); + writer.serialize(boundaries.get(bucketCount - 2)); } else { double lower = boundaries.get(i - 1); double upper = boundaries.get(i); - NumberConverter.serialize(lower + (upper - lower) / 2, jw); + writer.serialize(lower + (upper - lower) / 2); } } } - jw.writeByte(ARRAY_END); + writer.write(ARRAY_END); } private void serializeFieldKey(CharSequence fieldName) { - jw.writeString(fieldName); - jw.writeByte(JsonWriter.SEMI); + writer.writeString(fieldName); + writer.write(SEMI); } private void serializeFieldKeyAscii(String fieldName) { - jw.writeByte(JsonWriter.QUOTE); - jw.writeAscii(fieldName); - jw.writeByte(JsonWriter.QUOTE); - jw.writeByte(JsonWriter.SEMI); + writer.write(QUOTE); + writer.writeAscii(fieldName); + writer.write(QUOTE); + writer.write(SEMI); } private void serializeAttributes(CharSequence instrumentationScopeName, Attributes attributes) { @@ -188,12 +183,12 @@ private void serializeAttributes(CharSequence instrumentationScopeName, Attribut if (attributeMap.isEmpty() && instrumentationScopeName.length() == 0) { return; } - DslJsonSerializer.writeFieldName("tags", jw); - jw.writeByte(OBJECT_START); + writer.writeFieldName("tags"); + writer.write(OBJECT_START); boolean anyWritten = false; if (instrumentationScopeName.length() > 0) { - jw.writeAscii("\"otel_instrumentation_scope_name\":"); - jw.writeString(instrumentationScopeName); + writer.writeAscii("\"otel_instrumentation_scope_name\":"); + writer.writeString(instrumentationScopeName); anyWritten = true; } for (Map.Entry, Object> entry : attributeMap.entrySet()) { @@ -201,31 +196,31 @@ private void serializeAttributes(CharSequence instrumentationScopeName, Attribut Object value = entry.getValue(); anyWritten |= serializeAttribute(key, value, anyWritten); } - jw.writeByte(OBJECT_END); - jw.writeByte(COMMA); + writer.write(OBJECT_END); + writer.write(COMMA); } private boolean serializeAttribute(AttributeKey key, @Nullable Object value, boolean prependComma) { if (isValidAttributeValue(key, value)) { if (prependComma) { - jw.writeByte(COMMA); + writer.write(COMMA); } - DslJsonSerializer.writeStringValue(DslJsonSerializer.sanitizePropertyName(key.getKey(), replaceBuilder), replaceBuilder, jw); - jw.writeByte(JsonWriter.SEMI); + writer.writeStringValue(writer.sanitizePropertyName(key.getKey(), replaceBuilder), replaceBuilder); + writer.write(SEMI); AttributeType type = key.getType(); switch (type) { case STRING: - jw.writeString((CharSequence) value); + writer.writeString((CharSequence) value); return true; case BOOLEAN: - BoolConverter.serialize((Boolean) value, jw); + writer.serialize((Boolean) value); return true; case LONG: - NumberConverter.serialize(((Number) value).longValue(), jw); + writer.serialize(((Number) value).longValue()); return true; case DOUBLE: - NumberConverter.serialize(((Number) value).doubleValue(), jw); + writer.serialize(((Number) value).doubleValue()); return true; case STRING_ARRAY: case BOOLEAN_ARRAY: @@ -266,19 +261,19 @@ private void serializeMetricSetEnd() { { /*"samples":*/ { - jw.writeByte(JsonWriter.OBJECT_END); + writer.write(OBJECT_END); } } - jw.writeByte(JsonWriter.OBJECT_END); + writer.write(OBJECT_END); } - jw.writeByte(JsonWriter.OBJECT_END); - jw.writeByte(NEW_LINE); + writer.write(OBJECT_END); + writer.write(NEW_LINE); } - 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..99f4f9b43c 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,6 +43,7 @@ public class OtelMetricSerializer { private static final Logger logger = LoggerFactory.getLogger(OtelMetricSerializer.class); private final ReporterConfiguration reporterConfig; + private final ReportingTracer tracer; private final StringBuilder serializationTempBuilder; private final Set metricsWithBadAggregations = Collections.newSetFromMap(new ConcurrentHashMap<>()); @@ -52,8 +53,9 @@ 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(); } @@ -150,16 +152,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, serializationTempBuilder); 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 91b982a349..a5119a5a94 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.tracer.GlobalTracer; import co.elastic.apm.agent.sdk.ElasticApmInstrumentation; 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.sdk.internal.util.LoggerUtils; +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; @@ -69,7 +69,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-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..7035fe4f34 --- /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; + +public interface DataWriter { + + void writeFieldName(String name); + + void write(StructureType type); + + void serialize(boolean value); + + void serialize(long value); + + void serialize(double value); + + void writeAscii(String value); + + void writeString(CharSequence replaceBuilder); + + void writeStringValue(CharSequence value, StringBuilder replaceBuilder); + + int size(); + + CharSequence sanitizePropertyName(String key, StringBuilder replaceBuilder); + + void report(); + + enum StructureType { + OBJECT_START, + OBJECT_END, + ARRAY_START, + ARRAY_END, + COMMA, + SEMI, + QUOTE, + NEW_LINE + } +} 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 index 9c8577abd4..68caa70f80 100644 --- 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 @@ -43,6 +43,8 @@ public interface ReportingTracer extends Tracer { */ void reportLog(byte[] log); + DataWriter newWriter(int maxSerializedSize); + ScheduledExecutorService getSharedSingleThreadedPool(); void addShutdownHook(Closeable job); From 2d6e4accc895bb64ce097bdf8ae58cc79ec55a95 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 12:01:42 +0200 Subject: [PATCH 04/21] Remove unused import after merge. --- .../otelmetricsdk/SdkMeterProviderBuilderInstrumentation.java | 1 - 1 file changed, 1 deletion(-) 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 49135abb9f..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 @@ -24,7 +24,6 @@ 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.sdk.internal.util.LoggerUtils; import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.tracer.reporting.ReportingTracer; import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; From fa6181b67dfd3deabde8733eb51fd338a1cd31d5 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 12:14:03 +0200 Subject: [PATCH 05/21] Remove ASCII method as it can be replaced by more convenient calls. --- .../report/serialize/DslJsonDataWriter.java | 9 ++----- .../apm-micrometer-plugin/pom.xml | 6 ----- .../MicrometerMeterRegistrySerializer.java | 25 +++++++++++++------ .../otelmetricsdk/MetricSetSerializer.java | 10 +++----- .../agent/tracer/reporting/DataWriter.java | 4 +-- 5 files changed, 24 insertions(+), 30 deletions(-) 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 index b17cf31b98..54f4d7ff7b 100644 --- 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 @@ -86,13 +86,8 @@ public void serialize(double value) { } @Override - public void writeAscii(String value) { - jw.writeAscii(value); - } - - @Override - public void writeString(CharSequence replaceBuilder) { - jw.writeString(replaceBuilder); + public void writeString(CharSequence value) { + jw.writeString(value); } @Override 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/MicrometerMeterRegistrySerializer.java b/apm-agent-plugins/apm-micrometer-plugin/src/main/java/co/elastic/apm/agent/micrometer/MicrometerMeterRegistrySerializer.java index f794f78ccb..e06145f7b7 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,6 +18,7 @@ */ package co.elastic.apm.agent.micrometer; +import co.elastic.apm.agent.report.serialize.DslJsonDataWriter; 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; @@ -26,6 +27,8 @@ import co.elastic.apm.agent.tracer.configuration.MetricsConfiguration; import co.elastic.apm.agent.tracer.reporting.DataWriter; import co.elastic.apm.agent.tracer.reporting.ReportingTracer; +import com.dslplatform.json.DslJson; +import com.dslplatform.json.JsonWriter; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.DistributionSummary; import io.micrometer.core.instrument.FunctionCounter; @@ -256,9 +259,7 @@ private static void serializeHistogram(Meter.Id id, HistogramSnapshot histogramS } writer.write(ARRAY_END); writer.write(COMMA); - writer.write(QUOTE); - writer.writeAscii("counts"); - writer.write(QUOTE); + writer.writeString("counts"); writer.write(SEMI); writer.write(ARRAY_START); // Micrometer bucket counts are cumulative: E.g. the count at bucket with upper @@ -277,7 +278,8 @@ private static void serializeHistogram(Meter.Id id, HistogramSnapshot histogramS writer.write(ARRAY_END); writer.write(COMMA); - writer.writeAscii("\"type\":\"histogram\""); + writer.writeFieldName("type"); + writer.writeString("histogram"); writer.write(OBJECT_END); } @@ -335,13 +337,20 @@ private static void serializeObjectStart(String key, String objectName, String s writer.write(SEMI); writer.write(OBJECT_START); - writer.write(QUOTE); - writer.writeAscii(objectName); - writer.write(QUOTE); - writer.write(SEMI); + writer.writeFieldName(objectName); } private static boolean isValidValue(double value) { return !Double.isNaN(value) && !Double.isInfinite(value); } + + public static void main(String[] args) { + DslJson dslJson = new DslJson<>(new DslJson.Settings<>()); + JsonWriter jw = dslJson.newWriter(512); + jw.writeAscii("\"foo\""); + //jw.writeString("foo"); + String string = jw.toString(); + System.out.println(string); + + } } 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 9d86b59c50..5dd92dd73d 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 @@ -107,7 +107,8 @@ public void addExplicitBucketHistogram(CharSequence metricName, List bou serializeFieldKeyAscii("counts"); convertAndSerializeHistogramBucketCounts(counts); writer.write(COMMA); - writer.writeAscii("\"type\":\"histogram\""); + writer.writeFieldName("type"); + writer.writeString("histogram"); } writer.write(OBJECT_END); anySamplesWritten = true; @@ -172,10 +173,7 @@ private void serializeFieldKey(CharSequence fieldName) { } private void serializeFieldKeyAscii(String fieldName) { - writer.write(QUOTE); - writer.writeAscii(fieldName); - writer.write(QUOTE); - writer.write(SEMI); + writer.writeFieldName(fieldName); } private void serializeAttributes(CharSequence instrumentationScopeName, Attributes attributes) { @@ -187,7 +185,7 @@ private void serializeAttributes(CharSequence instrumentationScopeName, Attribut writer.write(OBJECT_START); boolean anyWritten = false; if (instrumentationScopeName.length() > 0) { - writer.writeAscii("\"otel_instrumentation_scope_name\":"); + writer.writeFieldName("otel_instrumentation_scope_name"); writer.writeString(instrumentationScopeName); anyWritten = true; } 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 index 7035fe4f34..0a0b2e9c0b 100644 --- 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 @@ -30,9 +30,7 @@ public interface DataWriter { void serialize(double value); - void writeAscii(String value); - - void writeString(CharSequence replaceBuilder); + void writeString(CharSequence value); void writeStringValue(CharSequence value, StringBuilder replaceBuilder); From da91e15b9ba077e1c1e80d8b58fa65b085dd4709 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 12:31:00 +0200 Subject: [PATCH 06/21] Simplify API for JSON writing. --- .../report/serialize/DslJsonDataWriter.java | 26 +++++- .../MicrometerMeterRegistrySerializer.java | 88 ++++++++----------- .../otelmetricsdk/MetricSetSerializer.java | 7 +- .../otelmetricsdk/OtelMetricSerializer.java | 5 +- .../agent/tracer/reporting/DataWriter.java | 6 +- 5 files changed, 66 insertions(+), 66 deletions(-) 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 index 54f4d7ff7b..676eea7bc7 100644 --- 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 @@ -30,6 +30,8 @@ public class DslJsonDataWriter implements DataWriter { private final Reporter reporter; + private final StringBuilder replaceBuilder = new StringBuilder(); + public DslJsonDataWriter(JsonWriter jw, Reporter reporter) { this.jw = jw; this.reporter = reporter; @@ -62,6 +64,8 @@ public void write(StructureType type) { case NEW_LINE: jw.writeByte((byte) '\n'); break; + default: + throw new IllegalArgumentException(); } } @@ -70,6 +74,16 @@ public void writeFieldName(String name) { DslJsonSerializer.writeFieldName(name, jw); } + @Override + public void writeFieldName(String name, boolean sanitized) { + if (sanitized) { + DslJsonSerializer.writeStringValue(DslJsonSerializer.sanitizePropertyName(name, replaceBuilder), replaceBuilder, jw); + jw.writeByte(JsonWriter.SEMI); + } else { + writeFieldName(name); + } + } + @Override public void serialize(boolean value) { BoolConverter.serialize(value, jw); @@ -91,13 +105,17 @@ public void writeString(CharSequence value) { } @Override - public void writeStringValue(CharSequence value, StringBuilder replaceBuilder) { - DslJsonSerializer.writeStringValue(value, replaceBuilder, jw); + public void writeString(CharSequence value, boolean trimmed) { + if (trimmed) { + DslJsonSerializer.writeStringValue(value, replaceBuilder, jw); + } else { + writeString(value); + } } @Override - public CharSequence sanitizePropertyName(String key, StringBuilder replaceBuilder) { - return DslJsonSerializer.sanitizePropertyName(key, replaceBuilder); + public String sanitizePropertyName(String key) { + return DslJsonSerializer.sanitizePropertyName(key, replaceBuilder).toString(); } @Override 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 e06145f7b7..f66563cc53 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,7 +18,6 @@ */ package co.elastic.apm.agent.micrometer; -import co.elastic.apm.agent.report.serialize.DslJsonDataWriter; 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; @@ -61,7 +60,6 @@ public class MicrometerMeterRegistrySerializer { private static final int BUFFER_SIZE_LIMIT = 2048; private static final Logger logger = LoggerFactory.getLogger(MicrometerMeterRegistrySerializer.class); - private final StringBuilder replaceBuilder = new StringBuilder(); private final MetricsConfiguration config; private final ReportingTracer tracer; private final WeakSet internallyDisabledMeters = WeakConcurrent.buildSet(); @@ -91,7 +89,7 @@ public List serialize(final Map metersById, final l } for (Map.Entry, List> entry : metersGroupedByTags.entrySet()) { DataWriter writer = tracer.newWriter(maxSerializedSize); - if (serializeMetricSet(entry.getKey(), entry.getValue(), epochMicros, replaceBuilder, writer)) { + if (serializeMetricSet(entry.getKey(), entry.getValue(), epochMicros, writer)) { serializedMeters.add(writer); maxSerializedSize = Math.max(Math.min(writer.size(), BUFFER_SIZE_LIMIT), maxSerializedSize); } @@ -99,7 +97,7 @@ public List serialize(final Map metersById, final l return serializedMeters; } - boolean serializeMetricSet(List tags, List meters, long epochMicros, StringBuilder replaceBuilder, DataWriter writer) { + boolean serializeMetricSet(List tags, List meters, long epochMicros, DataWriter writer) { boolean hasSamples = false; boolean dedotMetricName = config.isDedotCustomMetrics(); writer.write(OBJECT_START); @@ -110,7 +108,7 @@ boolean serializeMetricSet(List tags, List meters, long epochMicros, writer.writeFieldName("timestamp"); writer.serialize(epochMicros); writer.write(COMMA); - serializeTags(tags, replaceBuilder, writer); + serializeTags(tags, writer); writer.writeFieldName("samples"); writer.write(OBJECT_START); @@ -126,25 +124,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(writer, 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(writer, 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(writer, 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(writer, 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, writer, 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, writer, 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, writer, replaceBuilder, dedotMetricName); + hasSamples = serializeValue(counter.getId(), counter.count(), hasSamples, writer, dedotMetricName); } } catch (Throwable throwable) { String meterName = meter.getId().getName(); @@ -167,7 +165,7 @@ boolean serializeMetricSet(List tags, List meters, long epochMicros, return hasSamples; } - private static void serializeTags(List tags, StringBuilder replaceBuilder, DataWriter writer) { + private static void serializeTags(List tags, DataWriter writer) { if (tags.isEmpty()) { return; } @@ -178,9 +176,8 @@ private static void serializeTags(List tags, StringBuilder replaceBuilder, if (i > 0) { writer.write(COMMA); } - writer.writeStringValue(writer.sanitizePropertyName(tag.getKey(), replaceBuilder), replaceBuilder); - writer.write(SEMI); - writer.writeStringValue(tag.getValue(), replaceBuilder); + writer.writeFieldName(tag.getKey(), true); + writer.writeString(tag.getValue(), true); } writer.write(OBJECT_END); writer.write(COMMA); @@ -195,19 +192,18 @@ private static void serializeTags(List tags, StringBuilder replaceBuilder, * @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(DataWriter writer, 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) writer.write(COMMA); - serializeValue(id, ".count", count, writer, replaceBuilder, dedotMetricName); + serializeValue(id, ".count", count, writer, dedotMetricName); writer.write(COMMA); - serializeValue(id, ".sum.us", totalTime, writer, replaceBuilder, dedotMetricName); + serializeValue(id, ".sum.us", totalTime, writer, dedotMetricName); if (histogramSnapshot != null && histogramSnapshot.histogramCounts().length > 0) { writer.write(COMMA); - serializeHistogram(id, histogramSnapshot, writer, replaceBuilder, dedotMetricName); + serializeHistogram(id, histogramSnapshot, writer, dedotMetricName); } return true; } @@ -223,32 +219,31 @@ private static boolean serializeTimer(DataWriter writer, HistogramSnapshot histo * @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(DataWriter writer, 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) writer.write(COMMA); - serializeValue(id, ".count", count, writer, replaceBuilder, dedotMetricName); + serializeValue(id, ".count", count, writer, dedotMetricName); writer.write(COMMA); - serializeValue(id, ".sum", totalAmount, writer, replaceBuilder, dedotMetricName); + serializeValue(id, ".sum", totalAmount, writer, dedotMetricName); if (histogramSnapshot != null && histogramSnapshot.histogramCounts().length > 0) { writer.write(COMMA); - serializeHistogram(id, histogramSnapshot, writer, replaceBuilder, dedotMetricName); + serializeHistogram(id, histogramSnapshot, writer, dedotMetricName); } return true; } return hasValue; } - private static void serializeHistogram(Meter.Id id, HistogramSnapshot histogramSnapshot, DataWriter writer, 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, writer, replaceBuilder, dedotMetricName); + serializeObjectStart(id.getName(), "values", suffix, writer, dedotMetricName); writer.write(ARRAY_START); if (bucket.length > 0) { writer.serialize(bucket[0].bucket()); @@ -284,8 +279,8 @@ private static void serializeHistogram(Meter.Id id, HistogramSnapshot histogramS writer.write(OBJECT_END); } - private static void serializeValue(Meter.Id id, String suffix, long value, DataWriter writer, StringBuilder replaceBuilder, boolean dedotMetricName) { - serializeValueStart(id.getName(), suffix, writer, replaceBuilder, dedotMetricName); + private static void serializeValue(Meter.Id id, String suffix, long value, DataWriter writer, boolean dedotMetricName) { + serializeValueStart(id.getName(), suffix, writer, dedotMetricName); writer.serialize(value); writer.write(OBJECT_END); } @@ -297,45 +292,36 @@ private static void serializeValue(Meter.Id id, String suffix, long value, DataW * @param value meter value * @param hasValue whether a value has already been written * @param writer writer - * @param replaceBuilder * @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, DataWriter writer, StringBuilder replaceBuilder, boolean dedotMetricName) { + private static boolean serializeValue(Meter.Id id, double value, boolean hasValue, DataWriter writer, boolean dedotMetricName) { if (isValidValue(value)) { if (hasValue) writer.write(COMMA); - serializeValue(id, "", value, writer, replaceBuilder, dedotMetricName); + serializeValue(id, "", value, writer, dedotMetricName); return true; } return hasValue; } - private static void serializeValue(Meter.Id id, String suffix, double value, DataWriter writer, StringBuilder replaceBuilder, boolean dedotMetricName) { - serializeValueStart(id.getName(), suffix, writer, replaceBuilder, dedotMetricName); + private static void serializeValue(Meter.Id id, String suffix, double value, DataWriter writer, boolean dedotMetricName) { + serializeValueStart(id.getName(), suffix, writer, dedotMetricName); writer.serialize(value); writer.write(OBJECT_END); } - private static void serializeValueStart(String key, String suffix, DataWriter writer, StringBuilder replaceBuilder, boolean dedotMetricName) { - serializeObjectStart(key, "value", suffix, writer, 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, DataWriter writer, StringBuilder replaceBuilder, boolean dedotMetricName) { - replaceBuilder.setLength(0); - if (dedotMetricName) { - writer.sanitizePropertyName(key, replaceBuilder); + private static void serializeObjectStart(String key, String objectName, String suffix, DataWriter writer, boolean dedotMetricName) { + String name; + if (suffix == null) { + name = key; } else { - replaceBuilder.append(key); + name = key + suffix; } - if (suffix != null) { - if (replaceBuilder.length() == 0) { - replaceBuilder.append(key); - } - replaceBuilder.append(suffix); - } - writer.writeString(replaceBuilder); - - writer.write(SEMI); + writer.writeFieldName(name, dedotMetricName); writer.write(OBJECT_START); writer.writeFieldName(objectName); } 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 5dd92dd73d..a3d5f98d04 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 @@ -41,12 +41,10 @@ class MetricSetSerializer { private static final int INITIAL_BUFFER_SIZE = 2048; - private final StringBuilder replaceBuilder; private final DataWriter writer; private boolean anySamplesWritten; - public MetricSetSerializer(ReportingTracer tracer, Attributes attributes, CharSequence instrumentationScopeName, long epochMicros, StringBuilder replaceBuilder) { - this.replaceBuilder = replaceBuilder; + public MetricSetSerializer(ReportingTracer tracer, Attributes attributes, CharSequence instrumentationScopeName, long epochMicros) { anySamplesWritten = false; writer = tracer.newWriter(INITIAL_BUFFER_SIZE); writer.write(OBJECT_START); @@ -203,8 +201,7 @@ private boolean serializeAttribute(AttributeKey key, @Nullable Object value, if (prependComma) { writer.write(COMMA); } - writer.writeStringValue(writer.sanitizePropertyName(key.getKey(), replaceBuilder), replaceBuilder); - writer.write(SEMI); + writer.writeFieldName(key.getKey(), true); AttributeType type = key.getType(); switch (type) { 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 99f4f9b43c..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 @@ -44,8 +44,6 @@ public class OtelMetricSerializer { private static final Logger logger = LoggerFactory.getLogger(OtelMetricSerializer.class); private final ReporterConfiguration reporterConfig; private final ReportingTracer tracer; - private final StringBuilder serializationTempBuilder; - private final Set metricsWithBadAggregations = Collections.newSetFromMap(new ConcurrentHashMap<>()); private final Map> metricSets; @@ -57,7 +55,6 @@ public OtelMetricSerializer(ReporterConfiguration reporterConfig, ReportingTrace this.reporterConfig = reporterConfig; this.tracer = tracer; metricSets = new HashMap<>(); - serializationTempBuilder = new StringBuilder(); } public void addValues(MetricData metric) { @@ -152,7 +149,7 @@ private MetricSetSerializer getOrCreateMetricSet(CharSequence instrScopeName, lo MetricSetSerializer ms = timestampMetricSets.get(attributes); if (ms == null) { - ms = new MetricSetSerializer(tracer, attributes, key.instrumentationScopeName, key.timestamp, serializationTempBuilder); + ms = new MetricSetSerializer(tracer, attributes, key.instrumentationScopeName, key.timestamp); timestampMetricSets.put(attributes, ms); } return ms; 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 index 0a0b2e9c0b..1ca1174c45 100644 --- 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 @@ -22,6 +22,8 @@ public interface DataWriter { void writeFieldName(String name); + void writeFieldName(String name, boolean sanitized); + void write(StructureType type); void serialize(boolean value); @@ -32,11 +34,11 @@ public interface DataWriter { void writeString(CharSequence value); - void writeStringValue(CharSequence value, StringBuilder replaceBuilder); + void writeString(CharSequence value, boolean trimmed); int size(); - CharSequence sanitizePropertyName(String key, StringBuilder replaceBuilder); + String sanitizePropertyName(String key); void report(); From c01c2fa6d3be917577d306652491cb88aa369b9f Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 12:38:44 +0200 Subject: [PATCH 07/21] Further simplify API for JSON writing. --- .../report/serialize/DslJsonDataWriter.java | 40 +++--- .../MicrometerMeterRegistrySerializer.java | 105 ++++++++-------- .../otelmetricsdk/MetricSetSerializer.java | 117 ++++++++---------- .../agent/tracer/reporting/DataWriter.java | 24 ++-- 4 files changed, 129 insertions(+), 157 deletions(-) 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 index 676eea7bc7..af2f3f6b3f 100644 --- 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 @@ -38,7 +38,7 @@ public DslJsonDataWriter(JsonWriter jw, Reporter reporter) { } @Override - public void write(StructureType type) { + public void writeStructure(StructureType type) { switch (type) { case OBJECT_START: jw.writeByte(JsonWriter.OBJECT_START); @@ -52,16 +52,10 @@ public void write(StructureType type) { case ARRAY_END: jw.writeByte(JsonWriter.ARRAY_END); break; - case COMMA: + case NEXT: jw.writeByte(JsonWriter.COMMA); break; - case SEMI: - jw.writeByte(JsonWriter.SEMI); - break; - case QUOTE: - jw.writeByte(JsonWriter.QUOTE); - break; - case NEW_LINE: + case NEW: jw.writeByte((byte) '\n'); break; default: @@ -70,54 +64,50 @@ public void write(StructureType type) { } @Override - public void writeFieldName(String name) { - DslJsonSerializer.writeFieldName(name, jw); + public void writeKey(CharSequence name) { + jw.writeString(name); + jw.writeByte(JsonWriter.SEMI); } @Override - public void writeFieldName(String name, boolean sanitized) { + public void writeKey(CharSequence name, boolean sanitized) { if (sanitized) { - DslJsonSerializer.writeStringValue(DslJsonSerializer.sanitizePropertyName(name, replaceBuilder), replaceBuilder, jw); + DslJsonSerializer.writeStringValue(DslJsonSerializer.sanitizePropertyName(name.toString(), replaceBuilder), replaceBuilder, jw); jw.writeByte(JsonWriter.SEMI); } else { - writeFieldName(name); + writeKey(name); } } @Override - public void serialize(boolean value) { + public void writeValue(boolean value) { BoolConverter.serialize(value, jw); } @Override - public void serialize(long value) { + public void writeValue(long value) { NumberConverter.serialize(value, jw); } @Override - public void serialize(double value) { + public void writeValue(double value) { NumberConverter.serialize(value, jw); } @Override - public void writeString(CharSequence value) { + public void writeValue(CharSequence value) { jw.writeString(value); } @Override - public void writeString(CharSequence value, boolean trimmed) { + public void writeValue(CharSequence value, boolean trimmed) { if (trimmed) { DslJsonSerializer.writeStringValue(value, replaceBuilder, jw); } else { - writeString(value); + writeValue(value); } } - @Override - public String sanitizePropertyName(String key) { - return DslJsonSerializer.sanitizePropertyName(key, replaceBuilder).toString(); - } - @Override public int size() { return jw.size(); 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 f66563cc53..14e207a71d 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 @@ -48,12 +48,10 @@ 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.COMMA; -import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.NEW_LINE; +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; -import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.QUOTE; -import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.SEMI; public class MicrometerMeterRegistrySerializer { @@ -100,17 +98,17 @@ public List serialize(final Map metersById, final l boolean serializeMetricSet(List tags, List meters, long epochMicros, DataWriter writer) { boolean hasSamples = false; boolean dedotMetricName = config.isDedotCustomMetrics(); - writer.write(OBJECT_START); + writer.writeStructure(OBJECT_START); { - writer.writeFieldName("metricset"); - writer.write(OBJECT_START); + writer.writeKey("metricset"); + writer.writeStructure(OBJECT_START); { - writer.writeFieldName("timestamp"); - writer.serialize(epochMicros); - writer.write(COMMA); + writer.writeKey("timestamp"); + writer.writeValue(epochMicros); + writer.writeStructure(NEXT); serializeTags(tags, writer); - writer.writeFieldName("samples"); - writer.write(OBJECT_START); + writer.writeKey("samples"); + writer.writeStructure(OBJECT_START); ClassLoader originalContextCL = PrivilegedActionUtils.getContextClassLoader(Thread.currentThread()); try { @@ -156,12 +154,12 @@ boolean serializeMetricSet(List tags, List meters, long epochMicros, } finally { PrivilegedActionUtils.setContextClassLoader(Thread.currentThread(), originalContextCL); } - writer.write(OBJECT_END); + writer.writeStructure(OBJECT_END); } - writer.write(OBJECT_END); + writer.writeStructure(OBJECT_END); } - writer.write(OBJECT_END); - writer.write(NEW_LINE); + writer.writeStructure(OBJECT_END); + writer.writeStructure(NEW); return hasSamples; } @@ -169,18 +167,18 @@ private static void serializeTags(List tags, DataWriter writer) { if (tags.isEmpty()) { return; } - writer.writeFieldName("tags"); - writer.write(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) { - writer.write(COMMA); + writer.writeStructure(NEXT); } - writer.writeFieldName(tag.getKey(), true); - writer.writeString(tag.getValue(), true); + writer.writeKey(tag.getKey(), true); + writer.writeValue(tag.getValue(), true); } - writer.write(OBJECT_END); - writer.write(COMMA); + writer.writeStructure(OBJECT_END); + writer.writeStructure(NEXT); } /** @@ -197,12 +195,12 @@ private static void serializeTags(List tags, DataWriter writer) { */ private static boolean serializeTimer(DataWriter writer, HistogramSnapshot histogramSnapshot, Meter.Id id, long count, double totalTime, boolean hasValue, boolean dedotMetricName) { if (isValidValue(totalTime)) { - if (hasValue) writer.write(COMMA); + if (hasValue) writer.writeStructure(NEXT); serializeValue(id, ".count", count, writer, dedotMetricName); - writer.write(COMMA); + writer.writeStructure(NEXT); serializeValue(id, ".sum.us", totalTime, writer, dedotMetricName); if (histogramSnapshot != null && histogramSnapshot.histogramCounts().length > 0) { - writer.write(COMMA); + writer.writeStructure(NEXT); serializeHistogram(id, histogramSnapshot, writer, dedotMetricName); } return true; @@ -224,12 +222,12 @@ private static boolean serializeTimer(DataWriter writer, HistogramSnapshot histo */ private static boolean serializeDistributionSummary(DataWriter writer, HistogramSnapshot histogramSnapshot, Meter.Id id, long count, double totalAmount, boolean hasValue, boolean dedotMetricName) { if (isValidValue(totalAmount)) { - if (hasValue) writer.write(COMMA); + if (hasValue) writer.writeStructure(NEXT); serializeValue(id, ".count", count, writer, dedotMetricName); - writer.write(COMMA); + writer.writeStructure(NEXT); serializeValue(id, ".sum", totalAmount, writer, dedotMetricName); if (histogramSnapshot != null && histogramSnapshot.histogramCounts().length > 0) { - writer.write(COMMA); + writer.writeStructure(NEXT); serializeHistogram(id, histogramSnapshot, writer, dedotMetricName); } return true; @@ -244,45 +242,44 @@ private static void serializeHistogram(Meter.Id id, HistogramSnapshot histogramS String suffix = ".histogram"; CountAtBucket[] bucket = histogramSnapshot.histogramCounts(); serializeObjectStart(id.getName(), "values", suffix, writer, dedotMetricName); - writer.write(ARRAY_START); + writer.writeStructure(ARRAY_START); if (bucket.length > 0) { - writer.serialize(bucket[0].bucket()); + writer.writeValue(bucket[0].bucket()); for (int i = 1; i < bucket.length; i++) { - writer.write(COMMA); - writer.serialize(bucket[i].bucket()); + writer.writeStructure(NEXT); + writer.writeValue(bucket[i].bucket()); } } - writer.write(ARRAY_END); - writer.write(COMMA); - writer.writeString("counts"); - writer.write(SEMI); - writer.write(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) { - writer.serialize((long) bucket[0].count()); + writer.writeValue((long) bucket[0].count()); double prevBucketCount = bucket[0].count(); for (int i = 1; i < bucket.length; i++) { - writer.write(COMMA); - writer.serialize((long) (bucket[i].count() - prevBucketCount)); + writer.writeStructure(NEXT); + writer.writeValue((long) (bucket[i].count() - prevBucketCount)); prevBucketCount = bucket[i].count(); } } - writer.write(ARRAY_END); + writer.writeStructure(ARRAY_END); - writer.write(COMMA); - writer.writeFieldName("type"); - writer.writeString("histogram"); + writer.writeStructure(NEXT); + writer.writeKey("type"); + writer.writeValue("histogram"); - writer.write(OBJECT_END); + writer.writeStructure(OBJECT_END); } private static void serializeValue(Meter.Id id, String suffix, long value, DataWriter writer, boolean dedotMetricName) { serializeValueStart(id.getName(), suffix, writer, dedotMetricName); - writer.serialize(value); - writer.write(OBJECT_END); + writer.writeValue(value); + writer.writeStructure(OBJECT_END); } /** @@ -297,7 +294,7 @@ private static void serializeValue(Meter.Id id, String suffix, long value, DataW */ private static boolean serializeValue(Meter.Id id, double value, boolean hasValue, DataWriter writer, boolean dedotMetricName) { if (isValidValue(value)) { - if (hasValue) writer.write(COMMA); + if (hasValue) writer.writeStructure(NEXT); serializeValue(id, "", value, writer, dedotMetricName); return true; } @@ -306,8 +303,8 @@ private static boolean serializeValue(Meter.Id id, double value, boolean hasValu private static void serializeValue(Meter.Id id, String suffix, double value, DataWriter writer, boolean dedotMetricName) { serializeValueStart(id.getName(), suffix, writer, dedotMetricName); - writer.serialize(value); - writer.write(OBJECT_END); + writer.writeValue(value); + writer.writeStructure(OBJECT_END); } private static void serializeValueStart(String key, String suffix, DataWriter writer, boolean dedotMetricName) { @@ -321,9 +318,9 @@ private static void serializeObjectStart(String key, String objectName, String s } else { name = key + suffix; } - writer.writeFieldName(name, dedotMetricName); - writer.write(OBJECT_START); - writer.writeFieldName(objectName); + writer.writeKey(name, dedotMetricName); + writer.writeStructure(OBJECT_START); + writer.writeKey(objectName); } private static boolean isValidValue(double value) { 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 a3d5f98d04..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 @@ -30,12 +30,10 @@ 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.COMMA; -import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.NEW_LINE; +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; -import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.QUOTE; -import static co.elastic.apm.agent.tracer.reporting.DataWriter.StructureType.SEMI; class MetricSetSerializer { @@ -47,17 +45,17 @@ class MetricSetSerializer { public MetricSetSerializer(ReportingTracer tracer, Attributes attributes, CharSequence instrumentationScopeName, long epochMicros) { anySamplesWritten = false; writer = tracer.newWriter(INITIAL_BUFFER_SIZE); - writer.write(OBJECT_START); + writer.writeStructure(OBJECT_START); { - writer.writeFieldName("metricset"); - writer.write(OBJECT_START); + writer.writeKey("metricset"); + writer.writeStructure(OBJECT_START); { - writer.writeFieldName("timestamp"); - writer.serialize(epochMicros); - writer.write(COMMA); + writer.writeKey("timestamp"); + writer.writeValue(epochMicros); + writer.writeStructure(NEXT); serializeAttributes(instrumentationScopeName, attributes); - writer.writeFieldName("samples"); - writer.write(OBJECT_START); + writer.writeKey("samples"); + writer.writeStructure(OBJECT_START); } } } @@ -72,19 +70,19 @@ public void addValue(CharSequence metricName, long value) { private void addValue(CharSequence metricName, boolean isDouble, long longVal, double doubleVal) { if (anySamplesWritten) { - writer.write(COMMA); + writer.writeStructure(NEXT); } - serializeFieldKey(metricName); - writer.write(OBJECT_START); + writer.writeKey(metricName); + writer.writeStructure(OBJECT_START); { - serializeFieldKeyAscii("value"); + writer.writeKey("value"); if (isDouble) { - writer.serialize(doubleVal); + writer.writeValue(doubleVal); } else { - writer.serialize(longVal); + writer.writeValue(longVal); } } - writer.write(OBJECT_END); + writer.writeStructure(OBJECT_END); anySamplesWritten = true; } @@ -94,21 +92,21 @@ public void addExplicitBucketHistogram(CharSequence metricName, List bou return; } if (anySamplesWritten) { - writer.write(COMMA); + writer.writeStructure(NEXT); } - serializeFieldKey(metricName); - writer.write(OBJECT_START); + writer.writeKey(metricName); + writer.writeStructure(OBJECT_START); { - serializeFieldKeyAscii("values"); + writer.writeKey("values"); convertAndSerializeHistogramBucketBoundaries(boundaries, counts); - writer.write(COMMA); - serializeFieldKeyAscii("counts"); + writer.writeStructure(NEXT); + writer.writeKey("counts"); convertAndSerializeHistogramBucketCounts(counts); - writer.write(COMMA); - writer.writeFieldName("type"); - writer.writeString("histogram"); + writer.writeStructure(NEXT); + writer.writeKey("type"); + writer.writeValue("histogram"); } - writer.write(OBJECT_END); + writer.writeStructure(OBJECT_END); anySamplesWritten = true; } @@ -122,29 +120,29 @@ private boolean isEmptyHistogram(List boundaries, List counts) { } private void convertAndSerializeHistogramBucketCounts(List counts) { - writer.write(ARRAY_START); + writer.writeStructure(ARRAY_START); boolean firstElement = true; for (long count : counts) { if (count != 0) { if (!firstElement) { - writer.write(COMMA); + writer.writeStructure(NEXT); } firstElement = false; - writer.serialize(count); + writer.writeValue(count); } } - writer.write(ARRAY_END); + writer.writeStructure(ARRAY_END); } private void convertAndSerializeHistogramBucketBoundaries(List boundaries, List counts) { - writer.write(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) { - writer.write(COMMA); + writer.writeStructure(NEXT); } firstElement = false; if (i == 0) { @@ -152,26 +150,17 @@ private void convertAndSerializeHistogramBucketBoundaries(List boundarie if (bounds > 0) { bounds /= 2; } - writer.serialize(bounds); + writer.writeValue(bounds); } else if (i == bucketCount - 1) { - writer.serialize(boundaries.get(bucketCount - 2)); + writer.writeValue(boundaries.get(bucketCount - 2)); } else { double lower = boundaries.get(i - 1); double upper = boundaries.get(i); - writer.serialize(lower + (upper - lower) / 2); + writer.writeValue(lower + (upper - lower) / 2); } } } - writer.write(ARRAY_END); - } - - private void serializeFieldKey(CharSequence fieldName) { - writer.writeString(fieldName); - writer.write(SEMI); - } - - private void serializeFieldKeyAscii(String fieldName) { - writer.writeFieldName(fieldName); + writer.writeStructure(ARRAY_END); } private void serializeAttributes(CharSequence instrumentationScopeName, Attributes attributes) { @@ -179,12 +168,12 @@ private void serializeAttributes(CharSequence instrumentationScopeName, Attribut if (attributeMap.isEmpty() && instrumentationScopeName.length() == 0) { return; } - writer.writeFieldName("tags"); - writer.write(OBJECT_START); + writer.writeKey("tags"); + writer.writeStructure(OBJECT_START); boolean anyWritten = false; if (instrumentationScopeName.length() > 0) { - writer.writeFieldName("otel_instrumentation_scope_name"); - writer.writeString(instrumentationScopeName); + writer.writeKey("otel_instrumentation_scope_name"); + writer.writeValue(instrumentationScopeName); anyWritten = true; } for (Map.Entry, Object> entry : attributeMap.entrySet()) { @@ -192,30 +181,30 @@ private void serializeAttributes(CharSequence instrumentationScopeName, Attribut Object value = entry.getValue(); anyWritten |= serializeAttribute(key, value, anyWritten); } - writer.write(OBJECT_END); - writer.write(COMMA); + writer.writeStructure(OBJECT_END); + writer.writeStructure(NEXT); } private boolean serializeAttribute(AttributeKey key, @Nullable Object value, boolean prependComma) { if (isValidAttributeValue(key, value)) { if (prependComma) { - writer.write(COMMA); + writer.writeStructure(NEXT); } - writer.writeFieldName(key.getKey(), true); + writer.writeKey(key.getKey(), true); AttributeType type = key.getType(); switch (type) { case STRING: - writer.writeString((CharSequence) value); + writer.writeValue((CharSequence) value); return true; case BOOLEAN: - writer.serialize((Boolean) value); + writer.writeValue((Boolean) value); return true; case LONG: - writer.serialize(((Number) value).longValue()); + writer.writeValue(((Number) value).longValue()); return true; case DOUBLE: - writer.serialize(((Number) value).doubleValue()); + writer.writeValue(((Number) value).doubleValue()); return true; case STRING_ARRAY: case BOOLEAN_ARRAY: @@ -256,13 +245,13 @@ private void serializeMetricSetEnd() { { /*"samples":*/ { - writer.write(OBJECT_END); + writer.writeStructure(OBJECT_END); } } - writer.write(OBJECT_END); + writer.writeStructure(OBJECT_END); } - writer.write(OBJECT_END); - writer.write(NEW_LINE); + writer.writeStructure(OBJECT_END); + writer.writeStructure(NEW); } public void finishAndReport() { 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 index 1ca1174c45..9fc099845c 100644 --- 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 @@ -20,26 +20,24 @@ public interface DataWriter { - void writeFieldName(String name); + void writeStructure(StructureType type); - void writeFieldName(String name, boolean sanitized); + void writeKey(CharSequence name); - void write(StructureType type); + void writeKey(CharSequence name, boolean sanitized); - void serialize(boolean value); + void writeValue(boolean value); - void serialize(long value); + void writeValue(long value); - void serialize(double value); + void writeValue(double value); - void writeString(CharSequence value); + void writeValue(CharSequence value); - void writeString(CharSequence value, boolean trimmed); + void writeValue(CharSequence value, boolean trimmed); int size(); - String sanitizePropertyName(String key); - void report(); enum StructureType { @@ -47,9 +45,7 @@ enum StructureType { OBJECT_END, ARRAY_START, ARRAY_END, - COMMA, - SEMI, - QUOTE, - NEW_LINE + NEXT, + NEW } } From b136b3d71698de4bac155847aaa5bb662cfcbaf3 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 12:39:26 +0200 Subject: [PATCH 08/21] Remove test code. --- .../MicrometerMeterRegistrySerializer.java | 12 ------------ 1 file changed, 12 deletions(-) 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 14e207a71d..590cf1a4f3 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 @@ -26,8 +26,6 @@ import co.elastic.apm.agent.tracer.configuration.MetricsConfiguration; import co.elastic.apm.agent.tracer.reporting.DataWriter; import co.elastic.apm.agent.tracer.reporting.ReportingTracer; -import com.dslplatform.json.DslJson; -import com.dslplatform.json.JsonWriter; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.DistributionSummary; import io.micrometer.core.instrument.FunctionCounter; @@ -326,14 +324,4 @@ private static void serializeObjectStart(String key, String objectName, String s private static boolean isValidValue(double value) { return !Double.isNaN(value) && !Double.isInfinite(value); } - - public static void main(String[] args) { - DslJson dslJson = new DslJson<>(new DslJson.Settings<>()); - JsonWriter jw = dslJson.newWriter(512); - jw.writeAscii("\"foo\""); - //jw.writeString("foo"); - String string = jw.toString(); - System.out.println(string); - - } } From 72e5079d56133bfd930a66dae22a249d26cb877b Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 12:57:49 +0200 Subject: [PATCH 09/21] Add toString function to support tests. --- .../apm/agent/report/serialize/DslJsonDataWriter.java | 5 +++++ .../micrometer/MicrometerMeterRegistrySerializerTest.java | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) 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 index af2f3f6b3f..dd76658a92 100644 --- 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 @@ -117,4 +117,9 @@ public int size() { public void report() { reporter.reportMetrics(jw); } + + @Override + public String toString() { + return jw.toString(); + } } 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 5481763853..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 @@ -65,8 +65,8 @@ static void setup() { when(tracer.newWriter(anyInt())).thenAnswer(new Answer() { @Override public DataWriter answer(InvocationOnMock invocationOnMock) { - int size = invocationOnMock.getArgument(0); - return new DslJsonDataWriter(dslJson.newWriter(size), reporter); + int maxSerializedSize = invocationOnMock.getArgument(0); + return new DslJsonDataWriter(dslJson.newWriter(maxSerializedSize), reporter); } }); serializer = new MicrometerMeterRegistrySerializer(config, tracer); From e3de0e4de21166637dd201142f01795efbf24e99 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 15:56:22 +0200 Subject: [PATCH 10/21] Avoid escaping of suffix. --- .../report/serialize/DslJsonDataWriter.java | 20 +++++++++++++++++++ .../MicrometerMeterRegistrySerializer.java | 6 +++++- .../agent/tracer/reporting/DataWriter.java | 4 ++++ 3 files changed, 29 insertions(+), 1 deletion(-) 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 index dd76658a92..b12c6f592b 100644 --- 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 @@ -24,6 +24,8 @@ import com.dslplatform.json.JsonWriter; import com.dslplatform.json.NumberConverter; +import javax.annotation.Nullable; + public class DslJsonDataWriter implements DataWriter { private final JsonWriter jw; @@ -79,6 +81,24 @@ public void writeKey(CharSequence name, boolean sanitized) { } } + @Override + public void writeKey(CharSequence name, @Nullable String suffix, boolean sanitized) { + 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); 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 590cf1a4f3..b202cfd86e 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 @@ -316,7 +316,11 @@ private static void serializeObjectStart(String key, String objectName, String s } else { name = key + suffix; } - writer.writeKey(name, dedotMetricName); + if (suffix == null) { + writer.writeKey(name, dedotMetricName); + } else { + writer.writeKey(name, suffix, dedotMetricName); + } writer.writeStructure(OBJECT_START); writer.writeKey(objectName); } 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 index 9fc099845c..1538e53eca 100644 --- 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 @@ -18,6 +18,8 @@ */ package co.elastic.apm.agent.tracer.reporting; +import javax.annotation.Nullable; + public interface DataWriter { void writeStructure(StructureType type); @@ -26,6 +28,8 @@ public interface DataWriter { void writeKey(CharSequence name, boolean sanitized); + void writeKey(CharSequence name, @Nullable String suffix, boolean sanitized); + void writeValue(boolean value); void writeValue(long value); From d7887c38d18a033bd174ccd42866eaee08b69cfc Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 16:05:04 +0200 Subject: [PATCH 11/21] Avoid duplicate escaping of suffix. --- .../agent/report/serialize/DslJsonDataWriter.java | 2 +- .../MicrometerMeterRegistrySerializer.java | 12 +----------- .../apm/agent/tracer/reporting/DataWriter.java | 2 +- 3 files changed, 3 insertions(+), 13 deletions(-) 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 index b12c6f592b..235c7cd76d 100644 --- 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 @@ -82,7 +82,7 @@ public void writeKey(CharSequence name, boolean sanitized) { } @Override - public void writeKey(CharSequence name, @Nullable String suffix, boolean sanitized) { + public void writeKey(CharSequence name, boolean sanitized, @Nullable String suffix) { replaceBuilder.setLength(0); if (sanitized) { DslJsonSerializer.sanitizePropertyName(name.toString(), replaceBuilder); 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 b202cfd86e..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 @@ -310,17 +310,7 @@ private static void serializeValueStart(String key, String suffix, DataWriter wr } private static void serializeObjectStart(String key, String objectName, String suffix, DataWriter writer, boolean dedotMetricName) { - String name; - if (suffix == null) { - name = key; - } else { - name = key + suffix; - } - if (suffix == null) { - writer.writeKey(name, dedotMetricName); - } else { - writer.writeKey(name, suffix, dedotMetricName); - } + writer.writeKey(key, dedotMetricName, suffix); writer.writeStructure(OBJECT_START); writer.writeKey(objectName); } 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 index 1538e53eca..80232a06b1 100644 --- 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 @@ -28,7 +28,7 @@ public interface DataWriter { void writeKey(CharSequence name, boolean sanitized); - void writeKey(CharSequence name, @Nullable String suffix, boolean sanitized); + void writeKey(CharSequence name, boolean sanitized, @Nullable String suffix); void writeValue(boolean value); From ae642f8b0da1b497b72cec49ab4ebcfe327175da Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 15:08:46 +0200 Subject: [PATCH 12/21] Add support for direct tracing. --- .../apm/agent/impl/ElasticApmTracer.java | 14 +- .../co/elastic/apm/agent/impl/Tracer.java | 3 +- .../agent/impl/transaction/AbstractSpan.java | 19 ++- .../apm/agent/impl/transaction/Id.java | 1 + .../apm/agent/impl/transaction/Span.java | 6 +- .../agent/impl/transaction/TraceContext.java | 13 +- .../agent/impl/transaction/Transaction.java | 2 +- .../elastic/apm/agent/TransactionUtils.java | 2 +- .../apm/agent/impl/ElasticApmTracerTest.java | 2 +- .../apm/agent/impl/SpanTypeBreakdownTest.java | 2 +- .../apm/agent/impl/transaction/SpanTest.java | 2 +- .../impl/transaction/TraceContextTest.java | 5 +- .../TraceContinuationStrategyTest.java | 2 +- .../impl/transaction/TransactionTest.java | 2 +- .../serialize/DslJsonSerializerTest.java | 4 +- .../jms/jakarta/JmsInstrumentationIT.java | 4 +- .../agent/jms/javax/JmsInstrumentationIT.java | 4 +- .../co/elastic/apm/agent/kafka/KafkaIT.java | 4 +- .../tracing/OTelSpanLinkTest.java | 2 +- .../apm-opentracing-plugin/pom.xml | 9 -- .../ApmScopeInstrumentation.java | 2 +- .../ApmSpanBuilderInstrumentation.java | 41 +++--- .../ApmSpanInstrumentation.java | 59 +++++---- .../ElasticApmTracerInstrumentation.java | 3 +- .../ExternalSpanContextInstrumentation.java | 12 +- .../OpenTracingBridgeInstrumentation.java | 3 +- .../ScopeManagerInstrumentation.java | 2 +- .../SpanContextInstrumentation.java | 4 +- .../apm/agent/profiler/CallTreeTest.java | 2 +- .../apm/agent/tracer/AbstractSpan.java | 2 - .../java/co/elastic/apm/agent/tracer/Id.java | 2 + .../tracer/direct/AbstractDirectSpan.java | 36 +++++ .../agent/tracer/direct}/ConstantSampler.java | 13 +- .../apm/agent/tracer/direct/DirectSpan.java | 29 ++++ .../apm/agent/tracer/direct/DirectTracer.java | 43 ++++++ .../tracer/direct}/ProbabilitySampler.java | 14 +- .../apm/agent/tracer/direct}/Sampler.java | 19 +-- .../apm/agent/tracer/metadata/User.java | 4 + .../direct}/ProbabilitySamplerTest.java | 27 +--- .../apm/agent/tracer/direct/TestId.java | 124 ++++++++++++++++++ apm-opentracing/pom.xml | 6 + 41 files changed, 386 insertions(+), 163 deletions(-) create mode 100644 apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/AbstractDirectSpan.java rename {apm-agent-core/src/main/java/co/elastic/apm/agent/impl/sampling => apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct}/ConstantSampler.java (82%) create mode 100644 apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/DirectSpan.java create mode 100644 apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/DirectTracer.java rename {apm-agent-core/src/main/java/co/elastic/apm/agent/impl/sampling => apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct}/ProbabilitySampler.java (86%) rename {apm-agent-core/src/main/java/co/elastic/apm/agent/impl/sampling => apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct}/Sampler.java (73%) rename {apm-agent-core/src/test/java/co/elastic/apm/agent/impl/sampling => apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/direct}/ProbabilitySamplerTest.java (74%) create mode 100644 apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/direct/TestId.java 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 7ce38364cc..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 @@ -39,8 +39,8 @@ 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; @@ -307,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, 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 61d2c5b899..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; @@ -32,6 +32,7 @@ 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 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..ff805ed737 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); @@ -518,18 +521,21 @@ public String captureExceptionAndGetErrorId(@Nullable Throwable t) { return captureExceptionAndGetErrorId(getTraceContext().getClock().getEpochMicros(), t); } + @Override public void addLabel(String key, String value) { if (isSampled()) { getContext().addLabel(key, value); } } + @Override public void addLabel(String key, Number value) { if (isSampled()) { getContext().addLabel(key, value); } } + @Override public void addLabel(String key, Boolean value) { if (isSampled()) { getContext().addLabel(key, value); @@ -557,6 +563,7 @@ public void end() { end(traceContext.getClock().getEpochMicros()); } + @Override public final void end(long epochMicros) { if (!finished) { this.endTimestamp.set(epochMicros); @@ -792,4 +799,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 e9f59a6095..06f4a2d7e1 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,7 +26,7 @@ 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.tracer.direct.Sampler; import co.elastic.apm.agent.tracer.reporting.Labels; import co.elastic.apm.agent.metrics.MetricRegistry; import co.elastic.apm.agent.metrics.Timer; 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 2b85dc0543..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,7 +27,7 @@ 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; 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 c5bd601ae3..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,7 +22,7 @@ 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; 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/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-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-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-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..990049ef45 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,11 @@ */ 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.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 +32,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 +69,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,15 +122,14 @@ 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) { + span.captureException((Throwable) errorObject); if (epochTimestampMicros > 0) { - span.captureExceptionAndGetErrorId(epochTimestampMicros, (Throwable) errorObject); - } else { - span.captureException((Throwable) errorObject); + span.end(epochTimestampMicros); } } } @@ -152,28 +154,30 @@ 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 AbstractDirectSpan) { + if (abstractSpanObj instanceof Transaction) { + handleTransactionTag((Transaction) abstractSpanObj, (AbstractDirectSpan) 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(Transaction transaction, AbstractDirectSpan span, String key, Object value) { if (!handleSpecialTransactionTag(transaction, key, value)) { - addTag(transaction, key, value); + addTag(span, 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/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-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..277ce14556 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 @@ -151,6 +151,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-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..fb435ab812 --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/AbstractDirectSpan.java @@ -0,0 +1,36 @@ +/* + * 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; + +public interface AbstractDirectSpan> extends AbstractSpan { + + DirectSpan spanChild(); + + DirectSpan spanChild(long epochMicros); + + void end(long epochMicros); + + void addLabel(String key, Number value); + + void addLabel(String key, Boolean 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-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-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-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 From 742e76efa913db9f5c9c60cec0a2467bd0c324a3 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 16:40:04 +0200 Subject: [PATCH 13/21] Fix mock in test. --- .../apm/agent/configuration/ConfigurationExporterTest.java | 3 +++ 1 file changed, 3 insertions(+) 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..4e1d1ce90c 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,6 +90,7 @@ class ConfigurationExporterTest { void setUp() { renderedDocumentationPath = Paths.get("../../docs/configuration.asciidoc"); ElasticApmTracer tracer = mock(ElasticApmTracer.class); + when(tracer.require(ReportingTracer.class)).thenReturn(tracer); doReturn(tracer).when(tracer).require(ElasticApmTracer.class); doReturn(Tracer.TracerState.UNINITIALIZED).when(tracer).getState(); GlobalTracer.init(tracer); From 3ea33c8ad3ccb3d40ebfa7c98119ea596d35fc4e Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Thu, 28 Sep 2023 16:42:30 +0200 Subject: [PATCH 14/21] Fix configuration exporter. --- .../elastic/apm/agent/configuration/ConfigurationExporter.java | 3 ++- .../apm/agent/configuration/ConfigurationExporterTest.java | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) 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 4e1d1ce90c..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 @@ -90,8 +90,7 @@ class ConfigurationExporterTest { void setUp() { renderedDocumentationPath = Paths.get("../../docs/configuration.asciidoc"); ElasticApmTracer tracer = mock(ElasticApmTracer.class); - when(tracer.require(ReportingTracer.class)).thenReturn(tracer); - 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() From 6830206a9d5d803be55f88e7cb5dce1cf0447149 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Fri, 29 Sep 2023 11:54:02 +0200 Subject: [PATCH 15/21] Fix incorrect API port. --- .../apm/agent/impl/transaction/AbstractSpan.java | 15 ++++++++++++--- .../opentracingimpl/ApmSpanInstrumentation.java | 5 +++-- .../agent/tracer/direct/AbstractDirectSpan.java | 8 ++++++-- 3 files changed, 21 insertions(+), 7 deletions(-) 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 ff805ed737..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 @@ -512,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(); } @@ -521,8 +530,9 @@ public String captureExceptionAndGetErrorId(@Nullable Throwable t) { return captureExceptionAndGetErrorId(getTraceContext().getClock().getEpochMicros(), t); } + @Override - public void addLabel(String key, String value) { + public void addLabel(String key, Boolean value) { if (isSampled()) { getContext().addLabel(key, value); } @@ -534,9 +544,8 @@ public void addLabel(String key, Number value) { getContext().addLabel(key, value); } } - @Override - public void addLabel(String key, Boolean value) { + public void addLabel(String key, String value) { if (isSampled()) { getContext().addLabel(key, value); } 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 990049ef45..43d08428a4 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 @@ -127,9 +127,10 @@ public static void log(@Advice.FieldValue(value = "dispatcher", typing = Assigne if ("error".equals(fields.get("event"))) { final Object errorObject = fields.get("error.object"); if (errorObject instanceof Throwable) { - span.captureException((Throwable) errorObject); if (epochTimestampMicros > 0) { - span.end(epochTimestampMicros); + span.captureException((Throwable) errorObject, epochTimestampMicros); + } else { + span.captureException((Throwable) errorObject); } } } 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 index fb435ab812..e3da31c463 100644 --- 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 @@ -20,17 +20,21 @@ import co.elastic.apm.agent.tracer.AbstractSpan; +import javax.annotation.Nullable; + public interface AbstractDirectSpan> extends AbstractSpan { DirectSpan spanChild(); DirectSpan spanChild(long epochMicros); - void end(long epochMicros); + T captureException(@Nullable Throwable t, long epochMicros); - void addLabel(String key, Number value); + void end(long epochMicros); void addLabel(String key, Boolean value); + void addLabel(String key, Number value); + void addLabel(String key, String value); } From 020de775fa4d8090e7ea11eb958a9806d52a6c73 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Fri, 29 Sep 2023 12:09:17 +0200 Subject: [PATCH 16/21] Add direct transaction equivalent. --- .../agent/impl/transaction/Transaction.java | 5 +++- .../ApmSpanInstrumentation.java | 15 ++++++----- .../apm/agent/tracer/AbstractSpan.java | 1 - .../tracer/direct/DirectTransaction.java | 25 +++++++++++++++++++ 4 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/direct/DirectTransaction.java 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 06f4a2d7e1..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 @@ -27,6 +27,7 @@ import co.elastic.apm.agent.impl.context.Response; import co.elastic.apm.agent.impl.context.TransactionContext; 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; @@ -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-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 43d08428a4..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 @@ -22,6 +22,7 @@ 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 net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -155,20 +156,18 @@ public static void handleTag(@Advice.FieldValue(value = "dispatcher", typing = A if (value == null) { return; } - if (abstractSpanObj instanceof AbstractDirectSpan) { - if (abstractSpanObj instanceof Transaction) { - handleTransactionTag((Transaction) abstractSpanObj, (AbstractDirectSpan) abstractSpanObj, key, value); - } else if (abstractSpanObj instanceof DirectSpan) { - handleSpanTag((DirectSpan) 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, AbstractDirectSpan span, String key, Object value) { + private static void handleTransactionTag(DirectTransaction transaction, String key, Object value) { if (!handleSpecialTransactionTag(transaction, key, value)) { - addTag(span, key, value); + addTag(transaction, key, value); } } 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 277ce14556..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); 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 { + +} From 9fefdb5f654462fd2d319b12845147aaf9e7f5e0 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Fri, 29 Sep 2023 15:45:29 +0200 Subject: [PATCH 17/21] Remove dependency of AWS tracer onto agent-core module. --- .../apm/agent/impl/ElasticApmTracer.java | 18 ++++++++ .../apm/agent/impl/context/ServiceOrigin.java | 5 +- .../impl/context/TransactionContext.java | 1 + .../apm/agent/impl/transaction/Faas.java | 15 +++++- .../apm-awslambda-plugin/pom.xml | 6 --- ...stractAwsLambdaHandlerInstrumentation.java | 4 +- .../RequestHandlerInstrumentation.java | 10 ++-- .../RequestStreamHandlerInstrumentation.java | 10 ++-- .../APIGatewayProxyV1TransactionHelper.java | 12 ++--- .../APIGatewayProxyV2TransactionHelper.java | 12 ++--- .../awslambda/helper/AWSEventsHelper.java | 6 +-- .../AbstractAPIGatewayTransactionHelper.java | 40 +++++++--------- .../AbstractLambdaTransactionHelper.java | 46 ++++++------------- ...AbstractMessageBasedTransactionHelper.java | 24 +++++----- .../helper/PlainTransactionHelper.java | 16 +++---- .../awslambda/helper/S3TransactionHelper.java | 27 +++++------ .../helper/SNSTransactionHelper.java | 10 ++-- .../helper/SQSTransactionHelper.java | 10 ++-- .../apm/agent/tracer/GlobalTracer.java | 11 +++++ .../elastic/apm/agent/tracer/NoopTracer.java | 10 ++++ .../co/elastic/apm/agent/tracer/Tracer.java | 5 ++ .../elastic/apm/agent/tracer/Transaction.java | 4 ++ .../apm/agent/tracer/TransactionContext.java | 3 ++ .../apm/agent/tracer/metadata/Faas.java | 37 +++++++++++++++ .../apm/agent/tracer/metadata/Request.java | 2 + .../apm/agent/tracer/metadata/Response.java | 2 + .../agent/tracer/metadata/ServiceOrigin.java | 30 ++++++++++++ 27 files changed, 240 insertions(+), 136 deletions(-) create mode 100644 apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/Faas.java create mode 100644 apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/ServiceOrigin.java 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 4426dc812f..061ac6f91d 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 @@ -27,6 +27,9 @@ 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.impl.metadata.FaaSMetaDataExtension; +import co.elastic.apm.agent.impl.metadata.Framework; +import co.elastic.apm.agent.impl.metadata.NameAndIdField; import co.elastic.apm.agent.report.serialize.DslJsonDataWriter; import co.elastic.apm.agent.tracer.reporting.DataWriter; import co.elastic.apm.agent.tracer.reporting.DoubleSupplier; @@ -86,6 +89,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; /** @@ -1027,4 +1031,18 @@ public Set getTraceHeaderNames() { public ServiceInfo autoDetectedServiceInfo() { return AutoDetectedServiceInfo.autoDetected(); } + + @Override + public boolean flush(long timeout, TimeUnit timeUnit) { + return reporter.flush(timeout, timeUnit, true); + } + + @Override + public void notifyFaasMetaData(String frameworkName, String frameworkVersion, @Nullable String accountName, @Nullable String accountId, @Nullable String region) { + metaDataFuture.getFaaSMetaDataExtensionFuture().complete(new FaaSMetaDataExtension( + new Framework(frameworkName, frameworkVersion), + new NameAndIdField(accountName, accountId), + region + )); + } } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/context/ServiceOrigin.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/context/ServiceOrigin.java index 9927f7b66e..3c8e03f6bd 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/context/ServiceOrigin.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/context/ServiceOrigin.java @@ -28,7 +28,7 @@ * If a request originated from another service, * the service origin interface can be used to collect information about the origin service. */ -public class ServiceOrigin implements Recyclable { +public class ServiceOrigin implements Recyclable, co.elastic.apm.agent.tracer.metadata.ServiceOrigin { @Nullable private String id; @@ -43,6 +43,7 @@ public String getId() { return id; } + @Override public ServiceOrigin withId(@Nullable String id) { this.id = id; return this; @@ -52,6 +53,7 @@ public StringBuilder getName() { return name; } + @Override public ServiceOrigin withName(@Nullable CharSequence name) { this.name.setLength(0); if (name != null) { @@ -72,6 +74,7 @@ public String getVersion() { return version; } + @Override public ServiceOrigin withVersion(@Nullable String version) { this.version = version; return this; diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/context/TransactionContext.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/context/TransactionContext.java index c4c9ea756b..05df0e1015 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/context/TransactionContext.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/context/TransactionContext.java @@ -118,6 +118,7 @@ public CloudOrigin getCloudOrigin() { return cloudOrigin; } + @Override public ServiceOrigin getServiceOrigin() { return serviceOrigin; } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Faas.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Faas.java index 9d7e73b5f8..9c9707f988 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Faas.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Faas.java @@ -22,7 +22,7 @@ import javax.annotation.Nullable; -public class Faas implements Recyclable { +public class Faas implements Recyclable, co.elastic.apm.agent.tracer.metadata.Faas { @Nullable private String execution; @@ -68,6 +68,7 @@ public String getVersion() { return version; } + @Override public Faas withExecution(@Nullable String execution) { this.execution = execution; return this; @@ -93,6 +94,18 @@ public Faas withVersion(@Nullable String version) { return this; } + @Override + public Faas withTriggerType(@Nullable String type) { + getTrigger().withType(type); + return this; + } + + @Override + public Faas withTriggerRequestId(@Nullable String requestId) { + getTrigger().withRequestId(requestId); + return this; + } + @Override public void resetState() { this.execution = null; diff --git a/apm-agent-plugins/apm-awslambda-plugin/pom.xml b/apm-agent-plugins/apm-awslambda-plugin/pom.xml index fef395007b..5102f6ddeb 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/pom.xml +++ b/apm-agent-plugins/apm-awslambda-plugin/pom.xml @@ -17,12 +17,6 @@ - - - ${project.groupId} - apm-agent-core - ${project.version} - com.amazonaws aws-lambda-java-core diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/AbstractAwsLambdaHandlerInstrumentation.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/AbstractAwsLambdaHandlerInstrumentation.java index d447a53d40..a79ee7c37c 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/AbstractAwsLambdaHandlerInstrumentation.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/AbstractAwsLambdaHandlerInstrumentation.java @@ -18,8 +18,8 @@ */ package co.elastic.apm.agent.awslambda; -import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.sdk.ElasticApmInstrumentation; +import co.elastic.apm.agent.tracer.Tracer; import co.elastic.apm.agent.tracer.configuration.ServerlessConfiguration; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -41,7 +41,7 @@ public abstract class AbstractAwsLambdaHandlerInstrumentation extends ElasticApm @Nullable protected String handlerMethodName; - public AbstractAwsLambdaHandlerInstrumentation(ElasticApmTracer tracer) { + public AbstractAwsLambdaHandlerInstrumentation(Tracer tracer) { serverlessConfiguration = tracer.getConfig(ServerlessConfiguration.class); String awsLambdaHandler = serverlessConfiguration.getAwsLambdaHandler(); //noinspection ConstantConditions diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/RequestHandlerInstrumentation.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/RequestHandlerInstrumentation.java index 0d443b1316..a709840e7e 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/RequestHandlerInstrumentation.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/RequestHandlerInstrumentation.java @@ -20,8 +20,8 @@ import co.elastic.apm.agent.awslambda.helper.AWSEventsHelper; import co.elastic.apm.agent.awslambda.helper.PlainTransactionHelper; -import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.impl.transaction.Transaction; +import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.Transaction; import com.amazonaws.services.lambda.runtime.Context; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -35,7 +35,7 @@ public class RequestHandlerInstrumentation extends AbstractAwsLambdaHandlerInstrumentation { - public RequestHandlerInstrumentation(ElasticApmTracer tracer) { + public RequestHandlerInstrumentation(Tracer tracer) { super(tracer); } @@ -70,8 +70,8 @@ public static Object handlerEnter(@Nullable @Advice.Argument(value = 0) Object i public static void handlerExit(@Nullable @Advice.Enter Object transactionObj, @Nullable @Advice.Thrown Throwable thrown, @Nullable @Advice.Return Object output) { - if (transactionObj instanceof Transaction) { - Transaction transaction = (Transaction) transactionObj; + if (transactionObj instanceof Transaction) { + Transaction transaction = (Transaction) transactionObj; if (output != null && output.getClass().getName().startsWith("com.amazonaws.services.lambda.runtime.events")) { // handler uses aws events, it's safe to assume that the AWS events classes are available diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/RequestStreamHandlerInstrumentation.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/RequestStreamHandlerInstrumentation.java index a32e9a5246..e97fe84d19 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/RequestStreamHandlerInstrumentation.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/RequestStreamHandlerInstrumentation.java @@ -19,8 +19,8 @@ package co.elastic.apm.agent.awslambda; import co.elastic.apm.agent.awslambda.helper.PlainTransactionHelper; -import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.impl.transaction.Transaction; +import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.Transaction; import com.amazonaws.services.lambda.runtime.Context; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -35,7 +35,7 @@ public class RequestStreamHandlerInstrumentation extends AbstractAwsLambdaHandlerInstrumentation { - public RequestStreamHandlerInstrumentation(ElasticApmTracer tracer) { + public RequestStreamHandlerInstrumentation(Tracer tracer) { super(tracer); } @@ -65,8 +65,8 @@ public static Object handlerEnter(@Advice.Argument(value = 0) InputStream inputS @Advice.OnMethodExit(suppress = Throwable.class, inline = false, onThrowable = Throwable.class) public static void handlerExit(@Nullable @Advice.Enter Object transactionObj, @Nullable @Advice.Thrown Throwable thrown) { - if (transactionObj instanceof Transaction) { - Transaction transaction = (Transaction) transactionObj; + if (transactionObj instanceof Transaction) { + Transaction transaction = (Transaction) transactionObj; PlainTransactionHelper.getInstance().finalizeTransaction(transaction, null, thrown); } } diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV1TransactionHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV1TransactionHelper.java index d2d4589d9c..e6a1e3582f 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV1TransactionHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV1TransactionHelper.java @@ -19,10 +19,10 @@ package co.elastic.apm.agent.awslambda.helper; import co.elastic.apm.agent.awslambda.MapTextHeaderGetter; -import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.tracer.GlobalTracer; -import co.elastic.apm.agent.impl.transaction.Transaction; import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; +import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.Transaction; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; @@ -35,13 +35,13 @@ public class APIGatewayProxyV1TransactionHelper extends AbstractAPIGatewayTransa @Nullable private static APIGatewayProxyV1TransactionHelper INSTANCE; - private APIGatewayProxyV1TransactionHelper(ElasticApmTracer tracer) { + private APIGatewayProxyV1TransactionHelper(Tracer tracer) { super(tracer); } public static APIGatewayProxyV1TransactionHelper getInstance() { if (INSTANCE == null) { - INSTANCE = new APIGatewayProxyV1TransactionHelper(GlobalTracer.get().require(ElasticApmTracer.class)); + INSTANCE = new APIGatewayProxyV1TransactionHelper(GlobalTracer.get()); } return INSTANCE; } @@ -92,7 +92,7 @@ private String getQueryString(APIGatewayProxyRequestEvent apiGatewayEvent) { } @Override - public void captureOutputForTransaction(Transaction transaction, APIGatewayProxyResponseEvent responseEvent) { + public void captureOutputForTransaction(Transaction transaction, APIGatewayProxyResponseEvent responseEvent) { Integer statusCode = responseEvent.getStatusCode(); if (statusCode == null) { statusCode = 0; @@ -101,7 +101,7 @@ public void captureOutputForTransaction(Transaction transaction, APIGatewayProxy } @Override - protected void setTransactionTriggerData(Transaction transaction, APIGatewayProxyRequestEvent apiGatewayRequest) { + protected void setTransactionTriggerData(Transaction transaction, APIGatewayProxyRequestEvent apiGatewayRequest) { super.setTransactionTriggerData(transaction, apiGatewayRequest); APIGatewayProxyRequestEvent.ProxyRequestContext rContext = apiGatewayRequest.getRequestContext(); diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV2TransactionHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV2TransactionHelper.java index ec7ed0db69..f29c412822 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV2TransactionHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/APIGatewayProxyV2TransactionHelper.java @@ -19,10 +19,10 @@ package co.elastic.apm.agent.awslambda.helper; import co.elastic.apm.agent.awslambda.MapTextHeaderGetter; -import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.tracer.GlobalTracer; -import co.elastic.apm.agent.impl.transaction.Transaction; import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; +import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.Transaction; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPResponse; @@ -33,13 +33,13 @@ public class APIGatewayProxyV2TransactionHelper extends AbstractAPIGatewayTransa @Nullable private static APIGatewayProxyV2TransactionHelper INSTANCE; - private APIGatewayProxyV2TransactionHelper(ElasticApmTracer tracer) { + private APIGatewayProxyV2TransactionHelper(Tracer tracer) { super(tracer); } public static APIGatewayProxyV2TransactionHelper getInstance() { if (INSTANCE == null) { - INSTANCE = new APIGatewayProxyV2TransactionHelper(GlobalTracer.get().require(ElasticApmTracer.class)); + INSTANCE = new APIGatewayProxyV2TransactionHelper(GlobalTracer.get()); } return INSTANCE; } @@ -60,12 +60,12 @@ protected Transaction doStartTransaction(APIGatewayV2HTTPEvent apiGatewayEvent, } @Override - public void captureOutputForTransaction(Transaction transaction, APIGatewayV2HTTPResponse responseEvent) { + public void captureOutputForTransaction(Transaction transaction, APIGatewayV2HTTPResponse responseEvent) { fillHttpResponseData(transaction, responseEvent.getHeaders(), responseEvent.getStatusCode()); } @Override - protected void setTransactionTriggerData(Transaction transaction, APIGatewayV2HTTPEvent apiGatewayRequest) { + protected void setTransactionTriggerData(Transaction transaction, APIGatewayV2HTTPEvent apiGatewayRequest) { super.setTransactionTriggerData(transaction, apiGatewayRequest); APIGatewayV2HTTPEvent.RequestContext rContext = apiGatewayRequest.getRequestContext(); setApiGatewayContextData(transaction, rContext.getRequestId(), rContext.getApiId(), diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AWSEventsHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AWSEventsHelper.java index 9ec285ad99..b72c423c79 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AWSEventsHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AWSEventsHelper.java @@ -18,7 +18,7 @@ */ package co.elastic.apm.agent.awslambda.helper; -import co.elastic.apm.agent.impl.transaction.Transaction; +import co.elastic.apm.agent.tracer.Transaction; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; @@ -33,7 +33,7 @@ public class AWSEventsHelper { @Nullable - public static Transaction startTransaction(Object input, Context lambdaContext) { + public static Transaction startTransaction(Object input, Context lambdaContext) { if (input instanceof APIGatewayV2HTTPEvent && ((APIGatewayV2HTTPEvent) input).getRequestContext() != null && ((APIGatewayV2HTTPEvent) input).getRequestContext().getHttp() != null) { // API Gateway V2 trigger @@ -54,7 +54,7 @@ public static Transaction startTransaction(Object input, Context lambdaContext) return PlainTransactionHelper.getInstance().startTransaction(input, lambdaContext); } - public static void finalizeTransaction(Transaction transaction, Object output, @Nullable Throwable thrown) { + public static void finalizeTransaction(Transaction transaction, Object output, @Nullable Throwable thrown) { if (output instanceof APIGatewayV2HTTPResponse) { APIGatewayProxyV2TransactionHelper.getInstance().finalizeTransaction(transaction, (APIGatewayV2HTTPResponse) output, thrown); } else if (output instanceof APIGatewayProxyResponseEvent) { diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractAPIGatewayTransactionHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractAPIGatewayTransactionHelper.java index 72c1d0eecb..0aa476958b 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractAPIGatewayTransactionHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractAPIGatewayTransactionHelper.java @@ -18,13 +18,13 @@ */ package co.elastic.apm.agent.awslambda.helper; -import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.impl.context.CloudOrigin; -import co.elastic.apm.agent.impl.context.Request; -import co.elastic.apm.agent.impl.context.Response; -import co.elastic.apm.agent.impl.context.ServiceOrigin; +import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.Transaction; +import co.elastic.apm.agent.tracer.metadata.CloudOrigin; +import co.elastic.apm.agent.tracer.metadata.Request; +import co.elastic.apm.agent.tracer.metadata.Response; +import co.elastic.apm.agent.tracer.metadata.ServiceOrigin; import co.elastic.apm.agent.tracer.util.ResultUtil; -import co.elastic.apm.agent.impl.transaction.Transaction; import co.elastic.apm.agent.common.util.WildcardMatcher; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; @@ -47,13 +47,13 @@ public abstract class AbstractAPIGatewayTransactionHelper extends Abstract private static final Set METHODS_WITH_BODY = new HashSet<>(Arrays.asList("POST", "PUT", "PATCH", "DELETE")); private static final String CONTENT_TYPE_FROM_URLENCODED = "application/x-www-form-urlencoded"; - protected AbstractAPIGatewayTransactionHelper(ElasticApmTracer tracer) { + protected AbstractAPIGatewayTransactionHelper(Tracer tracer) { super(tracer); } protected abstract String getApiGatewayVersion(); - protected void fillHttpRequestData(Transaction transaction, @Nullable String httpMethod, @Nullable Map headers, @Nullable String serverName, @Nullable String path, @Nullable String queryString, @Nullable String body) { + protected void fillHttpRequestData(Transaction transaction, @Nullable String httpMethod, @Nullable Map headers, @Nullable String serverName, @Nullable String path, @Nullable String queryString, @Nullable String body) { Request request = transaction.getContext().getRequest(); request.withMethod(httpMethod); fillUrlRelatedFields(request, serverName, path, queryString); @@ -67,7 +67,7 @@ protected void fillHttpRequestData(Transaction transaction, @Nullable String htt } } - protected void fillHttpResponseData(Transaction transaction, @Nullable Map headers, int statusCode) { + protected void fillHttpResponseData(Transaction transaction, @Nullable Map headers, int statusCode) { Response response = transaction.getContext().getResponse(); response.withFinished(true); if (transaction.isSampled() && null != headers && isCaptureHeaders()) { @@ -82,17 +82,11 @@ protected void fillHttpResponseData(Transaction transaction, @Nullable Map transaction, @Nullable String method, @Nullable String contentTypeHeader) { Request request = transaction.getContext().getRequest(); if (hasBody(contentTypeHeader, method)) { if (coreConfiguration.getCaptureBody() != OFF @@ -127,18 +121,18 @@ private boolean hasBody(@Nullable String contentTypeHeader, @Nullable String met } @Override - protected void setTransactionTriggerData(Transaction transaction, I apiGatewayRequest) { + protected void setTransactionTriggerData(Transaction transaction, I apiGatewayRequest) { transaction.withType(TRANSACTION_TYPE); CloudOrigin cloudOrigin = transaction.getContext().getCloudOrigin(); cloudOrigin.withServiceName("api gateway"); cloudOrigin.withProvider("aws"); - transaction.getFaas().getTrigger().withType("http"); + transaction.getFaas().withTriggerType("http"); transaction.getContext().getServiceOrigin().withVersion(getApiGatewayVersion()); } - protected void setApiGatewayContextData(Transaction transaction, @Nullable String requestId, @Nullable String apiId, + protected void setApiGatewayContextData(Transaction transaction, @Nullable String requestId, @Nullable String apiId, @Nullable String domainName, @Nullable String accountId) { - transaction.getFaas().getTrigger().withRequestId(requestId); + transaction.getFaas().withTriggerRequestId(requestId); ServiceOrigin serviceOrigin = transaction.getContext().getServiceOrigin(); serviceOrigin.withName(domainName); serviceOrigin.withId(apiId); @@ -146,7 +140,7 @@ protected void setApiGatewayContextData(Transaction transaction, @Nullable Strin transaction.getContext().getCloudOrigin().withAccountId(accountId); } - private void setRequestHeaders(Transaction transaction, Map headers) { + private void setRequestHeaders(Transaction transaction, Map headers) { final Request req = transaction.getContext().getRequest(); if (transaction.isSampled() && isCaptureHeaders()) { for (Map.Entry headerEntry : headers.entrySet()) { @@ -156,7 +150,7 @@ private void setRequestHeaders(Transaction transaction, Map head } @Override - protected void setTransactionName(Transaction transaction, I event, Context lambdaContext) { + protected void setTransactionName(Transaction transaction, I event, Context lambdaContext) { StringBuilder transactionName = transaction.getAndOverrideName(AbstractSpan.PRIORITY_HIGH_LEVEL_FRAMEWORK); if (transactionName != null) { String httpMethod = getHttpMethod(event); diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractLambdaTransactionHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractLambdaTransactionHelper.java index 8c61317ce1..d3a063607b 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractLambdaTransactionHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractLambdaTransactionHelper.java @@ -18,20 +18,14 @@ */ package co.elastic.apm.agent.awslambda.helper; -import co.elastic.apm.agent.bci.ElasticApmAgent; -import co.elastic.apm.agent.bci.InstrumentationStats; -import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.Transaction; import co.elastic.apm.agent.tracer.configuration.CoreConfiguration; import co.elastic.apm.agent.tracer.configuration.ServerlessConfiguration; import co.elastic.apm.agent.tracer.configuration.WebConfiguration; -import co.elastic.apm.agent.impl.metadata.FaaSMetaDataExtension; -import co.elastic.apm.agent.impl.metadata.Framework; -import co.elastic.apm.agent.impl.metadata.NameAndIdField; -import co.elastic.apm.agent.impl.transaction.Transaction; 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.sdk.internal.util.LoggerUtils; import co.elastic.apm.agent.sdk.internal.util.VersionUtils; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; @@ -41,27 +35,26 @@ public abstract class AbstractLambdaTransactionHelper { private static final Logger logger = LoggerFactory.getLogger(AbstractLambdaTransactionHelper.class); - private static final Logger enabledInstrumentationsLogger = LoggerUtils.logOnce(logger); - protected final ElasticApmTracer tracer; + protected final Tracer tracer; protected final ServerlessConfiguration serverlessConfiguration; protected final CoreConfiguration coreConfiguration; protected final WebConfiguration webConfiguration; - protected AbstractLambdaTransactionHelper(ElasticApmTracer tracer) { + protected AbstractLambdaTransactionHelper(Tracer tracer) { this.tracer = tracer; this.coreConfiguration = tracer.getConfig(CoreConfiguration.class); this.webConfiguration = tracer.getConfig(WebConfiguration.class); this.serverlessConfiguration = tracer.getConfig(ServerlessConfiguration.class); } - protected abstract void setTransactionTriggerData(Transaction transaction, I input); + protected abstract void setTransactionTriggerData(Transaction transaction, I input); @Nullable - protected abstract Transaction doStartTransaction(I input, Context lambdaContext); + protected abstract Transaction doStartTransaction(I input, Context lambdaContext); - protected abstract void captureOutputForTransaction(Transaction transaction, O output); + protected abstract void captureOutputForTransaction(Transaction transaction, O output); private static boolean coldStart = true; @@ -69,13 +62,13 @@ protected AbstractLambdaTransactionHelper(ElasticApmTracer tracer) { private String functionArn; @Nullable - public Transaction startTransaction(I input, Context lambdaContext) { + public Transaction startTransaction(I input, Context lambdaContext) { boolean isColdStart = coldStart; if (isColdStart) { completeMetaData(lambdaContext); coldStart = false; } - Transaction transaction = doStartTransaction(input, lambdaContext); + Transaction transaction = doStartTransaction(input, lambdaContext); if (null != transaction) { transaction.getFaas() .withId(getFaasId(lambdaContext)) @@ -104,7 +97,7 @@ private String getFaasId(Context lambdaContext) { return functionArn; } - public void finalizeTransaction(Transaction transaction, @Nullable O output, @Nullable Throwable thrown) { + public void finalizeTransaction(Transaction transaction, @Nullable O output, @Nullable Throwable thrown) { try { if (null != output) { captureOutputForTransaction(transaction, output); @@ -120,21 +113,12 @@ public void finalizeTransaction(Transaction transaction, @Nullable O output, @Nu } long flushTimeout = serverlessConfiguration.getDataFlushTimeout(); try { - if (!tracer.getReporter().flush(flushTimeout, TimeUnit.MILLISECONDS, true)) { + if (!tracer.flush(flushTimeout, TimeUnit.MILLISECONDS)) { logger.error("APM data flush haven't completed within {} milliseconds.", flushTimeout); } } catch (Exception e) { logger.error("An error occurred on flushing APM data.", e); } - - logEnabledInstrumentations(); - } - - private void logEnabledInstrumentations() { - if (enabledInstrumentationsLogger.isInfoEnabled()) { - InstrumentationStats instrumentationStats = ElasticApmAgent.getInstrumentationStats(); - enabledInstrumentationsLogger.info("Used instrumentation groups: {}", instrumentationStats.getUsedInstrumentationGroups()); - } } private void completeMetaData(Context lambdaContext) { @@ -149,17 +133,13 @@ private void completeMetaData(Context lambdaContext) { lambdaLibVersion = "unknown"; } - tracer.getMetaDataFuture().getFaaSMetaDataExtensionFuture().complete(new FaaSMetaDataExtension( - new Framework("AWS Lambda", lambdaLibVersion), - new NameAndIdField(null, accountId), - region - )); + tracer.notifyFaasMetaData("AWS Lambda", lambdaLibVersion, null, accountId, region); } catch (Exception e) { logger.error("Failed updating metadata for first lambda execution!", e); } } - protected void setTransactionName(Transaction transaction, I event, Context lambdaContext) { + protected void setTransactionName(Transaction transaction, I event, Context lambdaContext) { StringBuilder transactionName = transaction.getAndOverrideName(AbstractSpan.PRIORITY_HIGH_LEVEL_FRAMEWORK); if (transactionName != null) { transactionName.append(lambdaContext.getFunctionName()); diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractMessageBasedTransactionHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractMessageBasedTransactionHelper.java index 328d88febf..7082933fba 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractMessageBasedTransactionHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/AbstractMessageBasedTransactionHelper.java @@ -18,12 +18,12 @@ */ package co.elastic.apm.agent.awslambda.helper; -import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.impl.context.CloudOrigin; -import co.elastic.apm.agent.impl.context.ServiceOrigin; -import co.elastic.apm.agent.impl.transaction.Transaction; import co.elastic.apm.agent.tracer.AbstractSpan; import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; +import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.Transaction; +import co.elastic.apm.agent.tracer.metadata.CloudOrigin; +import co.elastic.apm.agent.tracer.metadata.ServiceOrigin; import com.amazonaws.services.lambda.runtime.Context; import javax.annotation.Nullable; @@ -31,7 +31,7 @@ public abstract class AbstractMessageBasedTransactionHelper extends AbstractLambdaTransactionHelper { protected static final String TRANSACTION_TYPE = "messaging"; - protected AbstractMessageBasedTransactionHelper(ElasticApmTracer tracer) { + protected AbstractMessageBasedTransactionHelper(Tracer tracer) { super(tracer); } @@ -50,27 +50,27 @@ protected AbstractMessageBasedTransactionHelper(ElasticApmTracer tracer) { @Nullable @Override - protected Transaction doStartTransaction(I event, Context lambdaContext) { - Transaction transaction = tracer.startRootTransaction(PrivilegedActionUtils.getClassLoader(lambdaContext.getClass())); + protected Transaction doStartTransaction(I event, Context lambdaContext) { + Transaction transaction = tracer.startRootTransaction(PrivilegedActionUtils.getClassLoader(lambdaContext.getClass())); if (null != transaction) { addSpanLinks(transaction, event); } return transaction; } - protected abstract void addSpanLinks(Transaction transaction, I event); + protected abstract void addSpanLinks(Transaction transaction, I event); @Override - public void captureOutputForTransaction(Transaction transaction, O output) { + public void captureOutputForTransaction(Transaction transaction, O output) { // Nothing to do here } @Override - protected void setTransactionTriggerData(Transaction transaction, I event) { + protected void setTransactionTriggerData(Transaction transaction, I event) { R record = getFirstRecord(event); transaction.withType(TRANSACTION_TYPE); - transaction.getFaas().getTrigger().withType("pubsub"); + transaction.getFaas().withTriggerType("pubsub"); ServiceOrigin serviceOrigin = transaction.getContext().getServiceOrigin(); CloudOrigin cloudOrigin = transaction.getContext().getCloudOrigin(); @@ -107,7 +107,7 @@ protected void setTransactionTriggerData(Transaction transaction, I event) { } } - private void updateTransactionName(Transaction transaction, @Nullable String queueName) { + private void updateTransactionName(Transaction transaction, @Nullable String queueName) { StringBuilder transactionName = transaction.getAndOverrideName(AbstractSpan.PRIORITY_HIGH_LEVEL_FRAMEWORK); if (null != transactionName && null != queueName && !queueName.isEmpty()) { transactionName.append("RECEIVE ").append(queueName); diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/PlainTransactionHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/PlainTransactionHelper.java index d86880d0f4..af9f3cc3d6 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/PlainTransactionHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/PlainTransactionHelper.java @@ -18,10 +18,10 @@ */ package co.elastic.apm.agent.awslambda.helper; -import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.tracer.GlobalTracer; -import co.elastic.apm.agent.impl.transaction.Transaction; import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; +import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.Transaction; import com.amazonaws.services.lambda.runtime.Context; import javax.annotation.Nullable; @@ -33,30 +33,30 @@ public class PlainTransactionHelper extends AbstractLambdaTransactionHelper doStartTransaction(Object input, Context lambdaContext) { return tracer.startRootTransaction(PrivilegedActionUtils.getClassLoader(lambdaContext.getClass())); } @Override - public void captureOutputForTransaction(Transaction transaction, Object output) { + public void captureOutputForTransaction(Transaction transaction, Object output) { // Nothing to do here } @Override - protected void setTransactionTriggerData(Transaction transaction, Object input) { - transaction.getFaas().getTrigger().withType("other"); + protected void setTransactionTriggerData(Transaction transaction, Object input) { + transaction.getFaas().withTriggerType("other"); transaction.withType(TRANSACTION_TYPE); } } diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/S3TransactionHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/S3TransactionHelper.java index fbfda924cd..a41ccb456d 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/S3TransactionHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/S3TransactionHelper.java @@ -18,14 +18,12 @@ */ package co.elastic.apm.agent.awslambda.helper; -import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.tracer.AbstractSpan; import co.elastic.apm.agent.tracer.GlobalTracer; -import co.elastic.apm.agent.impl.context.CloudOrigin; -import co.elastic.apm.agent.impl.context.ServiceOrigin; -import co.elastic.apm.agent.impl.transaction.FaasTrigger; -import co.elastic.apm.agent.impl.transaction.Transaction; import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; +import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.Transaction; +import co.elastic.apm.agent.tracer.metadata.CloudOrigin; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.S3Event; import com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification; @@ -38,13 +36,13 @@ public class S3TransactionHelper extends AbstractLambdaTransactionHelper transaction, S3Event s3Event, Context lambdaContext) { S3EventNotification.S3EventNotificationRecord s3NotificationRecord = getS3NotificationRecord(s3Event); StringBuilder transactionName = transaction.getAndOverrideName(AbstractSpan.PRIORITY_HIGH_LEVEL_FRAMEWORK); if (transactionName != null && null != s3NotificationRecord && null != s3NotificationRecord.getS3() && null != s3NotificationRecord.getS3().getBucket()) { diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/SNSTransactionHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/SNSTransactionHelper.java index ed635f00e4..9e3425837b 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/SNSTransactionHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/SNSTransactionHelper.java @@ -19,9 +19,9 @@ package co.elastic.apm.agent.awslambda.helper; import co.elastic.apm.agent.awslambda.SNSMessageAttributesGetter; -import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.tracer.GlobalTracer; -import co.elastic.apm.agent.impl.transaction.Transaction; +import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.Transaction; import com.amazonaws.services.lambda.runtime.events.SNSEvent; import javax.annotation.Nullable; @@ -33,13 +33,13 @@ public class SNSTransactionHelper extends AbstractMessageBasedTransactionHelper< private final SNSEvent.SNSRecord placeholderRecord = new SNSEvent.SNSRecord(); - private SNSTransactionHelper(ElasticApmTracer tracer) { + private SNSTransactionHelper(Tracer tracer) { super(tracer); } public static SNSTransactionHelper getInstance() { if (INSTANCE == null) { - INSTANCE = new SNSTransactionHelper(GlobalTracer.get().require(ElasticApmTracer.class)); + INSTANCE = new SNSTransactionHelper(GlobalTracer.get()); } return INSTANCE; } @@ -78,7 +78,7 @@ record = event.getRecords().get(0); } @Override - protected void addSpanLinks(Transaction transaction, SNSEvent event) { + protected void addSpanLinks(Transaction transaction, SNSEvent event) { List records = event.getRecords(); if (records != null && !records.isEmpty()) { for (SNSEvent.SNSRecord record : records) { diff --git a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/SQSTransactionHelper.java b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/SQSTransactionHelper.java index 218506a463..6f6ba9e807 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/SQSTransactionHelper.java +++ b/apm-agent-plugins/apm-awslambda-plugin/src/main/java/co/elastic/apm/agent/awslambda/helper/SQSTransactionHelper.java @@ -19,9 +19,9 @@ package co.elastic.apm.agent.awslambda.helper; import co.elastic.apm.agent.awslambda.SQSMessageAttributesGetter; -import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.tracer.GlobalTracer; -import co.elastic.apm.agent.impl.transaction.Transaction; +import co.elastic.apm.agent.tracer.Tracer; +import co.elastic.apm.agent.tracer.Transaction; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import javax.annotation.Nullable; @@ -34,13 +34,13 @@ public class SQSTransactionHelper extends AbstractMessageBasedTransactionHelper< private final SQSEvent.SQSMessage placeholderMessage = new SQSEvent.SQSMessage(); - private SQSTransactionHelper(ElasticApmTracer tracer) { + private SQSTransactionHelper(Tracer tracer) { super(tracer); } public static SQSTransactionHelper getInstance() { if (INSTANCE == null) { - INSTANCE = new SQSTransactionHelper(GlobalTracer.get().require(ElasticApmTracer.class)); + INSTANCE = new SQSTransactionHelper(GlobalTracer.get()); } return INSTANCE; } @@ -76,7 +76,7 @@ record = event.getRecords().get(0); } @Override - protected void addSpanLinks(Transaction transaction, SQSEvent event) { + protected void addSpanLinks(Transaction transaction, SQSEvent event) { List records = event.getRecords(); if (records != null && !records.isEmpty()) { for (SQSEvent.SQSMessage record : records) { diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/GlobalTracer.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/GlobalTracer.java index 031f927381..8240997455 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/GlobalTracer.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/GlobalTracer.java @@ -25,6 +25,7 @@ import javax.annotation.Nullable; import java.util.Set; +import java.util.concurrent.TimeUnit; public class GlobalTracer implements Tracer { @@ -133,4 +134,14 @@ public Transaction startChildTransaction(@Nullable C headerCarrier, He public ErrorCapture captureException(@Nullable Throwable e, @Nullable ClassLoader initiatingClassLoader) { return tracer.captureException(e, initiatingClassLoader); } + + @Override + public boolean flush(long timeout, TimeUnit timeUnit) { + return tracer.flush(timeout, timeUnit); + } + + @Override + public void notifyFaasMetaData(String frameworkName, String frameworkVersion, @Nullable String accountName, @Nullable String accountId, @Nullable String region) { + tracer.notifyFaasMetaData(frameworkName, frameworkVersion, accountName, accountId, region); + } } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/NoopTracer.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/NoopTracer.java index 6088e75683..43d7ef0c64 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/NoopTracer.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/NoopTracer.java @@ -26,6 +26,7 @@ import javax.annotation.Nullable; import java.util.Collections; import java.util.Set; +import java.util.concurrent.TimeUnit; class NoopTracer implements Tracer { @@ -110,4 +111,13 @@ public Transaction startChildTransaction(@Nullable C headerCarrier, He public ErrorCapture captureException(@Nullable Throwable e, @Nullable ClassLoader initiatingClassLoader) { return null; } + + @Override + public boolean flush(long timeout, TimeUnit timeUnit) { + return true; + } + + @Override + public void notifyFaasMetaData(String frameworkName, String frameworkVersion, @Nullable String accountName, @Nullable String accountId, @Nullable String region) { + } } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Tracer.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Tracer.java index 97f8e8bb87..8836918ff4 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Tracer.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Tracer.java @@ -25,6 +25,7 @@ import javax.annotation.Nullable; import java.util.Set; +import java.util.concurrent.TimeUnit; public interface Tracer { @@ -80,4 +81,8 @@ public interface Tracer { @Nullable ErrorCapture captureException(@Nullable Throwable e, @Nullable ClassLoader initiatingClassLoader); + + boolean flush(long timeout, TimeUnit timeUnit); + + void notifyFaasMetaData(String frameworkName, String frameworkVersion, @Nullable String accountName, @Nullable String accountId, @Nullable String region); } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Transaction.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Transaction.java index 1424da3766..0a2435914f 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Transaction.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Transaction.java @@ -18,6 +18,8 @@ */ package co.elastic.apm.agent.tracer; +import co.elastic.apm.agent.tracer.metadata.Faas; + import javax.annotation.Nullable; public interface Transaction> extends AbstractSpan { @@ -32,6 +34,8 @@ public interface Transaction> extends AbstractSpan { @Override TransactionContext getContext(); + Faas getFaas(); + boolean isNoop(); /** diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/TransactionContext.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/TransactionContext.java index baafaacb96..a38f284a20 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/TransactionContext.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/TransactionContext.java @@ -21,6 +21,7 @@ import co.elastic.apm.agent.tracer.metadata.CloudOrigin; import co.elastic.apm.agent.tracer.metadata.Request; import co.elastic.apm.agent.tracer.metadata.Response; +import co.elastic.apm.agent.tracer.metadata.ServiceOrigin; import co.elastic.apm.agent.tracer.metadata.User; public interface TransactionContext extends AbstractContext { @@ -43,4 +44,6 @@ public interface TransactionContext extends AbstractContext { User getUser(); CloudOrigin getCloudOrigin(); + + ServiceOrigin getServiceOrigin(); } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/Faas.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/Faas.java new file mode 100644 index 0000000000..0e602b8820 --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/Faas.java @@ -0,0 +1,37 @@ +/* + * 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.metadata; + +import javax.annotation.Nullable; + +public interface Faas { + Faas withTriggerType(@Nullable String type); + + Faas withTriggerRequestId(@Nullable String requestId); + + Faas withId(@Nullable String id); + + Faas withName(@Nullable String name); + + Faas withVersion(@Nullable String version); + + Faas withColdStart(boolean coldStart); + + Faas withExecution(@Nullable String execution); +} diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/Request.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/Request.java index fe8afd2f5f..d510be164c 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/Request.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/Request.java @@ -75,6 +75,8 @@ public interface Request { Request addFormUrlEncodedParameters(String key, String[] values); + Request addHeader(String headerName, String headerValue); + Request addHeader(String headerName, @Nullable Enumeration headerValues); Request addCookie(String cookieName, String cookieValue); diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/Response.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/Response.java index e87a517a8a..58b2b728b6 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/Response.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/Response.java @@ -40,5 +40,7 @@ public interface Response { Response withHeadersSent(boolean headersSent); + Response addHeader(String headerName, String headerValue); + Response addHeader(String headerName, @Nullable Collection headerValues); } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/ServiceOrigin.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/ServiceOrigin.java new file mode 100644 index 0000000000..00ce0e4f8c --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/metadata/ServiceOrigin.java @@ -0,0 +1,30 @@ +/* + * 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.metadata; + +import javax.annotation.Nullable; + +public interface ServiceOrigin { + + ServiceOrigin withId(@Nullable String apiId); + + ServiceOrigin withName(@Nullable CharSequence name); + + ServiceOrigin withVersion(@Nullable String version); +} From 1ff99bee47dbad435f8191e1d808c9a6d11775fb Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Mon, 9 Oct 2023 21:12:02 +0200 Subject: [PATCH 18/21] Update apm-agent-core/src/main/java/co/elastic/apm/agent/context/InitializableLifecycleListener.java Co-authored-by: SylvainJuge <763082+SylvainJuge@users.noreply.github.com> --- .../apm/agent/context/InitializableLifecycleListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 47c3f6e33d..c360b4d410 100644 --- 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 @@ -25,7 +25,7 @@ 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. + * be called in a delay, this callback is called at the bootstrap of the JVM, before anything else starts. * 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. */ From ca6ee7fb967db9a363a674c1c420e0186e77b087 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Mon, 9 Oct 2023 21:13:04 +0200 Subject: [PATCH 19/21] Update apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/LifecycleListener.java Co-authored-by: SylvainJuge <763082+SylvainJuge@users.noreply.github.com> --- .../java/co/elastic/apm/agent/tracer/LifecycleListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/LifecycleListener.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/LifecycleListener.java index fe905248d1..3c13cae318 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/LifecycleListener.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/LifecycleListener.java @@ -43,7 +43,7 @@ public interface LifecycleListener { void start() throws Exception; /** - * Callback for when {@link co.elastic.apm.agent.tracer.Tracer} has been paused. + * Callback for when {@link 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. From 99255085c12b7ecb268e9a95819bc1c21b65ff0c Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Mon, 9 Oct 2023 21:29:55 +0200 Subject: [PATCH 20/21] Rename init lifecycle listener. --- .../agent/bci/InstrumentationStatsLifecycleListener.java | 4 ++-- .../agent/configuration/ApmServerConfigurationSource.java | 4 ++-- .../co/elastic/apm/agent/configuration/StartupInfo.java | 4 ++-- ...leLifecycleListener.java => InitLifecycleListener.java} | 2 +- .../java/co/elastic/apm/agent/impl/ElasticApmTracer.java | 6 +++--- .../co/elastic/apm/agent/logging/ApmServerLogAppender.java | 7 +++---- .../test/java/co/elastic/apm/agent/impl/LifecycleTest.java | 4 ++-- 7 files changed, 15 insertions(+), 16 deletions(-) rename apm-agent-core/src/main/java/co/elastic/apm/agent/context/{InitializableLifecycleListener.java => InitLifecycleListener.java} (94%) 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 1429e79ae1..2e5e022870 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,7 +19,7 @@ package co.elastic.apm.agent.bci; import co.elastic.apm.agent.bci.bytebuddy.MatcherTimer; -import co.elastic.apm.agent.context.InitializableLifecycleListener; +import co.elastic.apm.agent.context.InitLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.sdk.logging.Logger; @@ -28,7 +28,7 @@ import java.util.ArrayList; import java.util.Collections; -public class InstrumentationStatsLifecycleListener extends AbstractLifecycleListener implements InitializableLifecycleListener { +public class InstrumentationStatsLifecycleListener extends AbstractLifecycleListener implements InitLifecycleListener { private static final Logger logger = LoggerFactory.getLogger(InstrumentationStatsLifecycleListener.class); @Override 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 604bb59f52..7afda0b25b 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.InitializableLifecycleListener; +import co.elastic.apm.agent.context.InitLifecycleListener; 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 InitializableLifecycleListener { +public class ApmServerConfigurationSource extends AbstractConfigurationSource implements InitLifecycleListener { // 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"); 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 9033a82c35..27882d7610 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,7 +18,7 @@ */ package co.elastic.apm.agent.configuration; -import co.elastic.apm.agent.context.InitializableLifecycleListener; +import co.elastic.apm.agent.context.InitLifecycleListener; import co.elastic.apm.agent.tracer.configuration.TimeDuration; import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; @@ -39,7 +39,7 @@ * under Apache license 2.0. *

    */ -public class StartupInfo extends AbstractLifecycleListener implements InitializableLifecycleListener { +public class StartupInfo extends AbstractLifecycleListener implements InitLifecycleListener { 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/InitializableLifecycleListener.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/context/InitLifecycleListener.java similarity index 94% rename from apm-agent-core/src/main/java/co/elastic/apm/agent/context/InitializableLifecycleListener.java rename to apm-agent-core/src/main/java/co/elastic/apm/agent/context/InitLifecycleListener.java index 47c3f6e33d..97403f0547 100644 --- 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/InitLifecycleListener.java @@ -21,7 +21,7 @@ import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.tracer.LifecycleListener; -public interface InitializableLifecycleListener extends LifecycleListener { +public interface InitLifecycleListener extends LifecycleListener { /** * Callback for tracer initialization. As opposed to {@link LifecycleListener#start()}, which may 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 061ac6f91d..e68dbf6664 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,7 +26,7 @@ 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.context.InitLifecycleListener; import co.elastic.apm.agent.impl.metadata.FaaSMetaDataExtension; import co.elastic.apm.agent.impl.metadata.Framework; import co.elastic.apm.agent.impl.metadata.NameAndIdField; @@ -694,9 +694,9 @@ public List getActivationListeners() { void init(List lifecycleListeners) { this.lifecycleListeners.addAll(lifecycleListeners); for (LifecycleListener lifecycleListener : lifecycleListeners) { - if (lifecycleListener instanceof InitializableLifecycleListener) { + if (lifecycleListener instanceof InitLifecycleListener) { try { - ((InitializableLifecycleListener) lifecycleListener).init(this); + ((InitLifecycleListener) lifecycleListener).init(this); } catch (Exception e) { logger.error("Failed to init " + lifecycleListener.getClass().getName(), e); } 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 a7d35ac1fb..5cf4fa486c 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,9 +18,8 @@ */ package co.elastic.apm.agent.logging; -import co.elastic.apm.agent.context.InitializableLifecycleListener; +import co.elastic.apm.agent.context.InitLifecycleListener; 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; @@ -101,8 +100,8 @@ public void append(LogEvent event) { sendLogEvent(event); } - public InitializableLifecycleListener getInitListener() { - class InitListener extends AbstractLifecycleListener implements InitializableLifecycleListener { + public InitLifecycleListener getInitListener() { + class InitListener extends AbstractLifecycleListener implements InitLifecycleListener { @Override public void init(ElasticApmTracer tracer) { initStreaming(tracer.getConfig(LoggingConfiguration.class), tracer.getReporter()); 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 2281ae3cab..e2f4ec032f 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,7 @@ 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.InitializableLifecycleListener; +import co.elastic.apm.agent.context.InitLifecycleListener; import co.elastic.apm.agent.tracer.AbstractLifecycleListener; import co.elastic.apm.agent.objectpool.TestObjectPoolFactory; import net.bytebuddy.agent.ByteBuddyAgent; @@ -141,7 +141,7 @@ void testStartDisabled() throws Exception { ConfigurationRegistry configRegistry = SpyConfiguration.createSpyConfig(SimpleSource.forTest("enabled", "false")); final AtomicBoolean initialized = new AtomicBoolean(); final AtomicBoolean started = new AtomicBoolean(); - class TestListener extends AbstractLifecycleListener implements InitializableLifecycleListener { + class TestListener extends AbstractLifecycleListener implements InitLifecycleListener { @Override public void init(ElasticApmTracer tracer) { initialized.set(true); From f06060f811b733b6d33cd135b2f7b20eb41e69e6 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Mon, 9 Oct 2023 22:17:02 +0200 Subject: [PATCH 21/21] Add test for header caching. --- .../apm/agent/impl/transaction/TraceContext.java | 10 +++++++++- .../apm/agent/impl/transaction/TraceContextTest.java | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) 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 1d8b2f6388..019ae2e94a 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 @@ -350,12 +350,20 @@ public void asRootSpan(Sampler sampler) { cachedSampleRate = rate; cachedHeader = TraceState.getHeaderValue(rate); } - traceState.set(rate, cachedHeader); + traceState.set(rate, getHeader(rate)); } clock.init(); onMutation(); } + String getHeader(double rate) { + if (cachedHeader == null || cachedSampleRate != rate) { + cachedSampleRate = rate; + cachedHeader = TraceState.getHeaderValue(rate); + } + return cachedHeader; + } + public void asChildOf(TraceContext parent) { traceId.copyFrom(parent.traceId); parentId.copyFrom(parent.id); 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 2042067555..f1d4f55023 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 @@ -646,4 +646,12 @@ void testSetServiceInfoWithNonEmptyServiceName() { assertThat(traceContext.getServiceName()).isEqualTo("My Service"); assertThat(traceContext.getServiceVersion()).isEqualTo("My Version"); } + + @Test + void testCachedTraceHeader() { + TraceContext traceContext = TraceContext.with64BitId(tracer); + String header = traceContext.getHeader(0.5); + assertThat(header).isNotNull().isSameAs(traceContext.getHeader(0.5)); + assertThat(header).isNotEqualTo(traceContext.getHeader(1)); + } }