Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add logging for OpenTelemetry integration #2425

Merged
merged 6 commits into from Dec 22, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Features

- Add logging for OpenTelemetry integration ([#2425](https://github.com/getsentry/sentry-java/pull/2425))

### Dependencies

- Bump Native SDK from v0.5.2 to v0.5.3 ([#2423](https://github.com/getsentry/sentry-java/pull/2423))
Expand Down
Expand Up @@ -6,22 +6,36 @@
import io.sentry.EventProcessor;
import io.sentry.Hint;
import io.sentry.HubAdapter;
import io.sentry.IHub;
import io.sentry.ISpan;
import io.sentry.Instrumenter;
import io.sentry.SentryEvent;
import io.sentry.SentryLevel;
import io.sentry.SentrySpanStorage;
import io.sentry.SpanContext;
import io.sentry.protocol.SentryId;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;

public final class OpenTelemetryLinkErrorEventProcessor implements EventProcessor {

private final @NotNull IHub hub;
private final @NotNull SentrySpanStorage spanStorage = SentrySpanStorage.getInstance();

public OpenTelemetryLinkErrorEventProcessor() {
this(HubAdapter.getInstance());
}

@TestOnly
OpenTelemetryLinkErrorEventProcessor(final @NotNull IHub hub) {
this.hub = hub;
}

@Override
public @Nullable SentryEvent process(final @NotNull SentryEvent event, final @NotNull Hint hint) {
if (Instrumenter.OTEL.equals(HubAdapter.getInstance().getOptions().getInstrumenter())) {
final @NotNull Instrumenter instrumenter = hub.getOptions().getInstrumenter();
if (Instrumenter.OTEL.equals(instrumenter)) {
@NotNull final Span otelSpan = Span.current();
@NotNull final String traceId = otelSpan.getSpanContext().getTraceId();
@NotNull final String spanId = otelSpan.getSpanContext().getSpanId();
Expand All @@ -41,8 +55,42 @@ public final class OpenTelemetryLinkErrorEventProcessor implements EventProcesso
null);

event.getContexts().setTrace(spanContext);
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Linking Sentry event %s to span %s created via OpenTelemetry (trace %s).",
event.getEventId(),
spanId,
traceId);
} else {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Not linking Sentry event %s to any transaction created via OpenTelemetry as none has been found for span %s (trace %s).",
event.getEventId(),
spanId,
traceId);
}
} else {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Not linking Sentry event %s to any transaction created via OpenTelemetry as traceId %s or spanId %s are invalid.",
event.getEventId(),
traceId,
spanId);
}
} else {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Not linking Sentry event %s to any transaction created via OpenTelemetry as instrumenter is set to %s.",
event.getEventId(),
instrumenter);
}

