getObservabilityBackends() {
}
@Inject
- public void setOpenTelemetrySdkProvider(OpenTelemetrySdkProvider openTelemetrySdkProvider) {
- this.openTelemetrySdkProvider = openTelemetrySdkProvider;
+ public void setJenkinsControllerOpenTelemetry(JenkinsControllerOpenTelemetry jenkinsControllerOpenTelemetry) {
+ this.jenkinsControllerOpenTelemetry = jenkinsControllerOpenTelemetry;
}
public Integer getExporterTimeoutMillis() {
@@ -506,7 +519,7 @@ public void setServiceName(String serviceName) {
}
/**
- * @see ServiceIncubatingAttributes#SERVICE_NAMESPACE
+ * @see io.opentelemetry.semconv.incubating.ServiceIncubatingAttributes#SERVICE_NAMESPACE
*/
public String getServiceNamespace() {
return (Strings.isNullOrEmpty(this.serviceNamespace)) ? JenkinsOtelSemanticAttributes.JENKINS : this.serviceNamespace;
@@ -520,10 +533,10 @@ public void setServiceNamespace(String serviceNamespace) {
@NonNull
public Resource getResource() {
- if (this.openTelemetrySdkProvider == null) {
+ if (this.jenkinsControllerOpenTelemetry == null) {
return Resource.empty();
} else {
- return this.openTelemetrySdkProvider.getResource();
+ return this.jenkinsControllerOpenTelemetry.getResource();
}
}
@@ -540,10 +553,10 @@ public String getResourceAsText() {
@NonNull
public ConfigProperties getConfigProperties() {
- if (this.openTelemetrySdkProvider == null) {
+ if (this.jenkinsControllerOpenTelemetry == null) {
return ConfigPropertiesUtils.emptyConfig();
} else {
- return this.openTelemetrySdkProvider.getConfig();
+ return this.jenkinsControllerOpenTelemetry.getConfig();
}
}
@@ -568,11 +581,12 @@ public LogStorageRetriever getLogStorageRetriever() {
@NonNull
@MustBeClosed
- @SuppressWarnings("MustBeClosedChecker") // false positive invoking backend.getLogStorageRetriever(templateBindingsProvider)
+ @SuppressWarnings("MustBeClosedChecker")
+ // false positive invoking backend.getLogStorageRetriever(templateBindingsProvider)
private LogStorageRetriever resolveLogStorageRetriever() {
LogStorageRetriever logStorageRetriever = null;
- Resource otelSdkResource = openTelemetrySdkProvider.getResource();
+ Resource otelSdkResource = jenkinsControllerOpenTelemetry.getResource();
String serviceName = Objects.requireNonNull(otelSdkResource.getAttribute(ServiceAttributes.SERVICE_NAME), "service.name can't be null");
String serviceNamespace = otelSdkResource.getAttribute(ServiceIncubatingAttributes.SERVICE_NAMESPACE);
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/OtelComponent.java b/src/main/java/io/jenkins/plugins/opentelemetry/OpenTelemetryLifecycleListener.java
similarity index 95%
rename from src/main/java/io/jenkins/plugins/opentelemetry/OtelComponent.java
rename to src/main/java/io/jenkins/plugins/opentelemetry/OpenTelemetryLifecycleListener.java
index 7266143d7..4847c189b 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/OtelComponent.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/OpenTelemetryLifecycleListener.java
@@ -24,7 +24,7 @@
*
* Used by components that create counters...
*/
-public interface OtelComponent extends Comparable{
+public interface OpenTelemetryLifecycleListener extends Comparable{
/**
* Invoked soon after the Otel SDK has been initialized.
@@ -64,7 +64,7 @@ default int ordinal() {
}
@Override
- default int compareTo(OtelComponent other) {
+ default int compareTo(OpenTelemetryLifecycleListener other) {
if (this.ordinal() == other.ordinal()) {
return this.getClass().getName().compareTo(other.getClass().getName());
} else {
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/OpenTelemetryRootAction.java b/src/main/java/io/jenkins/plugins/opentelemetry/OpenTelemetryRootAction.java
index e6a802931..0002f9bf4 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/OpenTelemetryRootAction.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/OpenTelemetryRootAction.java
@@ -14,12 +14,15 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+/**
+ * Decorates Jenkins navigation GUI with the OpenTelemetry dashboard link if defined
+ */
@Extension
public class OpenTelemetryRootAction implements RootAction {
private static final Logger logger = Logger.getLogger(OpenTelemetryRootAction.class.getName());
private JenkinsOpenTelemetryPluginConfiguration pluginConfiguration;
- private OpenTelemetrySdkProvider openTelemetrySdkProvider;
+ private JenkinsControllerOpenTelemetry jenkinsControllerOpenTelemetry;
public Optional getFirstMetricsCapableObservabilityBackend() {
final Optional observabilityBackend = pluginConfiguration.getObservabilityBackends()
@@ -47,7 +50,7 @@ public String getDisplayName() {
public String getUrlName() {
// TODO we could keep in cache this URL
return getFirstMetricsCapableObservabilityBackend()
- .map(backend -> backend.getMetricsVisualizationUrl(this.openTelemetrySdkProvider.getResource()))
+ .map(backend -> backend.getMetricsVisualizationUrl(this.jenkinsControllerOpenTelemetry.getResource()))
.orElse(null);
}
@@ -57,7 +60,7 @@ public void setJenkinsOpenTelemetryPluginConfiguration(JenkinsOpenTelemetryPlugi
}
@Inject
- public void setOpenTelemetrySdkProvider(OpenTelemetrySdkProvider openTelemetrySdkProvider) {
- this.openTelemetrySdkProvider = openTelemetrySdkProvider;
+ public void setJenkinsControllerOpenTelemetry(JenkinsControllerOpenTelemetry jenkinsControllerOpenTelemetry) {
+ this.jenkinsControllerOpenTelemetry = jenkinsControllerOpenTelemetry;
}
}
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/OpenTelemetrySdkProvider.java b/src/main/java/io/jenkins/plugins/opentelemetry/OpenTelemetrySdkProvider.java
deleted file mode 100644
index cf72624aa..000000000
--- a/src/main/java/io/jenkins/plugins/opentelemetry/OpenTelemetrySdkProvider.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright The Original Author or Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.jenkins.plugins.opentelemetry;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import edu.umd.cs.findbugs.annotations.NonNull;
-import edu.umd.cs.findbugs.annotations.Nullable;
-import hudson.Extension;
-import hudson.ExtensionList;
-import io.jenkins.plugins.opentelemetry.opentelemetry.ClosingOpenTelemetry;
-import io.jenkins.plugins.opentelemetry.opentelemetry.autoconfigure.ConfigPropertiesUtils;
-import io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes;
-import io.opentelemetry.api.GlobalOpenTelemetry;
-import io.opentelemetry.api.OpenTelemetry;
-import io.opentelemetry.api.incubator.events.EventLogger;
-import io.opentelemetry.api.incubator.events.EventLoggerProvider;
-import io.opentelemetry.api.incubator.events.GlobalEventLoggerProvider;
-import io.opentelemetry.api.logs.LoggerProvider;
-import io.opentelemetry.api.metrics.Meter;
-import io.opentelemetry.api.trace.SpanBuilder;
-import io.opentelemetry.api.trace.Tracer;
-import io.opentelemetry.context.propagation.ContextPropagators;
-import io.opentelemetry.instrumentation.resources.ProcessResourceProvider;
-import io.opentelemetry.sdk.OpenTelemetrySdk;
-import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
-import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder;
-import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
-import io.opentelemetry.sdk.common.CompletableResultCode;
-import io.opentelemetry.sdk.resources.Resource;
-
-import javax.annotation.PreDestroy;
-import java.util.Collections;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-
-
-@Extension
-public class OpenTelemetrySdkProvider {
-
- private static final Logger LOGGER = Logger.getLogger(OpenTelemetrySdkProvider.class.getName());
-
- /**
- * See {@code OTEL_JAVA_DISABLED_RESOURCE_PROVIDERS}
- */
- public static final String DEFAULT_OTEL_JAVA_DISABLED_RESOURCE_PROVIDERS = ProcessResourceProvider.class.getName();
-
- protected transient ClosingOpenTelemetry openTelemetry;
-
- protected transient Resource resource;
- protected transient ConfigProperties config;
- @Nullable
- protected transient OpenTelemetrySdk openTelemetrySdk;
- @NonNull
- private final transient TracerDelegate tracer = new TracerDelegate();
- protected transient Meter meter;
- protected transient EventLogger eventLogger;
-
- public OpenTelemetrySdkProvider() {
- }
-
-
- @NonNull
- public Tracer getTracer() {
- return Preconditions.checkNotNull(tracer.getDelegate());
- }
-
- @NonNull
- public Meter getMeter() {
- return Preconditions.checkNotNull(meter);
- }
-
- @NonNull
- public Resource getResource() {
- return Preconditions.checkNotNull(resource);
- }
-
- @NonNull
- public ConfigProperties getConfig() {
- return Preconditions.checkNotNull(config);
- }
-
- public boolean isOtelLogsEnabled(){
- String otelLogsExporter = config.getString("otel.logs.exporter");
- return otelLogsExporter != null && !otelLogsExporter.equals("none");
- }
-
- public boolean isOtelLogsMirrorToDisk(){
- String otelLogsExporter = config.getString("otel.logs.mirror_to_disk");
- return otelLogsExporter != null && otelLogsExporter.equals("true");
- }
-
- @NonNull
- public ContextPropagators getPropagators() {
- return openTelemetry.getPropagators();
- }
-
- @NonNull
- public LoggerProvider getLoggerProvider() {
- return openTelemetry.getLogsBridge();
- }
-
- @VisibleForTesting
- @NonNull
- protected OpenTelemetrySdk getOpenTelemetrySdk() {
- return Preconditions.checkNotNull(openTelemetrySdk);
- }
-
- @PreDestroy
- public void shutdown() {
- if (this.openTelemetrySdk != null) {
- LOGGER.log(Level.FINE, "Shutdown...");
- LOGGER.log(Level.FINE, () -> "Shutdown Otel SDK on components: " + ExtensionList.lookup(OtelComponent.class).stream().sorted().map(e -> e.getClass().getName()).collect(Collectors.joining(", ")));
-
- ExtensionList.lookup(OtelComponent.class).stream().sorted().forEachOrdered(OtelComponent::beforeSdkShutdown);
- this.openTelemetry.close();
- CompletableResultCode shutdown = this.openTelemetrySdk.shutdown();
- if(!shutdown.join(1, TimeUnit.SECONDS).isSuccess()) {
- LOGGER.log(Level.WARNING, "Failure to shutdown OTel SDK");
- }
- }
- GlobalOpenTelemetry.resetForTest();
- GlobalEventLoggerProvider.resetForTest();
- }
-
- public void initialize(@NonNull OpenTelemetryConfiguration configuration) {
- shutdown(); // shutdown existing SDK
- if (configuration.getEndpoint().isPresent()) {
- initializeOtlp(configuration);
- } else {
- initializeNoOp();
- }
- LOGGER.log(Level.FINE, () -> "Initialize Otel SDK on components: " + ExtensionList.lookup(OtelComponent.class).stream().sorted().map(e -> e.getClass().getName()).collect(Collectors.joining(", ")));
- ExtensionList.lookup(OtelComponent.class).stream().sorted().forEachOrdered(otelComponent -> {
- otelComponent.afterSdkInitialized(meter, openTelemetry.getLogsBridge(), eventLogger, tracer, config);
- otelComponent.afterSdkInitialized(openTelemetry, config);
- });
- }
-
- public void initializeOtlp(@NonNull OpenTelemetryConfiguration configuration) {
-
- AutoConfiguredOpenTelemetrySdkBuilder sdkBuilder = AutoConfiguredOpenTelemetrySdk.builder();
- // PROPERTIES
- sdkBuilder.addPropertiesSupplier(configuration::toOpenTelemetryProperties);
- sdkBuilder.addPropertiesCustomizer((Function>) configProperties -> {
- // keep a reference to the computed config properties for future use in the plugin
- OpenTelemetrySdkProvider.this.config = configProperties;
- return Collections.emptyMap();
- });
-
- // RESOURCE
- sdkBuilder.addResourceCustomizer((resource, configProperties) -> {
- // keep a reference to the computed Resource for future use in the plugin
- this.resource = Resource.builder()
- .putAll(resource)
- .putAll(configuration.toOpenTelemetryResource()).build();
- return this.resource;
- }
- );
-
- sdkBuilder
- .disableShutdownHook() // SDK closed by io.jenkins.plugins.opentelemetry.OpenTelemetrySdkProvider.preDestroy()
- .setResultAsGlobal(); // ensure GlobalOpenTelemetry.set() is invoked
- this.openTelemetrySdk = sdkBuilder.build().getOpenTelemetrySdk();
- this.openTelemetry = new ClosingOpenTelemetry(this.openTelemetrySdk);
- String opentelemetryPluginVersion = OtelUtils.getOpentelemetryPluginVersion();
- this.tracer.setDelegate(openTelemetry.getTracerProvider()
- .tracerBuilder(JenkinsOtelSemanticAttributes.INSTRUMENTATION_NAME)
- .setInstrumentationVersion(opentelemetryPluginVersion)
- .build());
- this.meter = openTelemetry.getMeterProvider()
- .meterBuilder(JenkinsOtelSemanticAttributes.INSTRUMENTATION_NAME)
- .setInstrumentationVersion(opentelemetryPluginVersion)
- .build();
- this.eventLogger = GlobalEventLoggerProvider.get()
- .eventLoggerBuilder(JenkinsOtelSemanticAttributes.INSTRUMENTATION_NAME)
- .setInstrumentationVersion(opentelemetryPluginVersion)
- // .setEventDomain("jenkins")
- .build();
-
- LOGGER.log(Level.INFO, () -> "OpenTelemetry SDK initialized: " + OtelUtils.prettyPrintOtelSdkConfig(this.config, this.resource));
- }
-
- @VisibleForTesting
- public void initializeNoOp() {
- LOGGER.log(Level.FINE, "initializeNoOp");
-
- this.openTelemetrySdk = null;
- this.resource = Resource.getDefault();
- this.config = ConfigPropertiesUtils.emptyConfig();
- this.openTelemetry = ClosingOpenTelemetry.noop();
- GlobalOpenTelemetry.resetForTest(); // hack for testing in Intellij cause by DiskUsageMonitoringInitializer
- GlobalEventLoggerProvider.resetForTest();
- GlobalOpenTelemetry.set(OpenTelemetry.noop());
- this.tracer.setDelegate(OpenTelemetry.noop().getTracer(JenkinsOtelSemanticAttributes.INSTRUMENTATION_NAME));
- this.meter = OpenTelemetry.noop().getMeter(JenkinsOtelSemanticAttributes.INSTRUMENTATION_NAME);
- this.eventLogger = EventLoggerProvider.noop().get(JenkinsOtelSemanticAttributes.INSTRUMENTATION_NAME);
- LOGGER.log(Level.FINE, "OpenTelemetry initialized as NoOp");
- }
-
- static public OpenTelemetrySdkProvider get() {
- return ExtensionList.lookupSingleton(OpenTelemetrySdkProvider.class);
- }
-
- static class TracerDelegate implements Tracer {
- private Tracer delegate;
-
- @Override
- public synchronized SpanBuilder spanBuilder(@NonNull String spanName) {
- return delegate.spanBuilder(spanName);
- }
-
- public synchronized void setDelegate(Tracer delegate) {
- this.delegate = delegate;
- }
-
- public synchronized Tracer getDelegate() {
- return delegate;
- }
- }
-}
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/backend/elastic/ElasticsearchLogStorageRetriever.java b/src/main/java/io/jenkins/plugins/opentelemetry/backend/elastic/ElasticsearchLogStorageRetriever.java
index a56b891e7..6abd1576b 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/backend/elastic/ElasticsearchLogStorageRetriever.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/backend/elastic/ElasticsearchLogStorageRetriever.java
@@ -21,7 +21,7 @@
import edu.umd.cs.findbugs.annotations.Nullable;
import groovy.text.Template;
import hudson.util.FormValidation;
-import io.jenkins.plugins.opentelemetry.OpenTelemetrySdkProvider;
+import io.jenkins.plugins.opentelemetry.JenkinsControllerOpenTelemetry;
import io.jenkins.plugins.opentelemetry.TemplateBindingsProvider;
import io.jenkins.plugins.opentelemetry.backend.ElasticBackend;
import io.jenkins.plugins.opentelemetry.backend.ObservabilityBackend;
@@ -378,7 +378,7 @@ public String toString() {
private Tracer getTracer() {
if (_tracer == null) {
- _tracer = OpenTelemetrySdkProvider.get().getTracer();
+ _tracer = JenkinsControllerOpenTelemetry.get().getDefaultTracer();
}
return _tracer;
}
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/computer/MonitoringCloudListener.java b/src/main/java/io/jenkins/plugins/opentelemetry/computer/MonitoringCloudListener.java
index b3819f937..0732bc420 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/computer/MonitoringCloudListener.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/computer/MonitoringCloudListener.java
@@ -10,7 +10,7 @@
import hudson.model.Node;
import hudson.slaves.CloudProvisioningListener;
import hudson.slaves.NodeProvisioner;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsSemanticMetrics;
import io.opentelemetry.api.incubator.events.EventLogger;
import io.opentelemetry.api.logs.LoggerProvider;
@@ -24,7 +24,7 @@
import java.util.logging.Logger;
@Extension(dynamicLoadable = YesNoMaybe.YES, optional = true)
-public class MonitoringCloudListener extends CloudProvisioningListener implements OtelComponent {
+public class MonitoringCloudListener extends CloudProvisioningListener implements OpenTelemetryLifecycleListener {
private final static Logger LOGGER = Logger.getLogger(MonitoringCloudListener.class.getName());
private LongCounter failureCloudCounter;
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/computer/MonitoringComputerListener.java b/src/main/java/io/jenkins/plugins/opentelemetry/computer/MonitoringComputerListener.java
index 2aed2d440..d4f3bb5f0 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/computer/MonitoringComputerListener.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/computer/MonitoringComputerListener.java
@@ -12,7 +12,7 @@
import hudson.remoting.Channel;
import hudson.slaves.ComputerListener;
import io.jenkins.plugins.opentelemetry.OpenTelemetryAttributesAction;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsSemanticMetrics;
import io.opentelemetry.api.common.AttributeKey;
@@ -36,7 +36,7 @@
import java.util.logging.Logger;
@Extension(dynamicLoadable = YesNoMaybe.YES, optional = true)
-public class MonitoringComputerListener extends ComputerListener implements OtelComponent {
+public class MonitoringComputerListener extends ComputerListener implements OpenTelemetryLifecycleListener {
private final static Logger LOGGER = Logger.getLogger(MonitoringComputerListener.class.getName());
private LongCounter failureAgentCounter;
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/init/DiskUsageMonitoringInitializer.java b/src/main/java/io/jenkins/plugins/opentelemetry/init/DiskUsageMonitoringInitializer.java
index 36f0740c3..2044f8752 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/init/DiskUsageMonitoringInitializer.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/init/DiskUsageMonitoringInitializer.java
@@ -9,7 +9,7 @@
import com.cloudbees.simplediskusage.QuickDiskUsagePlugin;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsSemanticMetrics;
import io.opentelemetry.api.incubator.events.EventLogger;
import io.opentelemetry.api.logs.LoggerProvider;
@@ -28,7 +28,7 @@
* Capture disk usage metrics relying on the {@link QuickDiskUsagePlugin}
*/
@Extension(dynamicLoadable = YesNoMaybe.YES, optional = true)
-public class DiskUsageMonitoringInitializer implements OtelComponent {
+public class DiskUsageMonitoringInitializer implements OpenTelemetryLifecycleListener {
private final static Logger LOGGER = Logger.getLogger(DiskUsageMonitoringInitializer.class.getName());
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/init/GitHubClientMonitoring.java b/src/main/java/io/jenkins/plugins/opentelemetry/init/GitHubClientMonitoring.java
index 46d45db2a..0af39047b 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/init/GitHubClientMonitoring.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/init/GitHubClientMonitoring.java
@@ -7,7 +7,7 @@
import com.google.common.base.Preconditions;
import hudson.Extension;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.api.incubator.events.EventLogger;
@@ -39,7 +39,7 @@
* field of the {@link Connector} class because we have not found any public API to observe the state of this GitHub client.
*/
@Extension(dynamicLoadable = YesNoMaybe.YES, optional = true)
-public class GitHubClientMonitoring implements OtelComponent {
+public class GitHubClientMonitoring implements OpenTelemetryLifecycleListener {
private final static Logger logger = Logger.getLogger(GitHubClientMonitoring.class.getName());
private final Field gitHub_clientField;
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/init/JenkinsExecutorMonitoringInitializer.java b/src/main/java/io/jenkins/plugins/opentelemetry/init/JenkinsExecutorMonitoringInitializer.java
index 41701b4ba..5b24d2cf5 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/init/JenkinsExecutorMonitoringInitializer.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/init/JenkinsExecutorMonitoringInitializer.java
@@ -7,7 +7,7 @@
import hudson.Extension;
import hudson.model.LoadStatistics;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.incubator.events.EventLogger;
@@ -22,7 +22,7 @@
import static io.jenkins.plugins.opentelemetry.semconv.JenkinsSemanticMetrics.*;
@Extension(dynamicLoadable = YesNoMaybe.MAYBE, optional = true)
-public class JenkinsExecutorMonitoringInitializer implements OtelComponent {
+public class JenkinsExecutorMonitoringInitializer implements OpenTelemetryLifecycleListener {
@Override
public void afterSdkInitialized(Meter meter, LoggerProvider loggerProvider, EventLogger eventLogger, Tracer tracer, ConfigProperties configProperties) {
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/init/JvmMonitoringInitializer.java b/src/main/java/io/jenkins/plugins/opentelemetry/init/JvmMonitoringInitializer.java
index 741a9c736..c56a2cef1 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/init/JvmMonitoringInitializer.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/init/JvmMonitoringInitializer.java
@@ -6,7 +6,7 @@
package io.jenkins.plugins.opentelemetry.init;
import hudson.Extension;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.runtimemetrics.java8.Classes;
import io.opentelemetry.instrumentation.runtimemetrics.java8.Cpu;
@@ -24,7 +24,7 @@
* Inspired by io.opentelemetry.instrumentation.javaagent.runtimemetrics.RuntimeMetricsInstaller
*/
@Extension(dynamicLoadable = YesNoMaybe.MAYBE, optional = true)
-public class JvmMonitoringInitializer implements OtelComponent {
+public class JvmMonitoringInitializer implements OpenTelemetryLifecycleListener {
private final static Logger LOGGER = Logger.getLogger(JvmMonitoringInitializer.class.getName());
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/init/OtelJulHandler.java b/src/main/java/io/jenkins/plugins/opentelemetry/init/OtelJulHandler.java
index d6e41cd63..d006e899d 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/init/OtelJulHandler.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/init/OtelJulHandler.java
@@ -6,7 +6,7 @@
package io.jenkins.plugins.opentelemetry.init;
import hudson.Extension;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.api.incubator.events.EventLogger;
@@ -34,7 +34,7 @@
* Inspired by https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/v1.14.0/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java
*/
@Extension(dynamicLoadable = YesNoMaybe.YES, optional = true)
-public class OtelJulHandler extends Handler implements OtelComponent {
+public class OtelJulHandler extends Handler implements OpenTelemetryLifecycleListener {
private final static Logger logger = Logger.getLogger(OtelJulHandler.class.getName());
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/init/SCMEventMonitoringInitializer.java b/src/main/java/io/jenkins/plugins/opentelemetry/init/SCMEventMonitoringInitializer.java
index c14cbb35c..592d6a312 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/init/SCMEventMonitoringInitializer.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/init/SCMEventMonitoringInitializer.java
@@ -6,7 +6,7 @@
package io.jenkins.plugins.opentelemetry.init;
import hudson.Extension;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsSemanticMetrics;
import io.opentelemetry.api.incubator.events.EventLogger;
import io.opentelemetry.api.logs.LoggerProvider;
@@ -23,7 +23,7 @@
* Capture SCM Events metrics
*/
@Extension(dynamicLoadable = YesNoMaybe.YES, optional = true)
-public class SCMEventMonitoringInitializer implements OtelComponent {
+public class SCMEventMonitoringInitializer implements OpenTelemetryLifecycleListener {
private final static Logger logger = Logger.getLogger(SCMEventMonitoringInitializer.class.getName());
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/init/ServletFilterInitializer.java b/src/main/java/io/jenkins/plugins/opentelemetry/init/ServletFilterInitializer.java
index 09b23ef38..099728aea 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/init/ServletFilterInitializer.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/init/ServletFilterInitializer.java
@@ -7,7 +7,7 @@
import hudson.Extension;
import hudson.util.PluginServletFilter;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes;
import io.jenkins.plugins.opentelemetry.servlet.StaplerInstrumentationServletFilter;
import io.jenkins.plugins.opentelemetry.servlet.TraceContextServletFilter;
@@ -30,7 +30,7 @@
* events can be associated to an HTTP trace.
*/
@Extension(dynamicLoadable = YesNoMaybe.MAYBE, optional = true)
-public class ServletFilterInitializer implements OtelComponent {
+public class ServletFilterInitializer implements OpenTelemetryLifecycleListener {
private static final Logger logger = Logger.getLogger(ServletFilterInitializer.class.getName());
StaplerInstrumentationServletFilter staplerInstrumentationServletFilter;
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/job/MonitoringBuildStepListener.java b/src/main/java/io/jenkins/plugins/opentelemetry/job/MonitoringBuildStepListener.java
index a96986ea6..3498f3a1b 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/job/MonitoringBuildStepListener.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/job/MonitoringBuildStepListener.java
@@ -14,7 +14,7 @@
import hudson.model.BuildStepListener;
import hudson.tasks.BuildStep;
import io.jenkins.plugins.opentelemetry.JenkinsOpenTelemetryPluginConfiguration;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.jenkins.plugins.opentelemetry.OtelUtils;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes;
import io.opentelemetry.api.incubator.events.EventLogger;
@@ -38,7 +38,7 @@
import static io.jenkins.plugins.opentelemetry.OtelUtils.JENKINS_CORE;
@Extension(dynamicLoadable = YesNoMaybe.YES)
-public class MonitoringBuildStepListener extends BuildStepListener implements OtelComponent {
+public class MonitoringBuildStepListener extends BuildStepListener implements OpenTelemetryLifecycleListener {
protected static final Logger LOGGER = Logger.getLogger(MonitoringRunListener.class.getName());
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/job/MonitoringPipelineListener.java b/src/main/java/io/jenkins/plugins/opentelemetry/job/MonitoringPipelineListener.java
index 3a4a842e3..dee4c333d 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/job/MonitoringPipelineListener.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/job/MonitoringPipelineListener.java
@@ -16,7 +16,7 @@
import hudson.model.Run;
import io.jenkins.plugins.opentelemetry.JenkinsOpenTelemetryPluginConfiguration;
import io.jenkins.plugins.opentelemetry.OpenTelemetryAttributesAction;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.jenkins.plugins.opentelemetry.OtelUtils;
import io.jenkins.plugins.opentelemetry.job.jenkins.AbstractPipelineListener;
import io.jenkins.plugins.opentelemetry.job.jenkins.PipelineListener;
@@ -77,7 +77,7 @@
@Extension(dynamicLoadable = YesNoMaybe.YES, optional = true)
-public class MonitoringPipelineListener extends AbstractPipelineListener implements PipelineListener, StepListener, OtelComponent {
+public class MonitoringPipelineListener extends AbstractPipelineListener implements PipelineListener, StepListener, OpenTelemetryLifecycleListener {
private final static Logger LOGGER = Logger.getLogger(MonitoringPipelineListener.class.getName());
private OtelTraceService otelTraceService;
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/job/action/OtelMonitoringAction.java b/src/main/java/io/jenkins/plugins/opentelemetry/job/action/OtelMonitoringAction.java
index abb3cafd9..aed284966 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/job/action/OtelMonitoringAction.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/job/action/OtelMonitoringAction.java
@@ -12,6 +12,9 @@
import java.util.Map;
+/**
+ * Action to decorate {@link hudson.model.Job} steps to hold references to {@link Span}s
+ */
public interface OtelMonitoringAction extends Action {
Map getW3cTraceContext();
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/job/action/RunPhaseMonitoringAction.java b/src/main/java/io/jenkins/plugins/opentelemetry/job/action/RunPhaseMonitoringAction.java
index 552a8acac..8fc61b6b0 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/job/action/RunPhaseMonitoringAction.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/job/action/RunPhaseMonitoringAction.java
@@ -5,10 +5,12 @@
package io.jenkins.plugins.opentelemetry.job.action;
+import hudson.model.Action;
import io.opentelemetry.api.trace.Span;
/**
- * Span reference associate with a phase of a {@link hudson.model.Run}
+ * Span reference associated with a phase of a {@link hudson.model.Run} as a {@link hudson.model.Run#getActions(Class)}
+ * @see hudson.model.Run#addAction(Action)
* @see io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes#JENKINS_JOB_SPAN_PHASE_START_NAME
* @see io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes#JENKINS_JOB_SPAN_PHASE_RUN_NAME
* @see io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes#JENKINS_JOB_SPAN_PHASE_FINALIZE_NAME
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/job/log/OtelLogSenderBuildListener.java b/src/main/java/io/jenkins/plugins/opentelemetry/job/log/OtelLogSenderBuildListener.java
index 5d28b3ffa..d36291512 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/job/log/OtelLogSenderBuildListener.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/job/log/OtelLogSenderBuildListener.java
@@ -9,7 +9,7 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.model.BuildListener;
-import io.jenkins.plugins.opentelemetry.OpenTelemetrySdkProvider;
+import io.jenkins.plugins.opentelemetry.JenkinsControllerOpenTelemetry;
import io.jenkins.plugins.opentelemetry.opentelemetry.GlobalOpenTelemetrySdk;
import io.jenkins.plugins.opentelemetry.opentelemetry.common.OffsetClock;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes;
@@ -88,7 +88,7 @@ public synchronized final PrintStream getLogger() {
/**
* {@link OtelLogSenderBuildListener} implementation that runs on the Jenkins Controller and
- * that retrieves the {@link io.opentelemetry.api.logs.Logger} from the {@link OpenTelemetrySdkProvider}
+ * that retrieves the {@link io.opentelemetry.api.logs.Logger} from the {@link JenkinsControllerOpenTelemetry}
*/
static final class OtelLogSenderBuildListenerOnController extends OtelLogSenderBuildListener {
private static final long serialVersionUID = 1;
@@ -104,7 +104,7 @@ public OtelLogSenderBuildListenerOnController(@NonNull RunTraceContext runTraceC
@Override
public io.opentelemetry.api.logs.Logger getOtelLogger() {
JenkinsJVM.checkJenkinsJVM();
- return OpenTelemetrySdkProvider.get().getLoggerProvider().get(JenkinsOtelSemanticAttributes.INSTRUMENTATION_NAME);
+ return JenkinsControllerOpenTelemetry.get().getLogsBridge().get(JenkinsOtelSemanticAttributes.INSTRUMENTATION_NAME);
}
/**
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/job/log/OtelLogStorage.java b/src/main/java/io/jenkins/plugins/opentelemetry/job/log/OtelLogStorage.java
index bc5a64aa4..552356565 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/job/log/OtelLogStorage.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/job/log/OtelLogStorage.java
@@ -6,9 +6,9 @@
import hudson.model.BuildListener;
import hudson.model.Run;
import hudson.model.TaskListener;
+import io.jenkins.plugins.opentelemetry.JenkinsControllerOpenTelemetry;
import io.jenkins.plugins.opentelemetry.JenkinsOpenTelemetryPluginConfiguration;
import io.jenkins.plugins.opentelemetry.OpenTelemetryConfiguration;
-import io.jenkins.plugins.opentelemetry.OpenTelemetrySdkProvider;
import io.jenkins.plugins.opentelemetry.job.MonitoringAction;
import io.jenkins.plugins.opentelemetry.job.OtelTraceService;
import io.jenkins.plugins.opentelemetry.job.log.util.TeeBuildListener;
@@ -80,7 +80,7 @@ public BuildListener overallListener() throws IOException {
OtelLogSenderBuildListener otelLogSenderBuildListener = new OtelLogSenderBuildListener.OtelLogSenderBuildListenerOnController(runTraceContext, otelConfigurationProperties, otelResourceAttributes);
BuildListener result;
- if (OpenTelemetrySdkProvider.get().isOtelLogsMirrorToDisk()) {
+ if (JenkinsControllerOpenTelemetry.get().isOtelLogsMirrorToDisk()) {
try {
File logFile = new File(runFolderPath, "log");
BuildListener fileStorageBuildListener = FileLogStorage.forFile(logFile).overallListener();
@@ -120,7 +120,7 @@ public BuildListener nodeListener(@NonNull FlowNode flowNode) throws IOException
OtelLogSenderBuildListener otelLogSenderBuildListener = new OtelLogSenderBuildListener.OtelLogSenderBuildListenerOnController(flowNodeTraceContext, otelConfigurationProperties, otelResourceAttributes);
BuildListener result;
- if (OpenTelemetrySdkProvider.get().isOtelLogsMirrorToDisk()) {
+ if (JenkinsControllerOpenTelemetry.get().isOtelLogsMirrorToDisk()) {
try {
File logFile = new File(runFolderPath, "log");
BuildListener fileStorageBuildListener = BuildListenerAdapter.wrap(FileLogStorage.forFile(logFile).nodeListener(flowNode));
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/job/log/OtelLogStorageFactory.java b/src/main/java/io/jenkins/plugins/opentelemetry/job/log/OtelLogStorageFactory.java
index 923ee2642..720e7dca2 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/job/log/OtelLogStorageFactory.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/job/log/OtelLogStorageFactory.java
@@ -11,8 +11,8 @@
import hudson.ExtensionList;
import hudson.model.Queue;
import hudson.model.Run;
-import io.jenkins.plugins.opentelemetry.OpenTelemetrySdkProvider;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.JenkinsControllerOpenTelemetry;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.jenkins.plugins.opentelemetry.job.OtelTraceService;
import io.opentelemetry.api.incubator.events.EventLogger;
import io.opentelemetry.api.logs.LoggerProvider;
@@ -34,7 +34,7 @@
* See https://github.com/jenkinsci/pipeline-cloudwatch-logs-plugin/blob/pipeline-cloudwatch-logs-0.2/src/main/java/io/jenkins/plugins/pipeline_cloudwatch_logs/PipelineBridge.java
*/
@Extension
-public final class OtelLogStorageFactory implements LogStorageFactory, OtelComponent {
+public final class OtelLogStorageFactory implements LogStorageFactory, OpenTelemetryLifecycleListener {
private final static Logger logger = Logger.getLogger(OtelLogStorageFactory.class.getName());
@@ -43,8 +43,7 @@ public final class OtelLogStorageFactory implements LogStorageFactory, OtelCompo
System.setProperty("org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.USE_WATCHING", "true");
}
- @Nullable
- private OpenTelemetrySdkProvider openTelemetrySdkProvider;
+ JenkinsControllerOpenTelemetry jenkinsControllerOpenTelemetry;
@Nullable
private OtelTraceService otelTraceService;
@@ -58,7 +57,7 @@ static OtelLogStorageFactory get() {
@Nullable
@Override
public LogStorage forBuild(@NonNull final FlowExecutionOwner owner) {
- if (!getOpenTelemetrySdkProvider().isOtelLogsEnabled()) {
+ if (!getJenkinsControllerOpenTelemetry().isLogsEnabled()) {
logger.log(Level.FINE, () -> "OTel Logs disabled");
return null;
}
@@ -83,11 +82,11 @@ public LogStorage forBuild(@NonNull final FlowExecutionOwner owner) {
* Workaround dependency injection problem. @Inject doesn't work here
*/
@NonNull
- private OpenTelemetrySdkProvider getOpenTelemetrySdkProvider() {
- if (openTelemetrySdkProvider == null) {
- openTelemetrySdkProvider = OpenTelemetrySdkProvider.get();
+ private JenkinsControllerOpenTelemetry getJenkinsControllerOpenTelemetry() {
+ if (jenkinsControllerOpenTelemetry == null) {
+ jenkinsControllerOpenTelemetry = JenkinsControllerOpenTelemetry.get();
}
- return openTelemetrySdkProvider;
+ return jenkinsControllerOpenTelemetry;
}
/**
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/job/opentelemetry/OtelContextAwareAbstractRunListener.java b/src/main/java/io/jenkins/plugins/opentelemetry/job/opentelemetry/OtelContextAwareAbstractRunListener.java
index 68f51cbb3..27ee4ddd3 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/job/opentelemetry/OtelContextAwareAbstractRunListener.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/job/opentelemetry/OtelContextAwareAbstractRunListener.java
@@ -13,7 +13,7 @@
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.model.listeners.RunListener;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.jenkins.plugins.opentelemetry.job.OtelTraceService;
import io.opentelemetry.api.incubator.events.EventLogger;
import io.opentelemetry.api.logs.LoggerProvider;
@@ -31,7 +31,7 @@
* {@link RunListener} that setups the OpenTelemetry {@link io.opentelemetry.context.Context}
* with the current {@link Span}.
*/
-public abstract class OtelContextAwareAbstractRunListener extends RunListener implements OtelComponent {
+public abstract class OtelContextAwareAbstractRunListener extends RunListener implements OpenTelemetryLifecycleListener {
private final static Logger LOGGER = Logger.getLogger(OtelContextAwareAbstractRunListener.class.getName());
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ClosingOpenTelemetry.java b/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/CloseableMeterProvider.java
similarity index 68%
rename from src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ClosingOpenTelemetry.java
rename to src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/CloseableMeterProvider.java
index bf27f4acf..0f19b1064 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ClosingOpenTelemetry.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/CloseableMeterProvider.java
@@ -6,13 +6,30 @@
package io.jenkins.plugins.opentelemetry.opentelemetry;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import io.opentelemetry.api.OpenTelemetry;
-import io.opentelemetry.api.logs.LoggerProvider;
-import io.opentelemetry.api.metrics.*;
-import io.opentelemetry.api.trace.Tracer;
-import io.opentelemetry.api.trace.TracerBuilder;
-import io.opentelemetry.api.trace.TracerProvider;
-import io.opentelemetry.context.propagation.ContextPropagators;
+import io.opentelemetry.api.metrics.BatchCallback;
+import io.opentelemetry.api.metrics.DoubleCounter;
+import io.opentelemetry.api.metrics.DoubleCounterBuilder;
+import io.opentelemetry.api.metrics.DoubleGaugeBuilder;
+import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
+import io.opentelemetry.api.metrics.DoubleUpDownCounter;
+import io.opentelemetry.api.metrics.DoubleUpDownCounterBuilder;
+import io.opentelemetry.api.metrics.LongCounter;
+import io.opentelemetry.api.metrics.LongCounterBuilder;
+import io.opentelemetry.api.metrics.LongGaugeBuilder;
+import io.opentelemetry.api.metrics.LongUpDownCounter;
+import io.opentelemetry.api.metrics.LongUpDownCounterBuilder;
+import io.opentelemetry.api.metrics.Meter;
+import io.opentelemetry.api.metrics.MeterBuilder;
+import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.api.metrics.ObservableDoubleCounter;
+import io.opentelemetry.api.metrics.ObservableDoubleGauge;
+import io.opentelemetry.api.metrics.ObservableDoubleMeasurement;
+import io.opentelemetry.api.metrics.ObservableDoubleUpDownCounter;
+import io.opentelemetry.api.metrics.ObservableLongCounter;
+import io.opentelemetry.api.metrics.ObservableLongGauge;
+import io.opentelemetry.api.metrics.ObservableLongMeasurement;
+import io.opentelemetry.api.metrics.ObservableLongUpDownCounter;
+import io.opentelemetry.api.metrics.ObservableMeasurement;
import java.io.Closeable;
import java.util.ArrayList;
@@ -21,28 +38,38 @@
import java.util.logging.Level;
import java.util.logging.Logger;
-/**
- * Holds a reference on all the instantiated {@link AutoCloseable} instrument in order to properly close them before
- * reconfigurations (eg {@link ObservableLongUpDownCounter}, {@link ObservableLongCounter}...).
- */
-public class ClosingOpenTelemetry implements OpenTelemetry, Closeable {
+public class CloseableMeterProvider implements MeterProvider, Closeable {
+ private final static Logger LOGGER = Logger.getLogger(CloseableMeterProvider.class.getName());
+
+ /**
+ * Reference on all the instantiated {@link AutoCloseable} instrument in order to properly close them before
+ * reconfigurations (eg {@link ObservableLongUpDownCounter}, {@link ObservableLongCounter}...).
+ */
+ final List closeables = new ArrayList<>();
- private final static Logger LOGGER = Logger.getLogger(ClosingOpenTelemetry.class.getName());
+ final MeterProvider delegate;
- public static ClosingOpenTelemetry noop() {
- return new ClosingOpenTelemetry(OpenTelemetry.noop());
+ public CloseableMeterProvider(MeterProvider delegate) {
+ this.delegate = delegate;
}
- final OpenTelemetry delegate;
+ @Override
+ public Meter get(String instrumentationScopeName) {
+ return new CloseableMeter(delegate.get(instrumentationScopeName));
+ }
- final List closeables = new ArrayList<>();
+ @Override
+ public MeterBuilder meterBuilder(String instrumentationScopeName) {
+ return new CloseableMeterBuilder(delegate.meterBuilder(instrumentationScopeName));
+ }
@Override
public void close() {
+ LOGGER.log(Level.FINE, () -> "Close " + closeables.size() + " instruments");
+ LOGGER.log(Level.FINEST, () -> "Close " + closeables);
List instruments = new ArrayList<>(this.closeables);
this.closeables.clear(); // reset the list of instruments for reuse
- LOGGER.log(Level.FINE, () -> "Close " + instruments.size() + " instruments");
- LOGGER.log(Level.FINEST, () -> "Close " + instruments);
+
for (AutoCloseable instrument : instruments) {
try {
instrument.close();
@@ -53,77 +80,10 @@ public void close() {
}
}
- public ClosingOpenTelemetry(OpenTelemetry delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public TracerProvider getTracerProvider() {
- return delegate.getTracerProvider();
- }
-
- @Override
- public Tracer getTracer(String instrumentationScopeName) {
- return delegate.getTracer(instrumentationScopeName);
- }
-
- @Override
- public Tracer getTracer(String instrumentationScopeName, String instrumentationScopeVersion) {
- return delegate.getTracer(instrumentationScopeName, instrumentationScopeVersion);
- }
-
- @Override
- public TracerBuilder tracerBuilder(String instrumentationScopeName) {
- return delegate.tracerBuilder(instrumentationScopeName);
- }
-
- @Override
- public MeterProvider getMeterProvider() {
- return new ClosingMeterProvider(delegate.getMeterProvider());
- }
-
- @Override
- public Meter getMeter(String instrumentationScopeName) {
- return new ClosingMeter(delegate.getMeter(instrumentationScopeName));
- }
-
- @Override
- public LoggerProvider getLogsBridge() {
- return delegate.getLogsBridge();
- }
-
- @Override
- public MeterBuilder meterBuilder(String instrumentationScopeName) {
- return new ClosingMeterBuilder(delegate.meterBuilder(instrumentationScopeName));
- }
-
- @Override
- public ContextPropagators getPropagators() {
- return delegate.getPropagators();
- }
-
- class ClosingMeterProvider implements MeterProvider {
- final MeterProvider delegate;
-
- public ClosingMeterProvider(MeterProvider delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public Meter get(String instrumentationScopeName) {
- return new ClosingMeter(delegate.get(instrumentationScopeName));
- }
-
- @Override
- public MeterBuilder meterBuilder(String instrumentationScopeName) {
- return new ClosingMeterBuilder(delegate.meterBuilder(instrumentationScopeName));
- }
- }
-
- class ClosingMeterBuilder implements MeterBuilder {
+ class CloseableMeterBuilder implements MeterBuilder {
final MeterBuilder delegate;
- ClosingMeterBuilder(MeterBuilder delegate) {
+ CloseableMeterBuilder(MeterBuilder delegate) {
this.delegate = delegate;
}
@@ -143,25 +103,25 @@ public MeterBuilder setInstrumentationVersion(String instrumentationScopeVersion
@Override
public Meter build() {
- return new ClosingMeter(delegate.build());
+ return new CloseableMeter(delegate.build());
}
}
- class ClosingMeter implements Meter {
+ class CloseableMeter implements Meter {
private final Meter delegate;
- ClosingMeter(Meter delegate) {
+ CloseableMeter(Meter delegate) {
this.delegate = delegate;
}
@Override
public LongCounterBuilder counterBuilder(String name) {
- return new ClosingLongCounterBuilder(delegate.counterBuilder(name));
+ return new CloseableLongCounterBuilder(delegate.counterBuilder(name));
}
@Override
public LongUpDownCounterBuilder upDownCounterBuilder(String name) {
- return new ClosingLongUpDownCounterBuilder(delegate.upDownCounterBuilder(name));
+ return new CloseableLongUpDownCounterBuilder(delegate.upDownCounterBuilder(name));
}
@Override
@@ -171,7 +131,7 @@ public DoubleHistogramBuilder histogramBuilder(String name) {
@Override
public DoubleGaugeBuilder gaugeBuilder(String name) {
- return new ClosingDoubleGaugeBuilder(delegate.gaugeBuilder(name));
+ return new CloseableDoubleGaugeBuilder(delegate.gaugeBuilder(name));
}
@Override
@@ -182,10 +142,10 @@ public BatchCallback batchCallback(Runnable callback, ObservableMeasurement obse
}
}
- class ClosingLongCounterBuilder implements LongCounterBuilder {
+ class CloseableLongCounterBuilder implements LongCounterBuilder {
final LongCounterBuilder delegate;
- ClosingLongCounterBuilder(LongCounterBuilder delegate) {
+ CloseableLongCounterBuilder(LongCounterBuilder delegate) {
this.delegate = delegate;
}
@@ -205,7 +165,7 @@ public LongCounterBuilder setUnit(String unit) {
@Override
public DoubleCounterBuilder ofDoubles() {
- return new ClosingDoubleCounterBuilder(delegate.ofDoubles());
+ return new CloseableDoubleCounterBuilder(delegate.ofDoubles());
}
@Override
@@ -226,7 +186,7 @@ public ObservableLongMeasurement buildObserver() {
}
}
- class ClosingLongUpDownCounterBuilder implements LongUpDownCounterBuilder {
+ class CloseableLongUpDownCounterBuilder implements LongUpDownCounterBuilder {
@Override
@SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT")
public LongUpDownCounterBuilder setDescription(String description) {
@@ -243,7 +203,7 @@ public LongUpDownCounterBuilder setUnit(String unit) {
@Override
public DoubleUpDownCounterBuilder ofDoubles() {
- return new ClosingDoubleUpDownCounterBuilder(delegate.ofDoubles());
+ return new CloseableDoubleUpDownCounterBuilder(delegate.ofDoubles());
}
@Override
@@ -265,16 +225,16 @@ public ObservableLongMeasurement buildObserver() {
final LongUpDownCounterBuilder delegate;
- ClosingLongUpDownCounterBuilder(LongUpDownCounterBuilder delegate) {
+ CloseableLongUpDownCounterBuilder(LongUpDownCounterBuilder delegate) {
this.delegate = delegate;
}
}
- class ClosingDoubleUpDownCounterBuilder implements DoubleUpDownCounterBuilder {
+ class CloseableDoubleUpDownCounterBuilder implements DoubleUpDownCounterBuilder {
final DoubleUpDownCounterBuilder delegate;
- ClosingDoubleUpDownCounterBuilder(DoubleUpDownCounterBuilder delegate) {
+ CloseableDoubleUpDownCounterBuilder(DoubleUpDownCounterBuilder delegate) {
this.delegate = delegate;
}
@@ -310,10 +270,10 @@ public ObservableDoubleMeasurement buildObserver() {
}
}
- class ClosingDoubleGaugeBuilder implements DoubleGaugeBuilder {
+ class CloseableDoubleGaugeBuilder implements DoubleGaugeBuilder {
final DoubleGaugeBuilder delegate;
- ClosingDoubleGaugeBuilder(DoubleGaugeBuilder delegate) {
+ CloseableDoubleGaugeBuilder(DoubleGaugeBuilder delegate) {
this.delegate = delegate;
}
@@ -333,7 +293,7 @@ public DoubleGaugeBuilder setUnit(String unit) {
@Override
public LongGaugeBuilder ofLongs() {
- return new ClosingLongGaugeBuilder(delegate.ofLongs());
+ return new CloseableLongGaugeBuilder(delegate.ofLongs());
}
@Override
@@ -349,10 +309,10 @@ public ObservableDoubleMeasurement buildObserver() {
}
}
- class ClosingLongGaugeBuilder implements LongGaugeBuilder {
+ class CloseableLongGaugeBuilder implements LongGaugeBuilder {
final LongGaugeBuilder delegate;
- ClosingLongGaugeBuilder(LongGaugeBuilder delegate) {
+ CloseableLongGaugeBuilder(LongGaugeBuilder delegate) {
this.delegate = delegate;
}
@@ -383,10 +343,10 @@ public ObservableLongMeasurement buildObserver() {
}
}
- class ClosingDoubleCounterBuilder implements DoubleCounterBuilder {
+ class CloseableDoubleCounterBuilder implements DoubleCounterBuilder {
final DoubleCounterBuilder delegate;
- ClosingDoubleCounterBuilder(DoubleCounterBuilder delegate) {
+ CloseableDoubleCounterBuilder(DoubleCounterBuilder delegate) {
this.delegate = delegate;
}
@@ -421,4 +381,4 @@ public ObservableDoubleMeasurement buildObserver() {
return delegate.buildObserver();
}
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/InstrumentationScope.java b/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/InstrumentationScope.java
new file mode 100644
index 000000000..16d0e6d80
--- /dev/null
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/InstrumentationScope.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright The Original Author or Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.jenkins.plugins.opentelemetry.opentelemetry;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.Objects;
+
+public class InstrumentationScope {
+ @Nonnull
+ final String instrumentationScopeName;
+ @Nullable
+ final String schemaUrl;
+ @Nullable
+ final String instrumentationScopeVersion;
+
+ public InstrumentationScope(String instrumentationScopeName, @Nullable String schemaUrl, @Nullable String instrumentationScopeVersion) {
+ this.instrumentationScopeName = Objects.requireNonNull(instrumentationScopeName);
+ this.schemaUrl = schemaUrl;
+ this.instrumentationScopeVersion = instrumentationScopeVersion;
+ }
+
+ public InstrumentationScope(@Nonnull String instrumentationScopeName) {
+ this.instrumentationScopeName = instrumentationScopeName;
+ this.schemaUrl = null;
+ this.instrumentationScopeVersion = null;
+ }
+
+ @Override
+ public String toString() {
+ return "InstrumentationScope{" +
+ "instrumentationScopeName='" + instrumentationScopeName + '\'' +
+ ", schemaUrl='" + schemaUrl + '\'' +
+ ", instrumentationScopeVersion='" + instrumentationScopeVersion + '\'' +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ InstrumentationScope that = (InstrumentationScope) o;
+ return Objects.equals(instrumentationScopeName, that.instrumentationScopeName) && Objects.equals(schemaUrl, that.schemaUrl) && Objects.equals(instrumentationScopeVersion, that.instrumentationScopeVersion);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(instrumentationScopeName, schemaUrl, instrumentationScopeVersion);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableEventLoggerProvider.java b/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableEventLoggerProvider.java
new file mode 100644
index 000000000..81ba97de6
--- /dev/null
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableEventLoggerProvider.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright The Original Author or Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.jenkins.plugins.opentelemetry.opentelemetry;
+
+import com.google.common.annotations.VisibleForTesting;
+import io.opentelemetry.api.incubator.events.EventBuilder;
+import io.opentelemetry.api.incubator.events.EventLogger;
+import io.opentelemetry.api.incubator.events.EventLoggerBuilder;
+import io.opentelemetry.api.incubator.events.EventLoggerProvider;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class ReconfigurableEventLoggerProvider implements EventLoggerProvider {
+
+ private final ConcurrentMap eventLoggers = new ConcurrentHashMap<>();
+ private EventLoggerProvider delegate = EventLoggerProvider.noop();
+
+ @Override
+ public EventLoggerBuilder eventLoggerBuilder(String instrumentationScopeName) {
+ return new ReconfigurableEventLoggerBuilder(delegate.eventLoggerBuilder(instrumentationScopeName), instrumentationScopeName);
+ }
+
+ @Override
+ public EventLogger get(String instrumentationScopeName) {
+ return eventLoggers.computeIfAbsent(new InstrumentationScope(instrumentationScopeName), key -> new ReconfigurableEventLogger(delegate.get(key.instrumentationScopeName)));
+ }
+
+ public void setDelegate(EventLoggerProvider delegateEventLoggerBuilder) {
+ this.delegate = delegateEventLoggerBuilder;
+ eventLoggers.forEach((key, reconfigurableEventLogger) -> {
+ EventLoggerBuilder eventLoggerBuilder = delegateEventLoggerBuilder.eventLoggerBuilder(key.instrumentationScopeName);
+ Optional.ofNullable(key.schemaUrl).ifPresent(eventLoggerBuilder::setSchemaUrl);
+ Optional.ofNullable(key.instrumentationScopeVersion).ifPresent(eventLoggerBuilder::setInstrumentationVersion);
+ reconfigurableEventLogger.delegateEventLogger = eventLoggerBuilder.build();
+ });
+ }
+
+ @VisibleForTesting
+ protected Map getEventLoggers() {
+ return eventLoggers;
+ }
+
+ @VisibleForTesting
+ protected static class ReconfigurableEventLogger implements EventLogger {
+ EventLogger delegateEventLogger;
+
+ public ReconfigurableEventLogger(EventLogger delegateEventLogger) {
+ this.delegateEventLogger = Objects.requireNonNull(delegateEventLogger);
+ }
+
+ @Override
+ public EventBuilder builder(String eventName) {
+ return delegateEventLogger.builder(eventName);
+ }
+ }
+
+ @VisibleForTesting
+ protected class ReconfigurableEventLoggerBuilder implements EventLoggerBuilder {
+ EventLoggerBuilder delegate;
+ String instrumentationScopeName;
+ String schemaUrl;
+ String instrumentationScopeVersion;
+
+ public ReconfigurableEventLoggerBuilder(EventLoggerBuilder delegate, String instrumentationScopeName) {
+ this.delegate = Objects.requireNonNull(delegate);
+ this.instrumentationScopeName = Objects.requireNonNull(instrumentationScopeName);
+ }
+
+ @Override
+ public EventLoggerBuilder setSchemaUrl(String schemaUrl) {
+ delegate.setSchemaUrl(schemaUrl);
+ this.schemaUrl = schemaUrl;
+ return this;
+ }
+
+ @Override
+ public EventLoggerBuilder setInstrumentationVersion(String instrumentationScopeVersion) {
+ delegate.setInstrumentationVersion(instrumentationScopeVersion);
+ this.instrumentationScopeVersion = instrumentationScopeVersion;
+ return this;
+ }
+
+ @Override
+ public EventLogger build() {
+ InstrumentationScope key = new InstrumentationScope(instrumentationScopeName, schemaUrl, instrumentationScopeVersion);
+ return eventLoggers.computeIfAbsent(key, k -> new ReconfigurableEventLogger(delegate.build()));
+ }
+ }
+}
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableLoggerProvider.java b/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableLoggerProvider.java
new file mode 100644
index 000000000..e9f69901e
--- /dev/null
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableLoggerProvider.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright The Original Author or Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.jenkins.plugins.opentelemetry.opentelemetry;
+
+import com.google.common.annotations.VisibleForTesting;
+import io.opentelemetry.api.logs.LogRecordBuilder;
+import io.opentelemetry.api.logs.Logger;
+import io.opentelemetry.api.logs.LoggerBuilder;
+import io.opentelemetry.api.logs.LoggerProvider;
+import io.opentelemetry.api.trace.TracerBuilder;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class ReconfigurableLoggerProvider implements LoggerProvider {
+ private LoggerProvider delegate;
+
+ private final ConcurrentMap loggers = new ConcurrentHashMap<>();
+
+ public ReconfigurableLoggerProvider() {
+ this(LoggerProvider.noop());
+ }
+
+ public ReconfigurableLoggerProvider(LoggerProvider delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public LoggerBuilder loggerBuilder(String instrumentationScopeName) {
+ return new ReconfigurableLoggerBuilder(delegate.loggerBuilder(instrumentationScopeName), instrumentationScopeName);
+ }
+
+ @Override
+ public Logger get(String instrumentationScopeName) {
+ InstrumentationScope instrumentationScope = new InstrumentationScope(instrumentationScopeName);
+ return loggers.computeIfAbsent(instrumentationScope, scope -> new ReconfigurableLogger(delegate.get(instrumentationScopeName)));
+ }
+
+ public void setDelegate(LoggerProvider delegate) {
+ this.delegate = delegate;
+ loggers.forEach((instrumentationScope, reconfigurableTracer) -> {
+ LoggerBuilder loggerBuilder = delegate.loggerBuilder(instrumentationScope.instrumentationScopeName);
+ Optional.ofNullable(instrumentationScope.instrumentationScopeVersion).ifPresent(loggerBuilder::setInstrumentationVersion);
+ Optional.ofNullable(instrumentationScope.schemaUrl).ifPresent(loggerBuilder::setSchemaUrl);
+ reconfigurableTracer.setDelegate(loggerBuilder.build());
+ });
+ }
+
+ @VisibleForTesting
+ protected class ReconfigurableLoggerBuilder implements LoggerBuilder {
+ LoggerBuilder delegate;
+ String instrumentationScopeName;
+ String schemaUrl;
+ String instrumentationScopeVersion;
+
+ public ReconfigurableLoggerBuilder(LoggerBuilder delegate, String instrumentationScopeName) {
+ this.delegate = Objects.requireNonNull(delegate);
+ this.instrumentationScopeName = Objects.requireNonNull(instrumentationScopeName);
+ }
+
+ @Override
+ public LoggerBuilder setSchemaUrl(String schemaUrl) {
+ this.schemaUrl = schemaUrl;
+ delegate.setSchemaUrl(schemaUrl);
+ return this;
+ }
+
+ @Override
+ public LoggerBuilder setInstrumentationVersion(String instrumentationScopeVersion) {
+ this.instrumentationScopeVersion = instrumentationScopeVersion;
+ delegate.setInstrumentationVersion(instrumentationScopeVersion);
+ return this;
+ }
+
+ @Override
+ public Logger build() {
+ InstrumentationScope instrumentationScope = new InstrumentationScope(instrumentationScopeName, schemaUrl, instrumentationScopeVersion);
+ return loggers.computeIfAbsent(instrumentationScope, scope -> new ReconfigurableLogger(delegate.build()));
+ }
+ }
+
+ @VisibleForTesting
+ protected static class ReconfigurableLogger implements Logger {
+ Logger delegate;
+
+ public ReconfigurableLogger(Logger delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public synchronized LogRecordBuilder logRecordBuilder() {
+ return delegate.logRecordBuilder();
+ }
+
+ public synchronized void setDelegate(Logger delegate) {
+ this.delegate = delegate;
+ }
+ }
+}
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableOpenTelemetry.java b/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableOpenTelemetry.java
new file mode 100644
index 000000000..a894ded55
--- /dev/null
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableOpenTelemetry.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright The Original Author or Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.jenkins.plugins.opentelemetry.opentelemetry;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import edu.umd.cs.findbugs.annotations.NonNull;
+import hudson.ExtensionList;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
+import io.jenkins.plugins.opentelemetry.OtelUtils;
+import io.jenkins.plugins.opentelemetry.opentelemetry.autoconfigure.ConfigPropertiesUtils;
+import io.opentelemetry.api.GlobalOpenTelemetry;
+import io.opentelemetry.api.OpenTelemetry;
+import io.opentelemetry.api.incubator.events.EventLoggerProvider;
+import io.opentelemetry.api.incubator.events.GlobalEventLoggerProvider;
+import io.opentelemetry.api.logs.LoggerProvider;
+import io.opentelemetry.api.metrics.Meter;
+import io.opentelemetry.api.metrics.MeterBuilder;
+import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.api.trace.Tracer;
+import io.opentelemetry.api.trace.TracerBuilder;
+import io.opentelemetry.api.trace.TracerProvider;
+import io.opentelemetry.context.propagation.ContextPropagators;
+import io.opentelemetry.sdk.OpenTelemetrySdk;
+import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
+import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
+import io.opentelemetry.sdk.common.CompletableResultCode;
+import io.opentelemetry.sdk.logs.internal.SdkEventLoggerProvider;
+import io.opentelemetry.sdk.resources.Resource;
+
+import java.io.Closeable;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+/**
+ * Reconfigurable {@link OpenTelemetry}
+ */
+public class ReconfigurableOpenTelemetry implements OpenTelemetry, Closeable {
+
+ private final Logger LOGGER = Logger.getLogger(ReconfigurableOpenTelemetry.class.getName());
+ protected transient Resource resource;
+ protected transient ConfigProperties config;
+ protected transient OpenTelemetry openTelemetryImpl = OpenTelemetry.noop();
+ protected transient CloseableMeterProvider meterProviderImpl = new CloseableMeterProvider(MeterProvider.noop());
+ protected final transient ReconfigurableTracerProvider traceProviderImpl = new ReconfigurableTracerProvider();
+ protected final transient ReconfigurableEventLoggerProvider eventLoggerProviderImpl = new ReconfigurableEventLoggerProvider();
+ protected final transient ReconfigurableLoggerProvider loggerProviderImpl = new ReconfigurableLoggerProvider();
+
+ /**
+ * Initialize as NoOp
+ */
+ public ReconfigurableOpenTelemetry() {
+ try {
+ GlobalOpenTelemetry.set(this);
+ } catch (IllegalStateException e) {
+ LOGGER.log(Level.WARNING, "GlobalOpenTelemetry already set", e);
+ }
+ try {
+ GlobalEventLoggerProvider.set(eventLoggerProviderImpl);
+ } catch (IllegalStateException e) {
+ LOGGER.log(Level.WARNING, "GlobalEventLoggerProvider already set", e);
+ }
+
+ LOGGER.log(Level.FINE, () -> "Initialize " +
+ "GlobalOpenTelemetry with instance " + Optional.of(GlobalOpenTelemetry.get()).map(ot -> ot + "@" + System.identityHashCode(ot)) + "and " +
+ "GlobalEventLoggerProvide with instance " + Optional.of(GlobalEventLoggerProvider.get()).map(elp -> elp + "@" + System.identityHashCode(elp)));
+ }
+
+ public void configure(@NonNull Map openTelemetryProperties, Resource openTelemetryResource) {
+ close(); // shutdown existing SDK
+ if (openTelemetryProperties.containsKey("otel.exporter.otlp.endpoint") ||
+ openTelemetryProperties.containsKey("otel.traces.exporter") ||
+ openTelemetryProperties.containsKey("otel.metrics.exporter") ||
+ openTelemetryProperties.containsKey("otel.logs.exporter")) {
+
+ LOGGER.log(Level.FINE, "initializeOtlp");
+
+ // OPENTELEMETRY SDK
+ OpenTelemetrySdk openTelemetrySdk = AutoConfiguredOpenTelemetrySdk
+ .builder()
+ // properties
+ .addPropertiesSupplier(() -> openTelemetryProperties)
+ .addPropertiesCustomizer((Function>) configProperties -> {
+ // keep a reference to the computed config properties for future use in the plugin
+ this.config = configProperties;
+ return Collections.emptyMap();
+ })
+ // resource
+ .addResourceCustomizer((resource1, configProperties) -> {
+ // keep a reference to the computed Resource for future use in the plugin
+ this.resource = Resource.builder()
+ .putAll(resource1)
+ .putAll(openTelemetryResource).build();
+ return this.resource;
+ }
+ )
+ // disable shutdown hook, SDK closed by #close()
+ .disableShutdownHook()
+ .build()
+ .getOpenTelemetrySdk();
+
+ // OTEL IMPL
+ this.openTelemetryImpl = openTelemetrySdk;
+ // TRACER PROVIDER
+ traceProviderImpl.setDelegate(openTelemetryImpl.getTracerProvider());
+ // METER PROVIDER
+ meterProviderImpl = new CloseableMeterProvider(openTelemetryImpl.getMeterProvider());
+ // LOGGER PROVIDER
+ loggerProviderImpl.setDelegate(openTelemetryImpl.getLogsBridge());
+ // EVENT LOGGER PROVIDER
+ eventLoggerProviderImpl.setDelegate(SdkEventLoggerProvider.create(openTelemetrySdk.getSdkLoggerProvider()));
+
+ LOGGER.log(Level.INFO, () -> "OpenTelemetry initialized: " + OtelUtils.prettyPrintOtelSdkConfig(this.config, this.resource));
+
+ } else { // NO-OP
+
+ this.resource = Resource.getDefault();
+ this.config = ConfigPropertiesUtils.emptyConfig();
+ this.openTelemetryImpl = OpenTelemetry.noop();
+ this.traceProviderImpl.setDelegate(TracerProvider.noop());
+ this.meterProviderImpl = new CloseableMeterProvider(MeterProvider.noop());
+ this.loggerProviderImpl.setDelegate(LoggerProvider.noop());
+ this.eventLoggerProviderImpl.setDelegate(EventLoggerProvider.noop());
+
+ LOGGER.log(Level.INFO, "OpenTelemetry initialized as NoOp");
+ }
+
+ postOpenTelemetrySdkConfiguration();
+ }
+
+ @Override
+ public void close() {
+ LOGGER.log(Level.FINE, "Shutdown...");
+
+ // METER PROVIDER
+ meterProviderImpl.close();
+
+ // OTEL LIFECYCLE LISTENERS
+ LOGGER.log(Level.FINE, () -> "Shutdown Otel SDK on components: " + ExtensionList.lookup(OpenTelemetryLifecycleListener.class).stream().sorted().map(e -> e.getClass().getName()).collect(Collectors.joining(", ")));
+ ExtensionList.lookup(OpenTelemetryLifecycleListener.class).stream().sorted().forEachOrdered(OpenTelemetryLifecycleListener::beforeSdkShutdown);
+
+ // OTEL SDK
+ if (this.openTelemetryImpl instanceof OpenTelemetrySdk) {
+ LOGGER.log(Level.FINE, () -> "Shutdown OTel SDK...");
+ CompletableResultCode shutdown = ((OpenTelemetrySdk) this.openTelemetryImpl).shutdown();
+ if (!shutdown.join(1, TimeUnit.SECONDS).isSuccess()) {
+ LOGGER.log(Level.WARNING, "Failure to shutdown OTel SDK");
+ }
+ }
+ GlobalOpenTelemetry.resetForTest();
+ GlobalEventLoggerProvider.resetForTest();
+ }
+
+ @Override
+ public TracerProvider getTracerProvider() {
+ return traceProviderImpl;
+ }
+
+ @Override
+ public Tracer getTracer(String instrumentationScopeName) {
+ return traceProviderImpl.get(instrumentationScopeName);
+ }
+
+ @Override
+ public Tracer getTracer(String instrumentationScopeName, String instrumentationScopeVersion) {
+ return traceProviderImpl.get(instrumentationScopeName, instrumentationScopeVersion);
+ }
+
+ @Override
+ public TracerBuilder tracerBuilder(String instrumentationScopeName) {
+ return traceProviderImpl.tracerBuilder(instrumentationScopeName);
+ }
+
+ @Override
+ public MeterProvider getMeterProvider() {
+ return meterProviderImpl;
+ }
+
+ public EventLoggerProvider getEventLoggerProvider() {
+ return eventLoggerProviderImpl;
+ }
+
+ @Override
+ public Meter getMeter(String instrumentationScopeName) {
+ return meterProviderImpl.get(instrumentationScopeName);
+ }
+
+ @Override
+ public MeterBuilder meterBuilder(String instrumentationScopeName) {
+ return meterProviderImpl.meterBuilder(instrumentationScopeName);
+ }
+
+ protected OpenTelemetry getOpenTelemetryDelegate() {
+ return openTelemetryImpl;
+ }
+
+ @NonNull
+ public Resource getResource() {
+ return Preconditions.checkNotNull(resource);
+ }
+
+ @NonNull
+ public ConfigProperties getConfig() {
+ return Preconditions.checkNotNull(config);
+ }
+
+ @Override
+ public LoggerProvider getLogsBridge() {
+ return loggerProviderImpl;
+ }
+
+ @Override
+ public ContextPropagators getPropagators() {
+ return openTelemetryImpl.getPropagators();
+ }
+
+ /**
+ * For extension purpose
+ */
+ protected void postOpenTelemetrySdkConfiguration() {
+ }
+
+}
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableTracerProvider.java b/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableTracerProvider.java
new file mode 100644
index 000000000..e45274e44
--- /dev/null
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableTracerProvider.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright The Original Author or Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.jenkins.plugins.opentelemetry.opentelemetry;
+
+import com.google.common.annotations.VisibleForTesting;
+import io.opentelemetry.api.trace.SpanBuilder;
+import io.opentelemetry.api.trace.Tracer;
+import io.opentelemetry.api.trace.TracerBuilder;
+import io.opentelemetry.api.trace.TracerProvider;
+
+import javax.annotation.Nonnull;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class ReconfigurableTracerProvider implements TracerProvider {
+
+ private TracerProvider delegate;
+
+ private final ConcurrentMap tracers = new ConcurrentHashMap<>();
+
+ public ReconfigurableTracerProvider() {
+ this(TracerProvider.noop());
+ }
+
+ public ReconfigurableTracerProvider(TracerProvider delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public synchronized Tracer get(String instrumentationScopeName) {
+ return tracers.computeIfAbsent(
+ new InstrumentationScope(instrumentationScopeName),
+ instrumentationScope -> new ReconfigurableTracer(delegate.get(instrumentationScope.instrumentationScopeName)));
+ }
+
+ public synchronized void setDelegate(TracerProvider delegate) {
+ this.delegate = delegate;
+ tracers.forEach((instrumentationScope, reconfigurableTracer) -> {
+ TracerBuilder tracerBuilder = delegate.tracerBuilder(instrumentationScope.instrumentationScopeName);
+ Optional.ofNullable(instrumentationScope.instrumentationScopeVersion).ifPresent(tracerBuilder::setInstrumentationVersion);
+ Optional.ofNullable(instrumentationScope.schemaUrl).ifPresent(tracerBuilder::setSchemaUrl);
+ reconfigurableTracer.setDelegate(tracerBuilder.build());
+ });
+ }
+
+ @Override
+ public Tracer get(String instrumentationScopeName, String instrumentationScopeVersion) {
+ return tracers.computeIfAbsent(
+ new InstrumentationScope(instrumentationScopeName, null, instrumentationScopeVersion),
+ instrumentationScope -> new ReconfigurableTracer(delegate.get(instrumentationScopeName, instrumentationScopeVersion)));
+ }
+
+ @Override
+ public TracerBuilder tracerBuilder(String instrumentationScopeName) {
+ return new ReconfigurableTracerBuilder(delegate.tracerBuilder(instrumentationScopeName), instrumentationScopeName);
+ }
+
+ public synchronized TracerProvider getDelegate() {
+ return delegate;
+ }
+
+
+ @VisibleForTesting
+ protected class ReconfigurableTracerBuilder implements TracerBuilder {
+ TracerBuilder delegate;
+ String instrumentationScopeName;
+ String schemaUrl;
+ String instrumentationScopeVersion;
+
+ public ReconfigurableTracerBuilder(TracerBuilder delegate, String instrumentationScopeName) {
+ this.delegate = Objects.requireNonNull(delegate);
+ this.instrumentationScopeName = Objects.requireNonNull(instrumentationScopeName);
+ }
+
+ @Override
+ public TracerBuilder setSchemaUrl(String schemaUrl) {
+ delegate.setSchemaUrl(schemaUrl);
+ this.schemaUrl = schemaUrl;
+ return this;
+ }
+
+ @Override
+ public TracerBuilder setInstrumentationVersion(String instrumentationScopeVersion) {
+ delegate.setInstrumentationVersion(instrumentationScopeVersion);
+ this.instrumentationScopeVersion = instrumentationScopeVersion;
+ return this;
+ }
+
+ @Override
+ public Tracer build() {
+ InstrumentationScope instrumentationScope = new InstrumentationScope(instrumentationScopeName, schemaUrl, instrumentationScopeVersion);
+ return tracers.computeIfAbsent(instrumentationScope, k -> new ReconfigurableTracer(delegate.build()));
+ }
+ }
+
+ @VisibleForTesting
+ protected static class ReconfigurableTracer implements Tracer {
+ Tracer delegate;
+
+ public ReconfigurableTracer(Tracer delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public synchronized SpanBuilder spanBuilder(@Nonnull String spanName) {
+ return delegate.spanBuilder(spanName);
+ }
+
+ public synchronized void setDelegate(Tracer delegate) {
+ this.delegate = delegate;
+ }
+
+ public synchronized Tracer getDelegate() {
+ return delegate;
+ }
+ }
+
+}
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/queue/MonitoringQueueListener.java b/src/main/java/io/jenkins/plugins/opentelemetry/queue/MonitoringQueueListener.java
index 0bda6fe52..9bfc3ddc1 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/queue/MonitoringQueueListener.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/queue/MonitoringQueueListener.java
@@ -8,8 +8,8 @@
import hudson.Extension;
import hudson.model.Queue;
import hudson.model.queue.QueueListener;
-import io.jenkins.plugins.opentelemetry.OpenTelemetrySdkProvider;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.JenkinsControllerOpenTelemetry;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsSemanticMetrics;
import io.opentelemetry.api.incubator.events.EventLogger;
@@ -33,7 +33,7 @@
* Monitor the Jenkins Build queue
*/
@Extension(dynamicLoadable = YesNoMaybe.YES, optional = true)
-public class MonitoringQueueListener extends QueueListener implements OtelComponent {
+public class MonitoringQueueListener extends QueueListener implements OpenTelemetryLifecycleListener {
private final static Logger LOGGER = Logger.getLogger(MonitoringQueueListener.class.getName());
@@ -110,6 +110,6 @@ public void onEnterWaiting(Queue.WaitingItem wi) {
}
private boolean isRemoteSpanEnabled() {
- return OpenTelemetrySdkProvider.get().getConfig().getBoolean(JenkinsOtelSemanticAttributes.OTEL_INSTRUMENTATION_JENKINS_REMOTE_SPAN_ENABLED,false);
+ return JenkinsControllerOpenTelemetry.get().getConfig().getBoolean(JenkinsOtelSemanticAttributes.OTEL_INSTRUMENTATION_JENKINS_REMOTE_SPAN_ENABLED,false);
}
}
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/security/AuditingSecurityListener.java b/src/main/java/io/jenkins/plugins/opentelemetry/security/AuditingSecurityListener.java
index 8a9b4e820..601aa4e07 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/security/AuditingSecurityListener.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/security/AuditingSecurityListener.java
@@ -8,7 +8,7 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.model.User;
-import io.jenkins.plugins.opentelemetry.OtelComponent;
+import io.jenkins.plugins.opentelemetry.OpenTelemetryLifecycleListener;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsSemanticMetrics;
import io.opentelemetry.api.common.Attributes;
@@ -40,7 +40,7 @@
* within a trace.
*/
@Extension(dynamicLoadable = YesNoMaybe.YES, optional = true)
-public class AuditingSecurityListener extends SecurityListener implements OtelComponent {
+public class AuditingSecurityListener extends SecurityListener implements OpenTelemetryLifecycleListener {
private final static Logger LOGGER = Logger.getLogger(AuditingSecurityListener.class.getName());
diff --git a/src/main/java/io/jenkins/plugins/opentelemetry/servlet/TraceContextServletFilter.java b/src/main/java/io/jenkins/plugins/opentelemetry/servlet/TraceContextServletFilter.java
index 59fe3951e..7b3731ae6 100644
--- a/src/main/java/io/jenkins/plugins/opentelemetry/servlet/TraceContextServletFilter.java
+++ b/src/main/java/io/jenkins/plugins/opentelemetry/servlet/TraceContextServletFilter.java
@@ -1,7 +1,7 @@
package io.jenkins.plugins.opentelemetry.servlet;
import edu.umd.cs.findbugs.annotations.NonNull;
-import io.jenkins.plugins.opentelemetry.OpenTelemetrySdkProvider;
+import io.jenkins.plugins.opentelemetry.JenkinsControllerOpenTelemetry;
import io.jenkins.plugins.opentelemetry.OtelUtils;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes;
import io.opentelemetry.context.Context;
@@ -24,7 +24,7 @@ public class TraceContextServletFilter implements Filter {
protected static final Pattern JENKINS_TRIGGER_BUILD_URL_PATTERN = Pattern.compile("^(/[^/]+)?/job/([\\w/-]+)/build(WithParameters)?$");
- private OpenTelemetrySdkProvider openTelemetrySdkProvider;
+ private JenkinsControllerOpenTelemetry jenkinsControllerOpenTelemetry;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
@@ -37,7 +37,7 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
public void _doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
if (isW3cTraceContextPropagationEnabled() && isJenkinsRemoteBuildTriggerRequest(request)) {
- Context context = getOpenTelemetrySdkProvider()
+ Context context = getJenkinsControllerOpenTelemetry()
.getPropagators()
.getTextMapPropagator()
.extract(Context.current(), request, new OtelUtils.HttpServletRequestTextMapGetter());
@@ -57,7 +57,7 @@ private boolean isJenkinsRemoteBuildTriggerRequest(@NonNull HttpServletRequest r
}
private boolean isW3cTraceContextPropagationEnabled() {
- return getOpenTelemetrySdkProvider().getConfig()
+ return getJenkinsControllerOpenTelemetry().getConfig()
.getBoolean(JenkinsOtelSemanticAttributes.OTEL_INSTRUMENTATION_JENKINS_REMOTE_SPAN_ENABLED, false);
}
@@ -72,10 +72,10 @@ public int hashCode() {
return TraceContextServletFilter.class.hashCode();
}
- protected OpenTelemetrySdkProvider getOpenTelemetrySdkProvider() {
- if (this.openTelemetrySdkProvider == null) {
- this.openTelemetrySdkProvider = OpenTelemetrySdkProvider.get();
+ protected JenkinsControllerOpenTelemetry getJenkinsControllerOpenTelemetry() {
+ if (this.jenkinsControllerOpenTelemetry == null) {
+ this.jenkinsControllerOpenTelemetry = JenkinsControllerOpenTelemetry.get();
}
- return this.openTelemetrySdkProvider;
+ return this.jenkinsControllerOpenTelemetry;
}
}
diff --git a/src/test/java/io/jenkins/plugins/opentelemetry/BaseIntegrationTest.java b/src/test/java/io/jenkins/plugins/opentelemetry/BaseIntegrationTest.java
index 5e7d9c9d9..8e45dc6ab 100644
--- a/src/test/java/io/jenkins/plugins/opentelemetry/BaseIntegrationTest.java
+++ b/src/test/java/io/jenkins/plugins/opentelemetry/BaseIntegrationTest.java
@@ -81,7 +81,7 @@ public class BaseIntegrationTest {
@Rule
public ExtendedGitSampleRepoRule sampleRepo = new ExtendedGitSampleRepoRule();
- static OpenTelemetrySdkProvider openTelemetrySdkProvider;
+ static JenkinsControllerOpenTelemetry jenkinsControllerOpenTelemetry;
@Before
public void before() throws Exception {
@@ -101,20 +101,32 @@ public static void beforeClass() throws Exception {
jenkinsRule.waitUntilNoActivity();
LOGGER.log(Level.INFO, "Jenkins started");
- ExtensionList openTelemetrySdkProviders = jenkinsRule.getInstance().getExtensionList(OpenTelemetrySdkProvider.class);
- verify(openTelemetrySdkProviders.size() == 1, "Number of openTelemetrySdkProviders: %s", openTelemetrySdkProviders.size());
- openTelemetrySdkProvider = openTelemetrySdkProviders.get(0);
+ ExtensionList jenkinsOpenTelemetries = jenkinsRule.getInstance().getExtensionList(JenkinsControllerOpenTelemetry.class);
+ verify(jenkinsOpenTelemetries.size() == 1, "Number of jenkinsControllerOpenTelemetrys: %s", jenkinsOpenTelemetries.size());
+ jenkinsControllerOpenTelemetry = jenkinsOpenTelemetries.get(0);
- // verify(openTelemetrySdkProvider.openTelemetry == null, "OpenTelemetrySdkProvider has already been configured");
+ // verify(jenkinsControllerOpenTelemetry.openTelemetry == null, "JenkinsControllerOpenTelemetry has already been configured");
OpenTelemetryConfiguration.TESTING_INMEMORY_MODE = true;
- openTelemetrySdkProvider.initialize(new OpenTelemetryConfiguration(
- of("http://localhost:4317"), Optional.empty(),
- Optional.empty(),
- Optional.empty(), Optional.empty(),
- Optional.empty(), Optional.empty(), Optional.empty(),
- Collections.emptyMap()));
-
- // openTelemetrySdkProvider.tracer.setDelegate(openTelemetrySdkProvider.openTelemetry.getTracer("jenkins"));
+ try {
+ OpenTelemetryConfiguration configuration = new OpenTelemetryConfiguration(
+ of("http://localhost:4317"), empty(),
+ empty(),
+ empty(), empty(),
+ empty(), empty(), empty(),
+ Collections.emptyMap());
+
+ LOGGER.log(Level.INFO, "Initialize OTel with configuration " + configuration.toOpenTelemetryProperties());
+ jenkinsControllerOpenTelemetry.initialize(configuration);
+ } catch (RuntimeException e) {
+ LOGGER.log(Level.INFO, "Exception initializing OTel plugin", e);
+ throw e;
+ } catch (Error e) {
+ LOGGER.log(Level.INFO, "Error initializing OTel plugin", e);
+ throw e;
+ }
+ LOGGER.log(Level.INFO, "OTel plugin initialized");
+
+ // jenkinsControllerOpenTelemetry.tracer.setDelegate(jenkinsControllerOpenTelemetry.openTelemetry.getTracer("jenkins"));
}
protected void checkChainOfSpans(Tree spanTree, String... expectedSpanNames) {
@@ -168,7 +180,7 @@ protected Tree getGeneratedSpans() {
}
protected Tree getGeneratedSpans(int index) {
- CompletableResultCode completableResultCode = openTelemetrySdkProvider.getOpenTelemetrySdk().getSdkTracerProvider().forceFlush();
+ CompletableResultCode completableResultCode = jenkinsControllerOpenTelemetry.getOpenTelemetrySdk().getSdkTracerProvider().forceFlush();
completableResultCode.join(1, TimeUnit.SECONDS);
List spans = InMemorySpanExporterProvider.LAST_CREATED_INSTANCE.getFinishedSpanItems();
diff --git a/src/test/java/io/jenkins/plugins/opentelemetry/OpenTelemetrySdkProviderTest.java b/src/test/java/io/jenkins/plugins/opentelemetry/JenkinsControllerOpenTelemetryTest.java
similarity index 91%
rename from src/test/java/io/jenkins/plugins/opentelemetry/OpenTelemetrySdkProviderTest.java
rename to src/test/java/io/jenkins/plugins/opentelemetry/JenkinsControllerOpenTelemetryTest.java
index ce5517bc7..1d61a3f3d 100644
--- a/src/test/java/io/jenkins/plugins/opentelemetry/OpenTelemetrySdkProviderTest.java
+++ b/src/test/java/io/jenkins/plugins/opentelemetry/JenkinsControllerOpenTelemetryTest.java
@@ -17,7 +17,7 @@
import java.util.Map;
import java.util.Optional;
-public class OpenTelemetrySdkProviderTest {
+public class JenkinsControllerOpenTelemetryTest {
@Test
public void testOverwriteDefaultConfig() {
@@ -56,10 +56,10 @@ private void testDefaultConfigurationOverwrite(String serviceNameDefinedInConfig
Optional.empty(),
configurationProperties);
- OpenTelemetrySdkProvider openTelemetrySdkProvider = new OpenTelemetrySdkProvider();
- openTelemetrySdkProvider.initialize(openTelemetryConfiguration);
+ JenkinsControllerOpenTelemetry jenkinsControllerOpenTelemetry = new JenkinsControllerOpenTelemetry();
+ jenkinsControllerOpenTelemetry.initialize(openTelemetryConfiguration);
- Resource resource = openTelemetrySdkProvider.getResource();
+ Resource resource = jenkinsControllerOpenTelemetry.getResource();
// resource.getAttributes().forEach((key, value)-> System.out.println(key + ": " + value));
MatcherAssert.assertThat(
@@ -85,6 +85,6 @@ private void testDefaultConfigurationOverwrite(String serviceNameDefinedInConfig
CoreMatchers.is("1.2.3"));
- openTelemetrySdkProvider.shutdown();
+ jenkinsControllerOpenTelemetry.shutdown();
}
}
diff --git a/src/test/java/io/jenkins/plugins/opentelemetry/JenkinsOtelPluginIntegrationTest.java b/src/test/java/io/jenkins/plugins/opentelemetry/JenkinsOtelPluginIntegrationTest.java
index cb132f967..e4d65748d 100644
--- a/src/test/java/io/jenkins/plugins/opentelemetry/JenkinsOtelPluginIntegrationTest.java
+++ b/src/test/java/io/jenkins/plugins/opentelemetry/JenkinsOtelPluginIntegrationTest.java
@@ -83,7 +83,7 @@ public void testSimplePipeline() throws Exception {
// FIXME REPAIR METRICS TESTS
/*
// WORKAROUND because we don't know how to force the IntervalMetricReader to collect metrics
- openTelemetrySdkProvider.getOpenTelemetrySdk().getSdkMeterProvider().forceFlush();
+ jenkinsControllerOpenTelemetry.getOpenTelemetrySdk().getSdkMeterProvider().forceFlush();
Map exportedMetrics = InMemoryMetricExporterUtils.getLastExportedMetricByMetricName(InMemoryMetricExporterProvider.LAST_CREATED_INSTANCE.getFinishedMetricItems());
dumpMetrics(exportedMetrics);
MetricData runStartedCounterData = exportedMetrics.get(JenkinsSemanticMetrics.CI_PIPELINE_RUN_STARTED);
@@ -105,7 +105,7 @@ public void testMetricsWithDiskUsagePlugin() throws Exception {
Thread.sleep(100); // FIXME
LOGGER.log(Level.INFO, "slept");
- openTelemetrySdkProvider.getOpenTelemetrySdk().getSdkMeterProvider().forceFlush();
+ jenkinsControllerOpenTelemetry.getOpenTelemetrySdk().getSdkMeterProvider().forceFlush();
LOGGER.log(Level.INFO, "InMemoryMetricExporterProvider.LAST_CREATED_INSTANCE: " + InMemoryMetricExporterProvider.LAST_CREATED_INSTANCE);
Map exportedMetrics = InMemoryMetricExporterUtils.getLastExportedMetricByMetricName(InMemoryMetricExporterProvider.LAST_CREATED_INSTANCE.getFinishedMetricItems());
diff --git a/src/test/java/io/jenkins/plugins/opentelemetry/job/log/OtelLocaLogMirroringTest.java b/src/test/java/io/jenkins/plugins/opentelemetry/job/log/OtelLocaLogMirroringTest.java
index f66ed1d60..b07abc93e 100644
--- a/src/test/java/io/jenkins/plugins/opentelemetry/job/log/OtelLocaLogMirroringTest.java
+++ b/src/test/java/io/jenkins/plugins/opentelemetry/job/log/OtelLocaLogMirroringTest.java
@@ -3,7 +3,7 @@
import hudson.ExtensionList;
import hudson.model.Result;
import io.jenkins.plugins.opentelemetry.OpenTelemetryConfiguration;
-import io.jenkins.plugins.opentelemetry.OpenTelemetrySdkProvider;
+import io.jenkins.plugins.opentelemetry.JenkinsControllerOpenTelemetry;
import io.jenkins.plugins.opentelemetry.job.OtelTraceService;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.sdk.testing.exporter.InMemoryMetricExporterProvider;
@@ -36,7 +36,7 @@ public class OtelLocaLogMirroringTest {
@ClassRule
public static JenkinsRule jenkinsRule = new JenkinsRule();
- static OpenTelemetrySdkProvider openTelemetrySdkProvider;
+ static JenkinsControllerOpenTelemetry jenkinsControllerOpenTelemetry;
static WorkflowJob pipeline;
@@ -52,15 +52,15 @@ public static void beforeClass() throws Exception {
OpenTelemetryConfiguration.TESTING_INMEMORY_MODE = true;
OtelTraceService.STRICT_MODE = true;
- ExtensionList openTelemetrySdkProviders = jenkinsRule.getInstance().getExtensionList(OpenTelemetrySdkProvider.class);
- verify(openTelemetrySdkProviders.size() == 1, "Number of openTelemetrySdkProviders: %s", openTelemetrySdkProviders.size());
+ ExtensionList jenkinsOpenTelemetries = jenkinsRule.getInstance().getExtensionList(JenkinsControllerOpenTelemetry.class);
+ verify(jenkinsOpenTelemetries.size() == 1, "Number of jenkinsControllerOpenTelemetrys: %s", jenkinsOpenTelemetries.size());
- openTelemetrySdkProvider = openTelemetrySdkProviders.get(0);
- openTelemetrySdkProvider.initialize(new OpenTelemetryConfiguration(of("http://localhost:4317"), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Collections.emptyMap()));
+ jenkinsControllerOpenTelemetry = jenkinsOpenTelemetries.get(0);
+ jenkinsControllerOpenTelemetry.initialize(new OpenTelemetryConfiguration(of("http://localhost:4317"), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Collections.emptyMap()));
}
@AfterClass
public static void afterClass() {
- openTelemetrySdkProvider.shutdown();
+ jenkinsControllerOpenTelemetry.shutdown();
GlobalOpenTelemetry.resetForTest();
}
@@ -96,7 +96,7 @@ private WorkflowRun runBuild() throws Exception {
}
private void reInitProvider(Map configuration) {
- openTelemetrySdkProvider.initialize(new OpenTelemetryConfiguration(of("http://localhost:4317"), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), configuration));
+ jenkinsControllerOpenTelemetry.initialize(new OpenTelemetryConfiguration(of("http://localhost:4317"), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), configuration));
}
diff --git a/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/CloseableMeterProviderTest.java b/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/CloseableMeterProviderTest.java
new file mode 100644
index 000000000..acd3abac3
--- /dev/null
+++ b/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/CloseableMeterProviderTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright The Original Author or Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.jenkins.plugins.opentelemetry.opentelemetry;
+
+import io.opentelemetry.api.metrics.*;
+import org.junit.Test;
+
+import static org.hamcrest.MatcherAssert.*;
+import static org.hamcrest.Matchers.*;
+
+public class CloseableMeterProviderTest {
+
+
+ @Test
+ public void test() {
+ CloseableMeterProvider meterProvider = new CloseableMeterProvider(MeterProvider.noop());
+ testMeterMetricsWithCallback(meterProvider.get("test-meter-1"), meterProvider);
+
+ testMeterMetricsWithCallback(meterProvider.meterBuilder("test-meter").setSchemaUrl("https://example.com").setInstrumentationVersion("123").build(), meterProvider);
+
+ System.out.println("number of closeable meters: " + meterProvider.closeables.size());
+
+ meterProvider.close();
+
+ }
+
+ private static void testMeterMetricsWithCallback(Meter meter, CloseableMeterProvider closeableMeterProvider) {
+ assertThat(meter, instanceOf(CloseableMeterProvider.CloseableMeter.class));
+
+ int before = closeableMeterProvider.closeables.size();
+ ObservableLongCounter observableLongCounter = meter.counterBuilder("test-counter").setDescription("desc").setUnit("s").buildWithCallback(om -> om.record(1L));
+ int after = closeableMeterProvider.closeables.size();
+ assertThat(after, is(before + 1));
+
+ before = closeableMeterProvider.closeables.size();
+ meter.gaugeBuilder("test-double-gauge").setDescription("desc").setUnit("ms").buildWithCallback(om -> om.record(1.0));
+ after = closeableMeterProvider.closeables.size();
+ assertThat(after, is(before + 1));
+
+ before = closeableMeterProvider.closeables.size();
+ meter.gaugeBuilder("test-long-gauge").ofLongs().setDescription("desc").setUnit("ms").buildWithCallback(om -> om.record(1L));
+ after = closeableMeterProvider.closeables.size();
+ assertThat(after, is(before + 1));
+
+ before = closeableMeterProvider.closeables.size();
+ meter.upDownCounterBuilder("test-up-down-counter").setDescription("desc").setUnit("ms").buildWithCallback(om -> om.record(1L));
+ after = closeableMeterProvider.closeables.size();
+ assertThat(after, is(before + 1));
+
+ before = closeableMeterProvider.closeables.size();
+ meter.upDownCounterBuilder("test-double-up-down-counter").ofDoubles().setDescription("desc").setUnit("ms").buildWithCallback(om -> om.record(1.0));
+ after = closeableMeterProvider.closeables.size();
+ assertThat(after, is(before + 1));
+
+ before = closeableMeterProvider.closeables.size();
+ final ObservableDoubleMeasurement observableDoubleMeasurement = meter.gaugeBuilder("another-gauge").setUnit("1").setDescription("desc").buildObserver();
+ after = closeableMeterProvider.closeables.size();
+ assertThat(after, is(before));
+ meter.batchCallback(() -> observableDoubleMeasurement.record(1), observableDoubleMeasurement);
+ after = closeableMeterProvider.closeables.size();
+ assertThat(after, is(before + 1));
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/ClosingOpenTelemetryTest.java b/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/ClosingOpenTelemetryTest.java
deleted file mode 100644
index f755ce498..000000000
--- a/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/ClosingOpenTelemetryTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright The Original Author or Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.jenkins.plugins.opentelemetry.opentelemetry;
-
-import io.opentelemetry.api.OpenTelemetry;
-import io.opentelemetry.api.metrics.*;
-import org.junit.Test;
-
-import static org.hamcrest.MatcherAssert.*;
-import static org.hamcrest.Matchers.*;
-
-public class ClosingOpenTelemetryTest {
-
-
- @Test
- public void test() {
- ClosingOpenTelemetry closingOpenTelemetry = new ClosingOpenTelemetry(OpenTelemetry.noop());
-
- testMeterProvider(closingOpenTelemetry.getMeterProvider(), closingOpenTelemetry);
- testMeter(closingOpenTelemetry.getMeter("test"), closingOpenTelemetry);
-
- Meter meter = closingOpenTelemetry.meterBuilder("test-meter").setSchemaUrl("https://example.com").setInstrumentationVersion("123").build();
- testMeter(meter, closingOpenTelemetry);
-
- System.out.println("number of tests: " + closingOpenTelemetry.closeables.size());
-
- }
-
- private static void testMeterProvider(MeterProvider meterProvider, ClosingOpenTelemetry closingOpenTelemetry) {
- assertThat(meterProvider, instanceOf(ClosingOpenTelemetry.ClosingMeterProvider.class));
-
-
- MeterBuilder meterBuilder = meterProvider.meterBuilder("test");
-
- assertThat(meterBuilder, instanceOf(ClosingOpenTelemetry.ClosingMeterBuilder.class));
-
- testMeter(meterBuilder.setInstrumentationVersion("123").setSchemaUrl("https://example.com").build(), closingOpenTelemetry);
-
- testMeter(meterProvider.get("test"), closingOpenTelemetry);
- }
-
- private static void testMeter(Meter meter, ClosingOpenTelemetry closingOpenTelemetry) {
- assertThat(meter, instanceOf(ClosingOpenTelemetry.ClosingMeter.class));
-
- int before = closingOpenTelemetry.closeables.size();
- meter.counterBuilder("test-counter").setDescription("desc").setUnit("s").buildWithCallback(om -> om.record(1L));
- int after = closingOpenTelemetry.closeables.size();
- assertThat(after, is(before + 1));
-
- before = closingOpenTelemetry.closeables.size();
- meter.gaugeBuilder("test-double-gauge").setDescription("desc").setUnit("ms").buildWithCallback(om -> om.record(1.0));
- after = closingOpenTelemetry.closeables.size();
- assertThat(after, is(before + 1));
-
- before = closingOpenTelemetry.closeables.size();
- meter.gaugeBuilder("test-long-gauge").ofLongs().setDescription("desc").setUnit("ms").buildWithCallback(om -> om.record(1L));
- after = closingOpenTelemetry.closeables.size();
- assertThat(after, is(before + 1));
-
- before = closingOpenTelemetry.closeables.size();
- meter.upDownCounterBuilder("test-up-down-counter").setDescription("desc").setUnit("ms").buildWithCallback(om -> om.record(1L));
- after = closingOpenTelemetry.closeables.size();
- assertThat(after, is(before + 1));
-
- before = closingOpenTelemetry.closeables.size();
- meter.upDownCounterBuilder("test-double-up-down-counter").ofDoubles().setDescription("desc").setUnit("ms").buildWithCallback(om -> om.record(1.0));
- after = closingOpenTelemetry.closeables.size();
- assertThat(after, is(before + 1));
-
- before = closingOpenTelemetry.closeables.size();
- final ObservableDoubleMeasurement observableDoubleMeasurement = meter.gaugeBuilder("another-gauge").setUnit("1").setDescription("desc").buildObserver();
- after = closingOpenTelemetry.closeables.size();
- assertThat(after, is(before));
- meter.batchCallback(() -> observableDoubleMeasurement.record(1), observableDoubleMeasurement);
- after = closingOpenTelemetry.closeables.size();
- assertThat(after, is(before+1));
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableEventLoggerProviderTest.java b/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableEventLoggerProviderTest.java
new file mode 100644
index 000000000..e04720e03
--- /dev/null
+++ b/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableEventLoggerProviderTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright The Original Author or Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.jenkins.plugins.opentelemetry.opentelemetry;
+
+import io.opentelemetry.api.incubator.events.EventBuilder;
+import io.opentelemetry.api.incubator.events.EventLogger;
+import io.opentelemetry.api.incubator.events.EventLoggerBuilder;
+import io.opentelemetry.api.incubator.events.EventLoggerProvider;
+
+import javax.annotation.Nullable;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.junit.Assert.*;
+
+public class ReconfigurableEventLoggerProviderTest {
+
+ @org.junit.Test
+ public void testEventLoggerBuilder() {
+ ReconfigurableEventLoggerProvider eventLoggerProvider = new ReconfigurableEventLoggerProvider();
+
+ EventLoggerProviderMock eventLoggerProviderImpl_1 = new EventLoggerProviderMock();
+ eventLoggerProvider.setDelegate(eventLoggerProviderImpl_1);
+
+ ReconfigurableEventLoggerProvider.ReconfigurableEventLogger authenticationEventLogger = (ReconfigurableEventLoggerProvider.ReconfigurableEventLogger) eventLoggerProvider
+ .eventLoggerBuilder("io.jenkins.authentication")
+ .setInstrumentationVersion("1.0.0")
+ .build();
+
+ EventLoggerMock authenticationEventLoggerImpl = (EventLoggerMock) authenticationEventLogger.delegateEventLogger;
+ assertEquals("io.jenkins.authentication", authenticationEventLoggerImpl.instrumentationScopeName);
+ assertNull(authenticationEventLoggerImpl.schemaUrl);
+ assertEquals("1.0.0", authenticationEventLoggerImpl.instrumentationVersion);
+ assertEquals(eventLoggerProviderImpl_1.id, authenticationEventLoggerImpl.eventLoggerProviderId);
+
+
+ ReconfigurableEventLoggerProvider.ReconfigurableEventLogger buildEventLogger = (ReconfigurableEventLoggerProvider.ReconfigurableEventLogger) eventLoggerProvider
+ .eventLoggerBuilder("io.jenkins.build")
+ .setSchemaUrl("https://jenkins.io/build")
+ .build();
+ EventLoggerMock buildEventLoggerImpl = (EventLoggerMock) buildEventLogger.delegateEventLogger;
+ assertEquals("io.jenkins.build", buildEventLoggerImpl.instrumentationScopeName);
+ assertEquals("https://jenkins.io/build", buildEventLoggerImpl.schemaUrl);
+ assertNull(buildEventLoggerImpl.instrumentationVersion);
+ assertEquals(eventLoggerProviderImpl_1.id, buildEventLoggerImpl.eventLoggerProviderId);
+
+ ReconfigurableEventLoggerProvider.ReconfigurableEventLogger buildEventLoggerShouldBeTheSameInstance = (ReconfigurableEventLoggerProvider.ReconfigurableEventLogger) eventLoggerProvider
+ .eventLoggerBuilder("io.jenkins.build")
+ .setSchemaUrl("https://jenkins.io/build")
+ .build();
+
+ assertEquals(buildEventLogger, buildEventLoggerShouldBeTheSameInstance);
+
+ EventLoggerProviderMock eventLoggerProviderImpl_2 = new EventLoggerProviderMock();
+ assertNotEquals(eventLoggerProviderImpl_1.id, eventLoggerProviderImpl_2.id);
+
+ // CHANGE THE IMPLEMENTATION OF THE EVENT LOGGER PROVIDER
+ eventLoggerProvider.setDelegate(eventLoggerProviderImpl_2);
+
+ // VERIFY THE DELEGATE IMPL HAS CHANGED WHILE THE PARAMS REMAINS UNCHANGED
+ EventLoggerMock authenticationEventLoggerImpl_2 = (EventLoggerMock) authenticationEventLogger.delegateEventLogger;
+ assertEquals("io.jenkins.authentication", authenticationEventLoggerImpl_2.instrumentationScopeName);
+ assertNull(authenticationEventLoggerImpl_2.schemaUrl);
+ assertEquals("1.0.0", authenticationEventLoggerImpl_2.instrumentationVersion);
+ assertEquals(eventLoggerProviderImpl_2.id, authenticationEventLoggerImpl_2.eventLoggerProviderId);
+
+ EventLoggerMock buildEventLoggerImpl_2 = (EventLoggerMock) buildEventLogger.delegateEventLogger;
+
+ assertEquals("io.jenkins.build", buildEventLoggerImpl_2.instrumentationScopeName);
+ assertEquals("https://jenkins.io/build", buildEventLoggerImpl_2.schemaUrl);
+ assertNull(buildEventLoggerImpl_2.instrumentationVersion);
+ assertEquals(eventLoggerProviderImpl_2.id, buildEventLoggerImpl_2.eventLoggerProviderId);
+ }
+
+
+ static class EventLoggerProviderMock implements EventLoggerProvider {
+ static AtomicInteger ID_SOURCE = new AtomicInteger(0);
+ final String id;
+
+ public EventLoggerProviderMock() {
+ this.id = "EventLoggerProviderMock-" + ID_SOURCE.incrementAndGet();
+ }
+
+ @Override
+ public EventLoggerBuilder eventLoggerBuilder(String instrumentationScopeName) {
+ return new EventLoggerBuilderMock(instrumentationScopeName, id);
+ }
+
+ @Override
+ public EventLogger get(String instrumentationScopeName) {
+ return new EventLoggerMock(instrumentationScopeName, id);
+ }
+ }
+
+ static class EventLoggerMock implements EventLogger {
+ static AtomicInteger ID_SOURCE = new AtomicInteger(0);
+
+ final String instrumentationScopeName;
+ final String eventLoggerProviderId;
+ final String id;
+
+ final String schemaUrl;
+ final String instrumentationVersion;
+
+ public EventLoggerMock(String instrumentationScopeName, String eventLoggerProviderId) {
+ this(instrumentationScopeName, eventLoggerProviderId, null, null);
+ }
+ public EventLoggerMock(String instrumentationScopeName, String eventLoggerProviderId, @Nullable String schemaUrl, @Nullable String instrumentationVersion) {
+ this.id = "EventLoggerMock-" + ID_SOURCE.incrementAndGet();
+ this.instrumentationScopeName = instrumentationScopeName;
+ this.eventLoggerProviderId = eventLoggerProviderId;
+ this.schemaUrl = schemaUrl;
+ this.instrumentationVersion = instrumentationVersion;
+ }
+
+ @Override
+ public EventBuilder builder(String eventName) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ static class EventLoggerBuilderMock implements EventLoggerBuilder {
+ static AtomicInteger ID_SOURCE = new AtomicInteger(0);
+ final String id;
+ final String instrumentationScopeName;
+ final String eventLoggerProviderId;
+ String schemaUrl;
+ String instrumentationVersion;
+
+
+ public EventLoggerBuilderMock(String instrumentationScopeName, String eventLoggerProviderId) {
+ this.id = "EventLoggerBuilderMock-" + ID_SOURCE.incrementAndGet();
+ this.instrumentationScopeName = instrumentationScopeName;
+ this.eventLoggerProviderId = eventLoggerProviderId;
+ }
+
+ @Override
+ public EventLoggerBuilder setSchemaUrl(String schemaUrl) {
+ this.schemaUrl = schemaUrl;
+ return this;
+ }
+
+ @Override
+ public EventLoggerBuilder setInstrumentationVersion(String instrumentationVersion) {
+ this.instrumentationVersion = instrumentationVersion;
+ return this;
+ }
+
+ @Override
+ public EventLogger build() {
+ return new EventLoggerMock(instrumentationScopeName, eventLoggerProviderId, schemaUrl, instrumentationVersion);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableLoggerProviderTest.java b/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableLoggerProviderTest.java
new file mode 100644
index 000000000..7920ff5cf
--- /dev/null
+++ b/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableLoggerProviderTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright The Original Author or Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.jenkins.plugins.opentelemetry.opentelemetry;
+
+
+import io.opentelemetry.api.logs.LogRecordBuilder;
+import io.opentelemetry.api.logs.Logger;
+import io.opentelemetry.api.logs.LoggerBuilder;
+import io.opentelemetry.api.logs.LoggerProvider;
+
+import javax.annotation.Nullable;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.junit.Assert.*;
+
+public class ReconfigurableLoggerProviderTest {
+
+ @org.junit.Test
+ public void testLoggerBuilder() {
+ ReconfigurableLoggerProvider loggerProvider = new ReconfigurableLoggerProvider();
+
+ ReconfigurableLoggerProviderTest.LoggerProviderMock loggerProviderImpl_1 = new ReconfigurableLoggerProviderTest.LoggerProviderMock();
+ loggerProvider.setDelegate(loggerProviderImpl_1);
+
+ ReconfigurableLoggerProvider.ReconfigurableLogger authenticationLogger = (ReconfigurableLoggerProvider.ReconfigurableLogger) loggerProvider
+ .loggerBuilder("io.jenkins.authentication")
+ .setInstrumentationVersion("1.0.0")
+ .build();
+
+ ReconfigurableLoggerProviderTest.LoggerMock authenticationLoggerImpl = (ReconfigurableLoggerProviderTest.LoggerMock) authenticationLogger.delegate;
+ assertEquals("io.jenkins.authentication", authenticationLoggerImpl.instrumentationScopeName);
+ assertNull(authenticationLoggerImpl.schemaUrl);
+ assertEquals("1.0.0", authenticationLoggerImpl.instrumentationVersion);
+ assertEquals(loggerProviderImpl_1.id, authenticationLoggerImpl.loggerProviderId);
+
+
+ ReconfigurableLoggerProvider.ReconfigurableLogger buildLogger = (ReconfigurableLoggerProvider.ReconfigurableLogger) loggerProvider
+ .loggerBuilder("io.jenkins.build")
+ .setSchemaUrl("https://jenkins.io/build")
+ .build();
+ ReconfigurableLoggerProviderTest.LoggerMock buildLoggerImpl = (ReconfigurableLoggerProviderTest.LoggerMock) buildLogger.delegate;
+ assertEquals("io.jenkins.build", buildLoggerImpl.instrumentationScopeName);
+ assertEquals("https://jenkins.io/build", buildLoggerImpl.schemaUrl);
+ assertNull(buildLoggerImpl.instrumentationVersion);
+ assertEquals(loggerProviderImpl_1.id, buildLoggerImpl.loggerProviderId);
+
+ ReconfigurableLoggerProvider.ReconfigurableLogger buildLoggerShouldBeTheSameInstance = (ReconfigurableLoggerProvider.ReconfigurableLogger) loggerProvider
+ .loggerBuilder("io.jenkins.build")
+ .setSchemaUrl("https://jenkins.io/build")
+ .build();
+
+ assertEquals(buildLogger, buildLoggerShouldBeTheSameInstance);
+
+ ReconfigurableLoggerProviderTest.LoggerProviderMock loggerProviderImpl_2 = new ReconfigurableLoggerProviderTest.LoggerProviderMock();
+ assertNotEquals(loggerProviderImpl_1.id, loggerProviderImpl_2.id);
+
+ // CHANGE THE IMPLEMENTATION OF THE EVENT LOGGER PROVIDER
+ loggerProvider.setDelegate(loggerProviderImpl_2);
+
+ // VERIFY THE DELEGATE IMPL HAS CHANGED WHILE THE PARAMS REMAINS UNCHANGED
+ ReconfigurableLoggerProviderTest.LoggerMock authenticationLoggerImpl_2 = (ReconfigurableLoggerProviderTest.LoggerMock) authenticationLogger.delegate;
+ assertEquals("io.jenkins.authentication", authenticationLoggerImpl_2.instrumentationScopeName);
+ assertNull(authenticationLoggerImpl_2.schemaUrl);
+ assertEquals("1.0.0", authenticationLoggerImpl_2.instrumentationVersion);
+ assertEquals(loggerProviderImpl_2.id, authenticationLoggerImpl_2.loggerProviderId);
+
+ ReconfigurableLoggerProviderTest.LoggerMock buildLoggerImpl_2 = (ReconfigurableLoggerProviderTest.LoggerMock) buildLogger.delegate;
+
+ assertEquals("io.jenkins.build", buildLoggerImpl_2.instrumentationScopeName);
+ assertEquals("https://jenkins.io/build", buildLoggerImpl_2.schemaUrl);
+ assertNull(buildLoggerImpl_2.instrumentationVersion);
+ assertEquals(loggerProviderImpl_2.id, buildLoggerImpl_2.loggerProviderId);
+ }
+
+
+ static class LoggerProviderMock implements LoggerProvider {
+ static AtomicInteger ID_SOURCE = new AtomicInteger(0);
+ final String id;
+
+ public LoggerProviderMock() {
+ this.id = "LoggerProviderMock-" + ID_SOURCE.incrementAndGet();
+ }
+
+ @Override
+ public LoggerBuilder loggerBuilder(String instrumentationScopeName) {
+ return new ReconfigurableLoggerProviderTest.LoggerBuilderMock(instrumentationScopeName, id);
+ }
+
+ @Override
+ public Logger get(String instrumentationScopeName) {
+ return new ReconfigurableLoggerProviderTest.LoggerMock(instrumentationScopeName, id);
+ }
+ }
+
+ static class LoggerMock implements Logger {
+ static AtomicInteger ID_SOURCE = new AtomicInteger(0);
+
+ final String instrumentationScopeName;
+ final String loggerProviderId;
+ final String id;
+
+ final String schemaUrl;
+ final String instrumentationVersion;
+
+ public LoggerMock(String instrumentationScopeName, String loggerProviderId) {
+ this(instrumentationScopeName, loggerProviderId, null, null);
+ }
+ public LoggerMock(String instrumentationScopeName, String loggerProviderId, @Nullable String schemaUrl, @Nullable String instrumentationVersion) {
+ this.id = "LoggerMock-" + ID_SOURCE.incrementAndGet();
+ this.instrumentationScopeName = instrumentationScopeName;
+ this.loggerProviderId = loggerProviderId;
+ this.schemaUrl = schemaUrl;
+ this.instrumentationVersion = instrumentationVersion;
+ }
+
+ @Override
+ public LogRecordBuilder logRecordBuilder() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ static class LoggerBuilderMock implements LoggerBuilder {
+ static AtomicInteger ID_SOURCE = new AtomicInteger(0);
+ final String id;
+ final String instrumentationScopeName;
+ final String loggerProviderId;
+ String schemaUrl;
+ String instrumentationVersion;
+
+
+ public LoggerBuilderMock(String instrumentationScopeName, String loggerProviderId) {
+ this.id = "LoggerBuilderMock-" + ID_SOURCE.incrementAndGet();
+ this.instrumentationScopeName = instrumentationScopeName;
+ this.loggerProviderId = loggerProviderId;
+ }
+
+ @Override
+ public LoggerBuilder setSchemaUrl(String schemaUrl) {
+ this.schemaUrl = schemaUrl;
+ return this;
+ }
+
+ @Override
+ public LoggerBuilder setInstrumentationVersion(String instrumentationVersion) {
+ this.instrumentationVersion = instrumentationVersion;
+ return this;
+ }
+
+ @Override
+ public Logger build() {
+ return new ReconfigurableLoggerProviderTest.LoggerMock(instrumentationScopeName, loggerProviderId, schemaUrl, instrumentationVersion);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableTracerProviderTest.java b/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableTracerProviderTest.java
new file mode 100644
index 000000000..b8c257464
--- /dev/null
+++ b/src/test/java/io/jenkins/plugins/opentelemetry/opentelemetry/ReconfigurableTracerProviderTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright The Original Author or Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.jenkins.plugins.opentelemetry.opentelemetry;
+
+import io.opentelemetry.api.trace.SpanBuilder;
+import io.opentelemetry.api.trace.Tracer;
+import io.opentelemetry.api.trace.TracerBuilder;
+import io.opentelemetry.api.trace.TracerProvider;
+
+import javax.annotation.Nullable;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.junit.Assert.*;
+
+public class ReconfigurableTracerProviderTest {
+ @org.junit.Test
+ public void test() {
+ ReconfigurableTracerProvider tracerProvider = new ReconfigurableTracerProvider();
+
+ ReconfigurableTracerProviderTest.TracerProviderMock tracerProviderImpl_1 = new ReconfigurableTracerProviderTest.TracerProviderMock();
+ tracerProvider.setDelegate(tracerProviderImpl_1);
+
+ ReconfigurableTracerProvider.ReconfigurableTracer authenticationTracer = (ReconfigurableTracerProvider.ReconfigurableTracer) tracerProvider
+ .tracerBuilder("io.jenkins.authentication")
+ .setInstrumentationVersion("1.0.0")
+ .build();
+
+ ReconfigurableTracerProviderTest.TracerMock authenticationTracerImpl = (ReconfigurableTracerProviderTest.TracerMock) authenticationTracer.delegate;
+ assertEquals("io.jenkins.authentication", authenticationTracerImpl.instrumentationScopeName);
+ assertNull(authenticationTracerImpl.schemaUrl);
+ assertEquals("1.0.0", authenticationTracerImpl.instrumentationVersion);
+ assertEquals(tracerProviderImpl_1.id, authenticationTracerImpl.tracerProviderId);
+
+
+ ReconfigurableTracerProvider.ReconfigurableTracer buildTracer = (ReconfigurableTracerProvider.ReconfigurableTracer) tracerProvider
+ .tracerBuilder("io.jenkins.build")
+ .setSchemaUrl("https://jenkins.io/build")
+ .build();
+ ReconfigurableTracerProviderTest.TracerMock buildTracerImpl = (ReconfigurableTracerProviderTest.TracerMock) buildTracer.delegate;
+ assertEquals("io.jenkins.build", buildTracerImpl.instrumentationScopeName);
+ assertEquals("https://jenkins.io/build", buildTracerImpl.schemaUrl);
+ assertNull(buildTracerImpl.instrumentationVersion);
+ assertEquals(tracerProviderImpl_1.id, buildTracerImpl.tracerProviderId);
+
+ ReconfigurableTracerProvider.ReconfigurableTracer buildTracerShouldBeTheSameInstance = (ReconfigurableTracerProvider.ReconfigurableTracer) tracerProvider
+ .tracerBuilder("io.jenkins.build")
+ .setSchemaUrl("https://jenkins.io/build")
+ .build();
+
+ assertEquals(buildTracer, buildTracerShouldBeTheSameInstance);
+
+ ReconfigurableTracerProviderTest.TracerProviderMock tracerProviderImpl_2 = new ReconfigurableTracerProviderTest.TracerProviderMock();
+ assertNotEquals(tracerProviderImpl_1.id, tracerProviderImpl_2.id);
+
+ // CHANGE THE IMPLEMENTATION OF THE EVENT TRACER PROVIDER
+ tracerProvider.setDelegate(tracerProviderImpl_2);
+
+ // VERIFY THE DELEGATE IMPL HAS CHANGED WHILE THE PARAMS REMAINS UNCHANGED
+ ReconfigurableTracerProviderTest.TracerMock authenticationTracerImpl_2 = (ReconfigurableTracerProviderTest.TracerMock) authenticationTracer.delegate;
+ assertEquals("io.jenkins.authentication", authenticationTracerImpl_2.instrumentationScopeName);
+ assertNull(authenticationTracerImpl_2.schemaUrl);
+ assertEquals("1.0.0", authenticationTracerImpl_2.instrumentationVersion);
+ assertEquals(tracerProviderImpl_2.id, authenticationTracerImpl_2.tracerProviderId);
+
+ ReconfigurableTracerProviderTest.TracerMock buildTracerImpl_2 = (ReconfigurableTracerProviderTest.TracerMock) buildTracer.delegate;
+
+ assertEquals("io.jenkins.build", buildTracerImpl_2.instrumentationScopeName);
+ assertEquals("https://jenkins.io/build", buildTracerImpl_2.schemaUrl);
+ assertNull(buildTracerImpl_2.instrumentationVersion);
+ assertEquals(tracerProviderImpl_2.id, buildTracerImpl_2.tracerProviderId);
+ }
+
+
+ static class TracerProviderMock implements TracerProvider {
+ static AtomicInteger ID_SOURCE = new AtomicInteger(0);
+ final String id;
+
+ public TracerProviderMock() {
+ this.id = "TracerProviderMock-" + ID_SOURCE.incrementAndGet();
+ }
+
+ @Override
+ public TracerBuilder tracerBuilder(String instrumentationScopeName) {
+ return new ReconfigurableTracerProviderTest.TracerBuilderMock(instrumentationScopeName, id);
+ }
+
+ @Override
+ public Tracer get(String instrumentationScopeName) {
+ return new ReconfigurableTracerProviderTest.TracerMock(instrumentationScopeName, id);
+ }
+
+ @Override
+ public Tracer get(String instrumentationScopeName, String instrumentationScopeVersion) {
+ return new ReconfigurableTracerProviderTest.TracerMock(instrumentationScopeName, instrumentationScopeVersion, id);
+ }
+ }
+
+ static class TracerMock implements Tracer {
+ static AtomicInteger ID_SOURCE = new AtomicInteger(0);
+
+ final String instrumentationScopeName;
+ final String tracerProviderId;
+ final String id;
+
+ final String schemaUrl;
+ final String instrumentationVersion;
+
+ public TracerMock(String instrumentationScopeName, String tracerProviderId) {
+ this(instrumentationScopeName, tracerProviderId, null, null);
+ }
+ public TracerMock(String instrumentationScopeName, String instrumentationVersion, String tracerProviderId) {
+ this(instrumentationScopeName, tracerProviderId, null, instrumentationVersion);
+ }
+
+ public TracerMock(String instrumentationScopeName, String tracerProviderId, @Nullable String schemaUrl, @Nullable String instrumentationVersion) {
+ this.id = "TracerMock-" + ID_SOURCE.incrementAndGet();
+ this.instrumentationScopeName = instrumentationScopeName;
+ this.tracerProviderId = tracerProviderId;
+ this.schemaUrl = schemaUrl;
+ this.instrumentationVersion = instrumentationVersion;
+ }
+
+ @Override
+ public SpanBuilder spanBuilder(String spanName) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ static class TracerBuilderMock implements TracerBuilder {
+ static AtomicInteger ID_SOURCE = new AtomicInteger(0);
+ final String id;
+ final String instrumentationScopeName;
+ final String tracerProviderId;
+ String schemaUrl;
+ String instrumentationVersion;
+
+
+ public TracerBuilderMock(String instrumentationScopeName, String tracerProviderId) {
+ this.id = "TracerBuilderMock-" + ID_SOURCE.incrementAndGet();
+ this.instrumentationScopeName = instrumentationScopeName;
+ this.tracerProviderId = tracerProviderId;
+ }
+
+ @Override
+ public TracerBuilder setSchemaUrl(String schemaUrl) {
+ this.schemaUrl = schemaUrl;
+ return this;
+ }
+
+ @Override
+ public TracerBuilder setInstrumentationVersion(String instrumentationVersion) {
+ this.instrumentationVersion = instrumentationVersion;
+ return this;
+ }
+
+ @Override
+ public Tracer build() {
+ return new ReconfigurableTracerProviderTest.TracerMock(instrumentationScopeName, tracerProviderId, schemaUrl, instrumentationVersion);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/io/jenkins/plugins/opentelemetry/remotespan/RemoteSpanTest.java b/src/test/java/io/jenkins/plugins/opentelemetry/remotespan/RemoteSpanTest.java
index 03dde6811..484eb4679 100644
--- a/src/test/java/io/jenkins/plugins/opentelemetry/remotespan/RemoteSpanTest.java
+++ b/src/test/java/io/jenkins/plugins/opentelemetry/remotespan/RemoteSpanTest.java
@@ -13,7 +13,7 @@
import io.jenkins.plugins.opentelemetry.BaseIntegrationTest;
import io.jenkins.plugins.opentelemetry.JenkinsOpenTelemetryPluginConfiguration;
import io.jenkins.plugins.opentelemetry.OpenTelemetryConfiguration;
-import io.jenkins.plugins.opentelemetry.OpenTelemetrySdkProvider;
+import io.jenkins.plugins.opentelemetry.JenkinsControllerOpenTelemetry;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes;
import jenkins.model.GlobalConfiguration;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
@@ -37,11 +37,11 @@ public class RemoteSpanTest extends BaseIntegrationTest {
@Before
public void enableRemoteSpan() {
- ExtensionList openTelemetrySdkProviders = jenkinsRule.getInstance().getExtensionList(OpenTelemetrySdkProvider.class);
- verify(openTelemetrySdkProviders.size() == 1, "Number of openTelemetrySdkProviders: %s", openTelemetrySdkProviders.size());
- OpenTelemetrySdkProvider openTelemetrySdkProvider = openTelemetrySdkProviders.get(0);
+ ExtensionList jenkinsOpenTelemetries = jenkinsRule.getInstance().getExtensionList(JenkinsControllerOpenTelemetry.class);
+ verify(jenkinsOpenTelemetries.size() == 1, "Number of jenkinsControllerOpenTelemetrys: %s", jenkinsOpenTelemetries.size());
+ JenkinsControllerOpenTelemetry jenkinsControllerOpenTelemetry = jenkinsOpenTelemetries.get(0);
- // verify(openTelemetrySdkProvider.openTelemetry == null, "OpenTelemetrySdkProvider has already been configured");
+ // verify(jenkinsControllerOpenTelemetry.openTelemetry == null, "JenkinsControllerOpenTelemetry has already been configured");
OpenTelemetryConfiguration.TESTING_INMEMORY_MODE = true;
@@ -50,7 +50,7 @@ public void enableRemoteSpan() {
configuration.setConfigurationProperties(JenkinsOtelSemanticAttributes.OTEL_INSTRUMENTATION_JENKINS_REMOTE_SPAN_ENABLED + "=true");
OpenTelemetryConfiguration config = configuration.toOpenTelemetryConfiguration();
- openTelemetrySdkProvider.initialize(config);
+ jenkinsControllerOpenTelemetry.initialize(config);
}
@Test
public void testRemoteTriggerParentChildTrace() throws Exception {