Skip to content

Commit

Permalink
Merge pull request #15 from jenkinsci/log-exporter-test
Browse files Browse the repository at this point in the history
Add log exporter test method
  • Loading branch information
cyrille-leclerc authored Aug 28, 2024
2 parents 85785bc + 46cdc83 commit 65c5907
Show file tree
Hide file tree
Showing 6 changed files with 561 additions and 10 deletions.
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<opentelemetry-instrumentation.version>2.6.0</opentelemetry-instrumentation.version>
<opentelemetry-semconv.version>1.25.0-alpha</opentelemetry-semconv.version>

<auto-value.version>1.11.0</auto-value.version>
<jenkins.version>2.440.3</jenkins.version>

<changelist>999999-SNAPSHOT</changelist>
Expand Down Expand Up @@ -109,6 +110,12 @@
<groupId>io.jenkins.plugins</groupId>
<artifactId>okhttp-api</artifactId>
</dependency>
<dependency>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value-annotations</artifactId>
<version>${auto-value.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-testing</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
import hudson.ExtensionPoint;
import hudson.init.InitMilestone;
import hudson.init.Initializer;
import io.jenkins.plugins.opentelemetry.api.logs.TestLogRecordData;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.incubator.events.EventLogger;
import io.opentelemetry.api.incubator.events.EventLoggerBuilder;
import io.opentelemetry.api.incubator.events.EventLoggerProvider;
import io.opentelemetry.api.incubator.events.GlobalEventLoggerProvider;
import io.opentelemetry.api.logs.LoggerProvider;
import io.opentelemetry.api.logs.Severity;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.MeterBuilder;
import io.opentelemetry.api.metrics.MeterProvider;
Expand All @@ -30,12 +32,17 @@
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.logs.data.LogRecordData;
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
import io.opentelemetry.sdk.logs.internal.SdkEventLoggerProvider;
import io.opentelemetry.sdk.resources.Resource;

import javax.annotation.OverridingMethodsMustInvokeSuper;
import javax.annotation.PreDestroy;
import java.io.Closeable;
import java.time.Instant;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
Expand Down Expand Up @@ -71,6 +78,7 @@ public class ReconfigurableOpenTelemetry implements ExtendedOpenTelemetry, OpenT
Resource resource = Resource.empty();
ConfigProperties config = ConfigPropertiesUtils.emptyConfig();
OpenTelemetry openTelemetryImpl = OpenTelemetry.noop();
LogRecordExporter logRecordExporter = NoopLogRecordExporter.getInstance();
Thread shutdownHook;
final ReconfigurableMeterProvider meterProviderImpl = new ReconfigurableMeterProvider();
final ReconfigurableTracerProvider traceProviderImpl = new ReconfigurableTracerProvider();
Expand All @@ -89,12 +97,12 @@ public static void init() {
* Use a factory method for the @{@link Extension} to ensure single instantiation
* across Jenkins
* <p>
* The Jenkins component {@link ReconfigurableOpenTelemetry} is instantiated through the static factory method
* {@link #get()} rather than through the instance constructor to ensure that we have single
* instantiation across Jenkins' @{@link Extension} and Google Guice @{@link com.google.inject.Inject}.
* The Jenkins component {@link ReconfigurableOpenTelemetry} is instantiated through the static factory method
* {@link #get()} rather than through the instance constructor to ensure that we have single
* instantiation across Jenkins' @{@link Extension} and Google Guice @{@link com.google.inject.Inject}.
* </p>
* <p>
* This {@link #get()} factory method works in conjunction with {@link OpenTelemetryApiGuiceModule}
* This {@link #get()} factory method works in conjunction with {@link OpenTelemetryApiGuiceModule}
* </p>
*/
@Extension(ordinal = Integer.MAX_VALUE)
Expand All @@ -108,7 +116,6 @@ public static ReconfigurableOpenTelemetry get() {
* <p>
* Initialize as NoOp.
* </p>
* @see #get()
*/
public ReconfigurableOpenTelemetry() {
Expand Down Expand Up @@ -146,7 +153,7 @@ public void configure(@NonNull Map<String, String> openTelemetryProperties, Reso
openTelemetryProperties.containsKey("otel.metrics.exporter") ||
openTelemetryProperties.containsKey("otel.logs.exporter")) {

logger.log(Level.FINE, "configure...");
logger.log(Level.FINE, "initializeOtlp");

// OPENTELEMETRY SDK
OpenTelemetrySdk openTelemetrySdk = AutoConfiguredOpenTelemetrySdk
Expand All @@ -167,34 +174,41 @@ public void configure(@NonNull Map<String, String> openTelemetryProperties, Reso
return this.resource;
}
)
.addLogRecordExporterCustomizer((logRecordExporter, configProperties) -> {
// keep a reference to the computed LogRecordExporter for future use in the plugin
this.logRecordExporter = logRecordExporter;
return logRecordExporter;
})
.disableShutdownHook()
.build()
.getOpenTelemetrySdk();
setOpenTelemetryImpl(openTelemetrySdk);

logger.log(Level.INFO, () -> "OpenTelemetry configured: " + ConfigPropertiesUtils.prettyPrintOtelSdkConfig(this.config, this.resource));

if (disableShutdownHook) {
if (shutdownHook == null) {
// nothing to do, no shutdownhook registered
// nothing to do, no shutdown hook registered
} else {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
}
} else {
if (shutdownHook == null) {
shutdownHook = new Thread(this::close);
shutdownHook = new Thread(this::close, "Reconfigurable OpenTelemetry SDK Shutdown Hook");

Check warning on line 195 in src/main/java/io/jenkins/plugins/opentelemetry/api/ReconfigurableOpenTelemetry.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 195 is not covered by tests
Runtime.getRuntime().addShutdownHook(shutdownHook);
} else {
// nothing to do, shutdown hook already registered
}
}

logger.log(Level.INFO, () -> "OpenTelemetry configured: " + ConfigPropertiesUtils.prettyPrintOtelSdkConfig(this.config, this.resource));

} else { // NO-OP

this.resource = Resource.empty();
this.config = ConfigPropertiesUtils.emptyConfig();
setOpenTelemetryImpl(OpenTelemetry.noop());

this.logRecordExporter = NoopLogRecordExporter.getInstance();

Check warning on line 210 in src/main/java/io/jenkins/plugins/opentelemetry/api/ReconfigurableOpenTelemetry.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 210 is not covered by tests

logger.log(Level.FINE, () -> "OpenTelemetry configured as NoOp");
}

Expand Down Expand Up @@ -305,11 +319,52 @@ public ContextPropagators getPropagators() {
return openTelemetryImpl.getPropagators();
}

/**
* For testing and troubleshooting purpose
*/
public LogRecordExporter getLogRecordExporter() {
return logRecordExporter;
}

@OverridingMethodsMustInvokeSuper
protected void postOpenTelemetrySdkConfiguration() {
ExtensionList.lookup(OpenTelemetryLifecycleListener.class).stream().sorted().forEach(openTelemetryLifecycleListener -> {
logger.log(Level.FINE, () -> "Notify " + openTelemetryLifecycleListener + " after OpenTelemetry configuration");
openTelemetryLifecycleListener.afterConfiguration(this.config);
});
}

/**
* Noop implementation of {@link LogRecordExporter}
*/
private static class NoopLogRecordExporter implements LogRecordExporter {
final static NoopLogRecordExporter INSTANCE = new NoopLogRecordExporter();

static NoopLogRecordExporter getInstance() {
return INSTANCE;
}

private NoopLogRecordExporter() {
}

@Override
public CompletableResultCode export(Collection<LogRecordData> logs) {
return CompletableResultCode.ofSuccess();
}

@Override
public CompletableResultCode flush() {
return CompletableResultCode.ofSuccess();
}

@Override
public CompletableResultCode shutdown() {
return CompletableResultCode.ofSuccess();
}

@Override
public String toString() {
return "NoopLogRecordExporter";

Check warning on line 367 in src/main/java/io/jenkins/plugins/opentelemetry/api/ReconfigurableOpenTelemetry.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 352-367 are not covered by tests
}
}
}
Loading

0 comments on commit 65c5907

Please sign in to comment.