Skip to content

Commit 41586a4

Browse files
authored
Initialize Sentry in OTEL Java Agent and allow configuring it (#2386)
1 parent 82f359f commit 41586a4

File tree

8 files changed

+94
-43
lines changed

8 files changed

+94
-43
lines changed

buildSrc/src/main/java/Config.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ object Config {
200200
val SENTRY_SPRING_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.spring"
201201
val SENTRY_SPRING_BOOT_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.spring-boot"
202202
val SENTRY_SPRING_BOOT_JAKARTA_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.spring-boot.jakarta"
203+
val SENTRY_OPENTELEMETRY_AGENT_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.opentelemetry.agent"
203204
val group = "io.sentry"
204205
val description = "SDK for sentry.io"
205206
val versionNameProp = "versionName"

sentry-opentelemetry/sentry-opentelemetry-agent/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ tasks {
147147
attributes.put("Can-Retransform-Classes", "true")
148148
attributes.put("Implementation-Vendor", "Sentry")
149149
attributes.put("Implementation-Version", "sentry-${project.version}-otel-${Config.Libs.otelJavaagentVersion}")
150+
attributes.put("Sentry-Version-Name", project.version)
151+
attributes.put("Sentry-Opentelemetry-SDK-Name", Config.Sentry.SENTRY_OPENTELEMETRY_AGENT_SDK_NAME)
152+
attributes.put("Sentry-Opentelemetry-Version-Name", Config.Libs.otelVersion)
153+
attributes.put("Sentry-Opentelemetry-Javaagent-Version-Name", Config.Libs.otelJavaagentVersion)
150154
}
151155
}
152156

sentry-opentelemetry/sentry-opentelemetry-agentcustomization/src/main/java/io/sentry/opentelemetry/SentryAutoConfigurationCustomizerProvider.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,87 @@
44
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
55
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
66
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
7+
import io.sentry.Instrumenter;
8+
import io.sentry.Sentry;
9+
import io.sentry.SentryOptions;
10+
import io.sentry.protocol.SdkVersion;
11+
import java.io.IOException;
12+
import java.net.URL;
13+
import java.util.Enumeration;
714
import java.util.HashMap;
815
import java.util.Map;
16+
import java.util.jar.Attributes;
17+
import java.util.jar.Manifest;
18+
import org.jetbrains.annotations.NotNull;
19+
import org.jetbrains.annotations.Nullable;
920

1021
public final class SentryAutoConfigurationCustomizerProvider
1122
implements AutoConfigurationCustomizerProvider {
1223

1324
@Override
1425
public void customize(AutoConfigurationCustomizer autoConfiguration) {
26+
final @Nullable String sentryPropertiesFile = System.getenv("SENTRY_PROPERTIES_FILE");
27+
final @Nullable String sentryDsn = System.getenv("SENTRY_DSN");
28+
29+
if (sentryPropertiesFile != null || sentryDsn != null) {
30+
Sentry.init(
31+
options -> {
32+
options.setEnableExternalConfiguration(true);
33+
options.setInstrumenter(Instrumenter.OTEL);
34+
final @Nullable SdkVersion sdkVersion = createSdkVersion(options);
35+
if (sdkVersion != null) {
36+
options.setSdkVersion(sdkVersion);
37+
}
38+
});
39+
}
40+
1541
autoConfiguration
1642
.addTracerProviderCustomizer(this::configureSdkTracerProvider)
1743
.addPropertiesSupplier(this::getDefaultProperties);
1844
}
1945

46+
private @Nullable SdkVersion createSdkVersion(final @NotNull SentryOptions sentryOptions) {
47+
SdkVersion sdkVersion = sentryOptions.getSdkVersion();
48+
49+
try {
50+
final @NotNull Enumeration<URL> resources =
51+
ClassLoader.getSystemClassLoader().getResources("META-INF/MANIFEST.MF");
52+
while (resources.hasMoreElements()) {
53+
try {
54+
final @NotNull Manifest manifest = new Manifest(resources.nextElement().openStream());
55+
final @Nullable Attributes mainAttributes = manifest.getMainAttributes();
56+
if (mainAttributes != null) {
57+
final @Nullable String name = mainAttributes.getValue("Sentry-Opentelemetry-SDK-Name");
58+
final @Nullable String version = mainAttributes.getValue("Sentry-Version-Name");
59+
60+
if (name != null && version != null) {
61+
sdkVersion = SdkVersion.updateSdkVersion(sdkVersion, name, version);
62+
sdkVersion.addPackage("maven:io.sentry:sentry-opentelemetry-agent", version);
63+
final @Nullable String otelVersion =
64+
mainAttributes.getValue("Sentry-Opentelemetry-Version-Name");
65+
if (otelVersion != null) {
66+
sdkVersion.addPackage("maven:io.opentelemetry:opentelemetry-sdk", otelVersion);
67+
}
68+
final @Nullable String otelJavaagentVersion =
69+
mainAttributes.getValue("Sentry-Opentelemetry-Javaagent-Version-Name");
70+
if (otelJavaagentVersion != null) {
71+
sdkVersion.addPackage(
72+
"maven:io.opentelemetry.javaagent:opentelemetry-javaagent",
73+
otelJavaagentVersion);
74+
}
75+
}
76+
}
77+
} catch (Exception e) {
78+
// ignore
79+
}
80+
}
81+
} catch (IOException e) {
82+
// ignore
83+
}
84+
85+
return sdkVersion;
86+
}
87+
2088
private SdkTracerProviderBuilder configureSdkTracerProvider(
2189
SdkTracerProviderBuilder tracerProvider, ConfigProperties config) {
2290
return tracerProvider.addSpanProcessor(new SentrySpanProcessor());

sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentryPropagator.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,8 @@ public <C> Context extract(
7575
Context modifiedContext = context.with(SentryOtelKeys.SENTRY_TRACE_KEY, sentryTraceHeader);
7676

7777
final @Nullable String baggageString = getter.get(carrier, BaggageHeader.BAGGAGE_HEADER);
78-
if (baggageString != null) {
79-
Baggage baggage = Baggage.fromHeader(baggageString);
80-
modifiedContext = modifiedContext.with(SentryOtelKeys.SENTRY_BAGGAGE_KEY, baggage);
81-
}
78+
Baggage baggage = Baggage.fromHeader(baggageString);
79+
modifiedContext = modifiedContext.with(SentryOtelKeys.SENTRY_BAGGAGE_KEY, baggage);
8280

8381
Span wrappedSpan = Span.wrap(otelSpanContext);
8482
modifiedContext = modifiedContext.with(wrappedSpan);

sentry-samples/sentry-samples-spring-boot/src/main/java/io/sentry/samples/spring/boot/CustomEventProcessor.java

Lines changed: 0 additions & 35 deletions
This file was deleted.

sentry/src/main/java/io/sentry/Baggage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public final class Baggage {
3535
final @NotNull ILogger logger;
3636

3737
@NotNull
38-
public static Baggage fromHeader(final String headerValue) {
38+
public static Baggage fromHeader(final @Nullable String headerValue) {
3939
return Baggage.fromHeader(
4040
headerValue, false, HubAdapter.getInstance().getOptions().getLogger());
4141
}

sentry/src/main/java/io/sentry/config/ClasspathPropertiesLoader.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@ final class ClasspathPropertiesLoader implements PropertiesLoader {
1616
private final @NotNull ILogger logger;
1717

1818
public ClasspathPropertiesLoader(
19-
@NotNull String fileName, @NotNull ClassLoader classLoader, @NotNull ILogger logger) {
19+
@NotNull String fileName, @Nullable ClassLoader classLoader, @NotNull ILogger logger) {
2020
this.fileName = fileName;
21-
this.classLoader = classLoader;
21+
// bootstrap classloader is represented as null, so using system classloader instead
22+
if (classLoader == null) {
23+
this.classLoader = ClassLoader.getSystemClassLoader();
24+
} else {
25+
this.classLoader = classLoader;
26+
}
2227
this.logger = logger;
2328
}
2429

2530
public ClasspathPropertiesLoader(@NotNull ILogger logger) {
26-
// TODO check not null
2731
this("sentry.properties", ClasspathPropertiesLoader.class.getClassLoader(), logger);
2832
}
2933

sentry/src/test/java/io/sentry/SentryTracerTest.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import org.mockito.kotlin.never
1010
import org.mockito.kotlin.spy
1111
import org.mockito.kotlin.times
1212
import org.mockito.kotlin.verify
13+
import java.time.LocalDateTime
14+
import java.time.ZoneOffset
1315
import java.util.Date
1416
import kotlin.test.Test
1517
import kotlin.test.assertEquals
@@ -119,6 +121,15 @@ class SentryTracerTest {
119121
assertEquals(SpanStatus.ABORTED, tracer.status)
120122
}
121123

124+
@Test
125+
fun `when transaction is finished with status and timestamp, timestamp and status are set`() {
126+
val tracer = fixture.getSut()
127+
val date = Date.from(LocalDateTime.of(2022, 12, 24, 23, 59, 58, 0).toInstant(ZoneOffset.UTC))
128+
tracer.finish(SpanStatus.ABORTED, date)
129+
assertEquals(tracer.timestamp, DateUtils.dateToSeconds(date))
130+
assertEquals(SpanStatus.ABORTED, tracer.status)
131+
}
132+
122133
@Test
123134
fun `when transaction is finished, transaction is captured`() {
124135
val tracer = fixture.getSut()

0 commit comments

Comments
 (0)