Skip to content

Commit e60f0df

Browse files
authored
Merge 476d7f1 into ad8da22
2 parents ad8da22 + 476d7f1 commit e60f0df

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+3944
-0
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ apiValidation {
7777
"sentry-samples-spring-boot-4",
7878
"sentry-samples-spring-boot-4-opentelemetry",
7979
"sentry-samples-spring-boot-4-opentelemetry-noagent",
80+
"sentry-samples-spring-boot-4-otlp",
8081
"sentry-samples-spring-boot-4-webflux",
8182
"sentry-samples-ktor-client",
8283
"sentry-uitest-android",

buildSrc/src/main/java/Config.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ object Config {
6464
val SENTRY_SPRING_BOOT_4_STARTER_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.spring-boot-4-starter"
6565
val SENTRY_OPENTELEMETRY_BOOTSTRAP_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.opentelemetry.bootstrap"
6666
val SENTRY_OPENTELEMETRY_CORE_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.opentelemetry.core"
67+
val SENTRY_OPENTELEMETRY_OTLP_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.opentelemetry.otlp"
6768
val SENTRY_OPENTELEMETRY_AGENT_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.opentelemetry.agent"
6869
val SENTRY_OPENTELEMETRY_AGENTLESS_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.opentelemetry.agentless"
6970
val SENTRY_OPENTELEMETRY_AGENTLESS_SPRING_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.opentelemetry.agentless-spring"
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
public final class io/sentry/opentelemetry/OpenTelemetryAttributesExtractor {
2+
public fun <init> ()V
3+
public fun extract (Lio/opentelemetry/sdk/trace/data/SpanData;Lio/sentry/IScope;Lio/sentry/SentryOptions;)V
4+
public fun extractUrl (Lio/opentelemetry/api/common/Attributes;Lio/sentry/SentryOptions;)Ljava/lang/String;
5+
}
6+
7+
public final class io/sentry/opentelemetry/OpenTelemetryLinkErrorEventProcessor : io/sentry/EventProcessor {
8+
public fun <init> ()V
9+
public fun getOrder ()Ljava/lang/Long;
10+
public fun process (Lio/sentry/SentryEvent;Lio/sentry/Hint;)Lio/sentry/SentryEvent;
11+
}
12+
13+
public final class io/sentry/opentelemetry/OtelInternalSpanDetectionUtil {
14+
public fun <init> ()V
15+
public static fun isSentryRequest (Lio/sentry/IScopes;Lio/opentelemetry/api/trace/SpanKind;Lio/opentelemetry/api/common/Attributes;)Z
16+
}
17+
18+
public final class io/sentry/opentelemetry/OtelSamplingUtil {
19+
public fun <init> ()V
20+
public static fun extractSamplingDecision (Lio/opentelemetry/api/common/Attributes;)Lio/sentry/TracesSamplingDecision;
21+
}
22+
23+
public final class io/sentry/opentelemetry/OtelSentryPropagator : io/opentelemetry/context/propagation/TextMapPropagator {
24+
public fun <init> ()V
25+
public fun extract (Lio/opentelemetry/context/Context;Ljava/lang/Object;Lio/opentelemetry/context/propagation/TextMapGetter;)Lio/opentelemetry/context/Context;
26+
public fun fields ()Ljava/util/Collection;
27+
public fun inject (Lio/opentelemetry/context/Context;Ljava/lang/Object;Lio/opentelemetry/context/propagation/TextMapSetter;)V
28+
}
29+
30+
public final class io/sentry/opentelemetry/OtelSentrySpanProcessor : io/opentelemetry/sdk/trace/SpanProcessor {
31+
public fun <init> ()V
32+
public fun isEndRequired ()Z
33+
public fun isStartRequired ()Z
34+
public fun onEnd (Lio/opentelemetry/sdk/trace/ReadableSpan;)V
35+
public fun onStart (Lio/opentelemetry/context/Context;Lio/opentelemetry/sdk/trace/ReadWriteSpan;)V
36+
}
37+
38+
public final class io/sentry/opentelemetry/OtelSpanContext : io/sentry/SpanContext {
39+
public fun <init> (Lio/opentelemetry/sdk/trace/ReadWriteSpan;Lio/sentry/TracesSamplingDecision;Lio/sentry/opentelemetry/IOtelSpanWrapper;Lio/sentry/SpanId;Lio/sentry/Baggage;)V
40+
public fun getOperation ()Ljava/lang/String;
41+
public fun getStatus ()Lio/sentry/SpanStatus;
42+
public fun setOperation (Ljava/lang/String;)V
43+
public fun setStatus (Lio/sentry/SpanStatus;)V
44+
}
45+
46+
public final class io/sentry/opentelemetry/OtelSpanInfo {
47+
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/sentry/protocol/TransactionNameSource;)V
48+
public fun getDescription ()Ljava/lang/String;
49+
public fun getOp ()Ljava/lang/String;
50+
public fun getTransactionNameSource ()Lio/sentry/protocol/TransactionNameSource;
51+
}
52+
53+
public final class io/sentry/opentelemetry/OtelSpanUtils {
54+
public fun <init> ()V
55+
public static fun maybeTransferOtelAttribute (Lio/opentelemetry/sdk/trace/data/SpanData;Lio/sentry/ISpan;Lio/opentelemetry/api/common/AttributeKey;)V
56+
}
57+
58+
public final class io/sentry/opentelemetry/OtelSpanWrapper : io/sentry/opentelemetry/IOtelSpanWrapper {
59+
public fun <init> (Lio/opentelemetry/sdk/trace/ReadWriteSpan;Lio/sentry/IScopes;Lio/sentry/SentryDate;Lio/sentry/TracesSamplingDecision;Lio/sentry/opentelemetry/IOtelSpanWrapper;Lio/sentry/SpanId;Lio/sentry/Baggage;)V
60+
public fun addFeatureFlag (Ljava/lang/String;Ljava/lang/Boolean;)V
61+
public fun finish ()V
62+
public fun finish (Lio/sentry/SpanStatus;)V
63+
public fun finish (Lio/sentry/SpanStatus;Lio/sentry/SentryDate;)V
64+
public fun getContexts ()Lio/sentry/protocol/Contexts;
65+
public fun getData ()Ljava/util/Map;
66+
public fun getData (Ljava/lang/String;)Ljava/lang/Object;
67+
public fun getDescription ()Ljava/lang/String;
68+
public fun getFinishDate ()Lio/sentry/SentryDate;
69+
public fun getMeasurements ()Ljava/util/Map;
70+
public fun getOpenTelemetrySpanAttributes ()Lio/opentelemetry/api/common/Attributes;
71+
public fun getOperation ()Ljava/lang/String;
72+
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
73+
public fun getScopes ()Lio/sentry/IScopes;
74+
public fun getSpanContext ()Lio/sentry/SpanContext;
75+
public fun getStartDate ()Lio/sentry/SentryDate;
76+
public fun getStatus ()Lio/sentry/SpanStatus;
77+
public fun getTag (Ljava/lang/String;)Ljava/lang/String;
78+
public fun getTags ()Ljava/util/Map;
79+
public fun getThrowable ()Ljava/lang/Throwable;
80+
public fun getTraceId ()Lio/sentry/protocol/SentryId;
81+
public fun getTransactionName ()Ljava/lang/String;
82+
public fun getTransactionNameSource ()Lio/sentry/protocol/TransactionNameSource;
83+
public fun isFinished ()Z
84+
public fun isNoOp ()Z
85+
public fun isProfileSampled ()Ljava/lang/Boolean;
86+
public fun isSampled ()Ljava/lang/Boolean;
87+
public fun makeCurrent ()Lio/sentry/ISentryLifecycleToken;
88+
public fun setContext (Ljava/lang/String;Ljava/lang/Object;)V
89+
public fun setData (Ljava/lang/String;Ljava/lang/Object;)V
90+
public fun setDescription (Ljava/lang/String;)V
91+
public fun setMeasurement (Ljava/lang/String;Ljava/lang/Number;)V
92+
public fun setMeasurement (Ljava/lang/String;Ljava/lang/Number;Lio/sentry/MeasurementUnit;)V
93+
public fun setOperation (Ljava/lang/String;)V
94+
public fun setStatus (Lio/sentry/SpanStatus;)V
95+
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
96+
public fun setThrowable (Ljava/lang/Throwable;)V
97+
public fun setTransactionName (Ljava/lang/String;)V
98+
public fun setTransactionName (Ljava/lang/String;Lio/sentry/protocol/TransactionNameSource;)V
99+
public fun startChild (Lio/sentry/SpanContext;Lio/sentry/SpanOptions;)Lio/sentry/ISpan;
100+
public fun startChild (Ljava/lang/String;)Lio/sentry/ISpan;
101+
public fun startChild (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/ISpan;
102+
public fun startChild (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryDate;Lio/sentry/Instrumenter;)Lio/sentry/ISpan;
103+
public fun startChild (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryDate;Lio/sentry/Instrumenter;Lio/sentry/SpanOptions;)Lio/sentry/ISpan;
104+
public fun startChild (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SpanOptions;)Lio/sentry/ISpan;
105+
public fun storeInContext (Lio/opentelemetry/context/Context;)Lio/opentelemetry/context/Context;
106+
public fun toBaggageHeader (Ljava/util/List;)Lio/sentry/BaggageHeader;
107+
public fun toSentryTrace ()Lio/sentry/SentryTraceHeader;
108+
public fun traceContext ()Lio/sentry/TraceContext;
109+
public fun updateEndDate (Lio/sentry/SentryDate;)Z
110+
}
111+
112+
public final class io/sentry/opentelemetry/SentryPropagator : io/opentelemetry/context/propagation/TextMapPropagator {
113+
public fun <init> ()V
114+
public fun extract (Lio/opentelemetry/context/Context;Ljava/lang/Object;Lio/opentelemetry/context/propagation/TextMapGetter;)Lio/opentelemetry/context/Context;
115+
public fun fields ()Ljava/util/Collection;
116+
public fun inject (Lio/opentelemetry/context/Context;Ljava/lang/Object;Lio/opentelemetry/context/propagation/TextMapSetter;)V
117+
}
118+
119+
public final class io/sentry/opentelemetry/SentrySampler : io/opentelemetry/sdk/trace/samplers/Sampler {
120+
public fun <init> ()V
121+
public fun <init> (Lio/sentry/IScopes;)V
122+
public fun getDescription ()Ljava/lang/String;
123+
public fun shouldSample (Lio/opentelemetry/context/Context;Ljava/lang/String;Ljava/lang/String;Lio/opentelemetry/api/trace/SpanKind;Lio/opentelemetry/api/common/Attributes;Ljava/util/List;)Lio/opentelemetry/sdk/trace/samplers/SamplingResult;
124+
}
125+
126+
public final class io/sentry/opentelemetry/SentrySamplingResult : io/opentelemetry/sdk/trace/samplers/SamplingResult {
127+
public fun <init> (Lio/sentry/TracesSamplingDecision;)V
128+
public fun getAttributes ()Lio/opentelemetry/api/common/Attributes;
129+
public fun getDecision ()Lio/opentelemetry/sdk/trace/samplers/SamplingDecision;
130+
public fun getSentryDecision ()Lio/sentry/TracesSamplingDecision;
131+
}
132+
133+
public final class io/sentry/opentelemetry/SentrySpanExporter : io/opentelemetry/sdk/trace/export/SpanExporter {
134+
public static final field TRACE_ORIGIN Ljava/lang/String;
135+
public fun <init> ()V
136+
public fun <init> (Lio/sentry/IScopes;)V
137+
public fun export (Ljava/util/Collection;)Lio/opentelemetry/sdk/common/CompletableResultCode;
138+
public fun flush ()Lio/opentelemetry/sdk/common/CompletableResultCode;
139+
public fun shutdown ()Lio/opentelemetry/sdk/common/CompletableResultCode;
140+
}
141+
142+
public final class io/sentry/opentelemetry/SentrySpanProcessor : io/opentelemetry/sdk/trace/SpanProcessor {
143+
public fun <init> ()V
144+
public fun isEndRequired ()Z
145+
public fun isStartRequired ()Z
146+
public fun onEnd (Lio/opentelemetry/sdk/trace/ReadableSpan;)V
147+
public fun onStart (Lio/opentelemetry/context/Context;Lio/opentelemetry/sdk/trace/ReadWriteSpan;)V
148+
}
149+
150+
public final class io/sentry/opentelemetry/SpanDescriptionExtractor {
151+
public fun <init> ()V
152+
public fun extractSpanInfo (Lio/opentelemetry/sdk/trace/data/SpanData;Lio/sentry/opentelemetry/IOtelSpanWrapper;)Lio/sentry/opentelemetry/OtelSpanInfo;
153+
}
154+
155+
public final class io/sentry/opentelemetry/SpanNode {
156+
public fun <init> (Ljava/lang/String;)V
157+
public fun addChild (Lio/sentry/opentelemetry/SpanNode;)V
158+
public fun addChildren (Ljava/util/List;)V
159+
public fun getChildren ()Ljava/util/List;
160+
public fun getId ()Ljava/lang/String;
161+
public fun getParentNode ()Lio/sentry/opentelemetry/SpanNode;
162+
public fun getSpan ()Lio/opentelemetry/sdk/trace/data/SpanData;
163+
public fun setParentNode (Lio/sentry/opentelemetry/SpanNode;)V
164+
public fun setSpan (Lio/opentelemetry/sdk/trace/data/SpanData;)V
165+
}
166+
167+
public final class io/sentry/opentelemetry/TraceData {
168+
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryTraceHeader;Lio/sentry/Baggage;)V
169+
public fun getBaggage ()Lio/sentry/Baggage;
170+
public fun getParentSpanId ()Ljava/lang/String;
171+
public fun getSentryTraceHeader ()Lio/sentry/SentryTraceHeader;
172+
public fun getSpanId ()Ljava/lang/String;
173+
public fun getTraceId ()Ljava/lang/String;
174+
}
175+
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import net.ltgt.gradle.errorprone.errorprone
2+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
3+
4+
plugins {
5+
`java-library`
6+
id("io.sentry.javadoc")
7+
alias(libs.plugins.kotlin.jvm)
8+
jacoco
9+
alias(libs.plugins.errorprone)
10+
alias(libs.plugins.gradle.versions)
11+
}
12+
13+
tasks.withType<KotlinCompile>().configureEach {
14+
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
15+
}
16+
17+
dependencies {
18+
api(projects.sentry)
19+
20+
compileOnly(libs.otel)
21+
// compileOnly(libs.otel.semconv)
22+
// compileOnly(libs.otel.semconv.incubating)
23+
24+
compileOnly(libs.jetbrains.annotations)
25+
compileOnly(libs.nopen.annotations)
26+
errorprone(libs.errorprone.core)
27+
errorprone(libs.nopen.checker)
28+
errorprone(libs.nullaway)
29+
30+
// tests
31+
testImplementation(projects.sentryTestSupport)
32+
testImplementation(kotlin(Config.kotlinStdLib))
33+
testImplementation(libs.awaitility.kotlin)
34+
testImplementation(libs.kotlin.test.junit)
35+
testImplementation(libs.mockito.kotlin)
36+
37+
testImplementation(libs.otel)
38+
// testImplementation(libs.otel.semconv)
39+
// testImplementation(libs.otel.semconv.incubating)
40+
}
41+
42+
configure<SourceSetContainer> { test { java.srcDir("src/test/java") } }
43+
44+
jacoco { toolVersion = libs.versions.jacoco.get() }
45+
46+
tasks.jacocoTestReport {
47+
reports {
48+
xml.required.set(true)
49+
html.required.set(false)
50+
}
51+
}
52+
53+
tasks {
54+
jacocoTestCoverageVerification {
55+
violationRules { rule { limit { minimum = Config.QualityPlugins.Jacoco.minimumCoverage } } }
56+
}
57+
check {
58+
dependsOn(jacocoTestCoverageVerification)
59+
dependsOn(jacocoTestReport)
60+
}
61+
}
62+
63+
tasks.withType<JavaCompile>().configureEach {
64+
options.errorprone {
65+
check("NullAway", net.ltgt.gradle.errorprone.CheckSeverity.ERROR)
66+
option("NullAway:AnnotatedPackages", "io.sentry")
67+
}
68+
}
69+
70+
tasks.jar {
71+
manifest {
72+
attributes(
73+
"Sentry-Version-Name" to project.version,
74+
"Sentry-SDK-Name" to Config.Sentry.SENTRY_OPENTELEMETRY_OTLP_SDK_NAME,
75+
"Sentry-SDK-Package-Name" to "maven:io.sentry:sentry-opentelemetry-otlp",
76+
"Implementation-Vendor" to "Sentry",
77+
"Implementation-Title" to project.name,
78+
"Implementation-Version" to project.version,
79+
)
80+
}
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package io.sentry.opentelemetry.otlp;
2+
3+
import io.opentelemetry.api.trace.Span;
4+
import io.opentelemetry.api.trace.SpanId;
5+
import io.opentelemetry.api.trace.TraceId;
6+
import io.sentry.EventProcessor;
7+
import io.sentry.Hint;
8+
import io.sentry.IScopes;
9+
import io.sentry.ScopesAdapter;
10+
import io.sentry.SentryEvent;
11+
import io.sentry.SentryLevel;
12+
import io.sentry.SentryLogEvent;
13+
import io.sentry.SentryMetricsEvent;
14+
import io.sentry.SpanContext;
15+
import io.sentry.protocol.SentryId;
16+
import org.jetbrains.annotations.NotNull;
17+
import org.jetbrains.annotations.Nullable;
18+
import org.jetbrains.annotations.TestOnly;
19+
20+
public final class OpenTelemetryOtlpEventProcessor implements EventProcessor {
21+
22+
private final @NotNull IScopes scopes;
23+
24+
public OpenTelemetryOtlpEventProcessor() {
25+
this(ScopesAdapter.getInstance());
26+
}
27+
28+
@TestOnly
29+
OpenTelemetryOtlpEventProcessor(final @NotNull IScopes scopes) {
30+
this.scopes = scopes;
31+
}
32+
33+
@Override
34+
public @Nullable SentryEvent process(final @NotNull SentryEvent event, final @NotNull Hint hint) {
35+
@NotNull final Span otelSpan = Span.current();
36+
@NotNull final String traceId = otelSpan.getSpanContext().getTraceId();
37+
@NotNull final String spanId = otelSpan.getSpanContext().getSpanId();
38+
39+
if (TraceId.isValid(traceId) && SpanId.isValid(spanId)) {
40+
final @NotNull SpanContext spanContext =
41+
new SpanContext(
42+
new SentryId(traceId),
43+
new io.sentry.SpanId(spanId),
44+
"opentelemetry",
45+
null,
46+
null);
47+
48+
event.getContexts().setTrace(spanContext);
49+
scopes
50+
.getOptions()
51+
.getLogger()
52+
.log(
53+
SentryLevel.DEBUG,
54+
"Linking Sentry event %s to span %s created via OpenTelemetry (trace %s).",
55+
event.getEventId(),
56+
spanId,
57+
traceId);
58+
} else {
59+
scopes
60+
.getOptions()
61+
.getLogger()
62+
.log(
63+
SentryLevel.DEBUG,
64+
"Not linking Sentry event %s to any transaction created via OpenTelemetry as traceId %s or spanId %s are invalid.",
65+
event.getEventId(),
66+
traceId,
67+
spanId);
68+
}
69+
70+
return event;
71+
}
72+
73+
@Override
74+
public @Nullable SentryLogEvent process(@NotNull SentryLogEvent event) {
75+
@NotNull final Span otelSpan = Span.current();
76+
@NotNull final String traceId = otelSpan.getSpanContext().getTraceId();
77+
@NotNull final String spanId = otelSpan.getSpanContext().getSpanId();
78+
79+
if (TraceId.isValid(traceId) && SpanId.isValid(spanId)) {
80+
event.setTraceId(new SentryId(traceId));
81+
event.setSpanId(new io.sentry.SpanId(spanId));
82+
} else {
83+
scopes
84+
.getOptions()
85+
.getLogger()
86+
.log(
87+
SentryLevel.DEBUG,
88+
"Not linking Sentry event to any transaction created via OpenTelemetry as traceId %s or spanId %s are invalid.",
89+
traceId,
90+
spanId);
91+
}
92+
93+
return event;
94+
}
95+
96+
@Override
97+
public @Nullable SentryMetricsEvent process(@NotNull SentryMetricsEvent event, @NotNull Hint hint) {
98+
@NotNull final Span otelSpan = Span.current();
99+
@NotNull final String traceId = otelSpan.getSpanContext().getTraceId();
100+
@NotNull final String spanId = otelSpan.getSpanContext().getSpanId();
101+
102+
if (TraceId.isValid(traceId) && SpanId.isValid(spanId)) {
103+
event.setTraceId(new SentryId(traceId));
104+
event.setSpanId(new io.sentry.SpanId(spanId));
105+
} else {
106+
scopes
107+
.getOptions()
108+
.getLogger()
109+
.log(
110+
SentryLevel.DEBUG,
111+
"Not linking Sentry event to any transaction created via OpenTelemetry as traceId %s or spanId %s are invalid.",
112+
traceId,
113+
spanId);
114+
}
115+
116+
return event;
117+
}
118+
119+
@Override
120+
public @Nullable Long getOrder() {
121+
return 6000L;
122+
}
123+
}

0 commit comments

Comments
 (0)