return event;
Expand Down
Expand Up @@ -10,7 +10,10 @@
import io.opentelemetry.context.propagation.TextMapSetter;
import io.sentry.Baggage;
import io.sentry.BaggageHeader;
import io.sentry.HubAdapter;
import io.sentry.IHub;
import io.sentry.ISpan;
import io.sentry.SentryLevel;
import io.sentry.SentrySpanStorage;
import io.sentry.SentryTraceHeader;
import io.sentry.exception.InvalidSentryTraceHeaderException;
Expand All @@ -26,6 +29,15 @@ public final class SentryPropagator implements TextMapPropagator {
private static final @NotNull List<String> FIELDS =
Arrays.asList(SentryTraceHeader.SENTRY_TRACE_HEADER, BaggageHeader.BAGGAGE_HEADER);
private final @NotNull SentrySpanStorage spanStorage = SentrySpanStorage.getInstance();
private final @NotNull IHub hub;

public SentryPropagator() {
this(HubAdapter.getInstance());
}

SentryPropagator(final @NotNull IHub hub) {
this.hub = hub;
}

@Override
public Collection<String> fields() {
Expand All @@ -37,10 +49,22 @@ public <C> void inject(final Context context, final C carrier, final TextMapSett
final @NotNull Span otelSpan = Span.fromContext(context);
final @NotNull SpanContext otelSpanContext = otelSpan.getSpanContext();
if (!otelSpanContext.isValid()) {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Not injecting Sentry tracing information for invalid OpenTelemetry span.");
return;
}
final @Nullable ISpan sentrySpan = spanStorage.get(otelSpanContext.getSpanId());
if (sentrySpan == null || sentrySpan.isNoOp()) {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Not injecting Sentry tracing information for span %s as no Sentry span has been found or it is a NoOp (trace %s). This might simply mean this is a request to Sentry.",
otelSpanContext.getSpanId(),
otelSpanContext.getTraceId());
return;
}

Expand Down Expand Up @@ -82,8 +106,18 @@ public <C> Context extract(
Span wrappedSpan = Span.wrap(otelSpanContext);
modifiedContext = modifiedContext.with(wrappedSpan);

hub.getOptions()
.getLogger()
.log(SentryLevel.DEBUG, "Continuing Sentry trace %s", sentryTraceHeader.getTraceId());

return modifiedContext;
} catch (InvalidSentryTraceHeaderException e) {
hub.getOptions()
.getLogger()
.log(
SentryLevel.ERROR,
"Unable to extract Sentry tracing information from invalid header.",
e);
return context;
}
}
Expand Down
Expand Up @@ -19,6 +19,7 @@
import io.sentry.ISpan;
import io.sentry.ITransaction;
import io.sentry.Instrumenter;
import io.sentry.SentryLevel;
import io.sentry.SentrySpanStorage;
import io.sentry.SentryTraceHeader;
import io.sentry.SpanId;
Expand Down Expand Up @@ -48,7 +49,7 @@ public SentrySpanProcessor() {
this(HubAdapter.getInstance());
}

SentrySpanProcessor(@NotNull IHub hub) {
SentrySpanProcessor(final @NotNull IHub hub) {
this.hub = hub;
}

Expand All @@ -58,22 +59,44 @@ public void onStart(final @NotNull Context parentContext, final @NotNull ReadWri
return;
}

final @NotNull TraceData traceData = getTraceData(otelSpan, parentContext);

if (isSentryRequest(otelSpan)) {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Not forwarding OpenTelemetry span %s to Sentry as this looks like a span for a request to Sentry (trace %s).",
traceData.getSpanId(),
traceData.getTraceId());
return;
}

final @NotNull TraceData traceData = getTraceData(otelSpan, parentContext);
final @Nullable ISpan sentryParentSpan =
traceData.getParentSpanId() == null ? null : spanStorage.get(traceData.getParentSpanId());

if (sentryParentSpan != null) {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Creating Sentry child span for OpenTelemetry span %s (trace %s). Parent span is %s.",
traceData.getSpanId(),
traceData.getTraceId(),
traceData.getParentSpanId());
final @NotNull Date startDate =
DateUtils.nanosToDate(otelSpan.toSpanData().getStartEpochNanos());
final @NotNull ISpan sentryChildSpan =
sentryParentSpan.startChild(
otelSpan.getName(), otelSpan.getName(), startDate, Instrumenter.OTEL);
spanStorage.store(traceData.getSpanId(), sentryChildSpan);
} else {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Creating Sentry transaction for OpenTelemetry span %s (trace %s).",
traceData.getSpanId(),
traceData.getTraceId());
final @NotNull String transactionName = otelSpan.getName();
final @NotNull TransactionNameSource transactionNameSource = TransactionNameSource.CUSTOM;
final @Nullable String op = otelSpan.getName();
Expand Down Expand Up @@ -124,18 +147,48 @@ public void onEnd(final @NotNull ReadableSpan otelSpan) {
final @Nullable ISpan sentrySpan = spanStorage.removeAndGet(traceData.getSpanId());

if (sentrySpan == null) {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Unable to find Sentry span for OpenTelemetry span %s (trace %s).",
traceData.getSpanId(),
traceData.getTraceId());
return;
}

if (isSentryRequest(otelSpan)) {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Not forwarding OpenTelemetry span %s to Sentry as this looks like a span for a request to Sentry (trace %s).",
traceData.getSpanId(),
traceData.getTraceId());
return;
}

if (sentrySpan instanceof ITransaction) {
ITransaction sentryTransaction = (ITransaction) sentrySpan;
final @NotNull ITransaction sentryTransaction = (ITransaction) sentrySpan;
updateTransactionWithOtelData(sentryTransaction, otelSpan);
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Finishing Sentry transaction %s for OpenTelemetry span %s (trace %s).",
sentryTransaction.getEventId(),
traceData.getSpanId(),
traceData.getTraceId());
} else {
updateSpanWithOtelData(sentrySpan, otelSpan);
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Finishing Sentry span for OpenTelemetry span %s (trace %s). Parent span is %s.",
traceData.getSpanId(),
traceData.getTraceId(),
traceData.getParentSpanId());
}

final @NotNull SpanStatus sentryStatus = mapOtelStatus(otelSpan);
Expand All @@ -151,15 +204,32 @@ public boolean isEndRequired() {

private boolean ensurePrerequisites(final @NotNull ReadableSpan otelSpan) {
if (!hasSentryBeenInitialized()) {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Not forwarding OpenTelemetry span to Sentry as Sentry has not yet been initialized.");
return false;
}

if (!Instrumenter.OTEL.equals(hub.getOptions().getInstrumenter())) {
final @NotNull Instrumenter instrumenter = hub.getOptions().getInstrumenter();
if (!Instrumenter.OTEL.equals(instrumenter)) {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Not forwarding OpenTelemetry span to Sentry as instrumenter has been set to %s.",
instrumenter);
return false;
}

final @NotNull SpanContext otelSpanContext = otelSpan.getSpanContext();
if (!otelSpanContext.isValid()) {
hub.getOptions()
.getLogger()
.log(
SentryLevel.DEBUG,
"Not forwarding OpenTelemetry span to Sentry as the span is invalid.");
return false;
}

Expand Down