diff --git a/CHANGES.md b/CHANGES.md index aa57174d65..8affde9592 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,9 @@ Release Notes. * Add the virtual thread executor plugin * Fix Conflicts apm-jdk-threadpool-plugin conflicts with apm-jdk-forkjoinpool-plugin * Fix NPE in hikaricp-plugin if JDBC URL is not set +* Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent transfer + initialization. Delay so11y metrics#build when the services are not ready to avoid MeterService status is not + initialized. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java index ab3042646d..015596ad26 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import java.util.ServiceLoader; +import lombok.Getter; import org.apache.skywalking.apm.agent.core.logging.api.ILog; import org.apache.skywalking.apm.agent.core.logging.api.LogManager; import org.apache.skywalking.apm.agent.core.plugin.loader.AgentClassLoader; @@ -37,6 +38,8 @@ public enum ServiceManager { private static final ILog LOGGER = LogManager.getLogger(ServiceManager.class); private Map bootedServices = Collections.emptyMap(); + @Getter + private volatile boolean isBooted = false; public void boot() { bootedServices = loadAllServices(); @@ -127,6 +130,7 @@ private void onComplete() { LOGGER.error(e, "Service [{}] AfterBoot process fails.", service.getClass().getName()); } } + isBooted = true; } /** diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/AgentSo11y.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/AgentSo11y.java index b1468f293a..c8da7ee262 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/AgentSo11y.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/AgentSo11y.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; import org.apache.skywalking.apm.agent.core.meter.Counter; import org.apache.skywalking.apm.agent.core.meter.Histogram; import org.apache.skywalking.apm.agent.core.meter.MeterFactory; @@ -58,6 +59,12 @@ public class AgentSo11y { private static Histogram INTERCEPTOR_TIME_COST; public static void measureTracingContextCreation(boolean forceSampling, boolean ignoredTracingContext) { + if (!ServiceManager.INSTANCE.isBooted()) { + // Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent + // transfer initialization. + // Skip when the services are not ready to avoid MeterService status is not initialized. + return; + } if (forceSampling) { if (ignoredTracingContext) { if (PROPAGATED_IGNORE_CONTEXT_COUNTER == null) { @@ -98,6 +105,12 @@ public static void measureTracingContextCreation(boolean forceSampling, boolean } public static void measureTracingContextCompletion(boolean ignoredTracingContext) { + if (!ServiceManager.INSTANCE.isBooted()) { + // Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent + // transfer initialization. + // Skip when the services are not ready to avoid MeterService status is not initialized. + return; + } if (ignoredTracingContext) { if (FINISH_IGNORE_CONTEXT_COUNTER == null) { FINISH_IGNORE_CONTEXT_COUNTER = MeterFactory.counter("finished_ignored_context_counter").build(); @@ -112,6 +125,12 @@ public static void measureTracingContextCompletion(boolean ignoredTracingContext } public static void measureLeakedTracingContext(boolean ignoredTracingContext) { + if (!ServiceManager.INSTANCE.isBooted()) { + // Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent + // transfer initialization. + // Skip when the services are not ready to avoid MeterService status is not initialized. + return; + } if (ignoredTracingContext) { if (LEAKED_IGNORE_CONTEXT_COUNTER == null) { LEAKED_IGNORE_CONTEXT_COUNTER = MeterFactory @@ -132,6 +151,12 @@ public static void measureLeakedTracingContext(boolean ignoredTracingContext) { } public static void durationOfInterceptor(double timeCostInNanos) { + if (!ServiceManager.INSTANCE.isBooted()) { + // Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent + // transfer initialization. + // Skip when the services are not ready to avoid MeterService status is not initialized. + return; + } if (INTERCEPTOR_TIME_COST == null) { INTERCEPTOR_TIME_COST = MeterFactory .histogram("tracing_context_performance") @@ -142,6 +167,12 @@ public static void durationOfInterceptor(double timeCostInNanos) { } public static void errorOfPlugin(String pluginName, String interType) { + if (!ServiceManager.INSTANCE.isBooted()) { + // Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent + // transfer initialization. + // Skip when the services are not ready to avoid MeterService status is not initialized. + return; + } Counter counter = ERROR_COUNTER_CACHE.computeIfAbsent(pluginName + interType, key -> MeterFactory .counter("interceptor_error_counter") .tag("plugin_name", pluginName)