From fae85e1922f2dc83ba44682d8b3dfff28511a0f7 Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Tue, 10 Dec 2024 10:11:37 +0100 Subject: [PATCH 01/12] update readmes for noagent samples, add otel properties to application.properties in noagent samples --- .../README.md | 2 +- .../src/main/resources/application.properties | 4 ++++ .../README.md | 2 +- .../src/main/resources/application.properties | 6 ++++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/README.md b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/README.md index 58b94ba899..89a8e603a3 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/README.md +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/README.md @@ -1,6 +1,6 @@ # Sentry Sample Spring Boot 3.0+ -Sample application showing how to use Sentry with [Spring boot](http://spring.io/projects/spring-boot) from version `3.0` onwards. +Sample application showing how to use Sentry with [Spring boot](http://spring.io/projects/spring-boot) from version `3.0` onwards integrated with the [OpenTelemetry Spring Boot Starter](https://opentelemetry.io/docs/zero-code/java/spring-boot-starter/). ## How to run? diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/src/main/resources/application.properties b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/src/main/resources/application.properties index 1c21d32049..402538a83a 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/src/main/resources/application.properties +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/src/main/resources/application.properties @@ -31,4 +31,8 @@ spring.graphql.graphiql.enabled=true spring.graphql.websocket.path=/graphql spring.quartz.job-store-type=memory +# OTEL configuration otel.propagators=tracecontext,baggage,sentry +otel.logs.exporter=none +otel.metrics.exporter=none +otel.traces.exporter=none diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/README.md b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/README.md index bd8d0af480..e8068dab25 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/README.md +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/README.md @@ -1,6 +1,6 @@ # Sentry Sample Spring Boot -Sample application showing how to use Sentry with [Spring boot](http://spring.io/projects/spring-boot). +Sample application showing how to use Sentry with [Spring boot](http://spring.io/projects/spring-boot) integrated with the [OpenTelemetry Spring Boot Starter](https://opentelemetry.io/docs/zero-code/java/spring-boot-starter/). ## How to run? diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/src/main/resources/application.properties b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/src/main/resources/application.properties index c7402eacc2..43d84aeb41 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/src/main/resources/application.properties +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/src/main/resources/application.properties @@ -23,3 +23,9 @@ spring.datasource.username=sa spring.datasource.password= spring.graphql.graphiql.enabled=true spring.graphql.websocket.path=/graphql + +# OTEL configuration +otel.propagators=tracecontext,baggage,sentry +otel.logs.exporter=none +otel.metrics.exporter=none +otel.traces.exporter=none From 4fa43273e9f9907b075a1ed83ed9fd52bfec1652 Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Tue, 10 Dec 2024 16:10:51 +0100 Subject: [PATCH 02/12] update readme for console - noagent --- .../sentry-samples-console-opentelemetry-noagent/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry-samples/sentry-samples-console-opentelemetry-noagent/README.md b/sentry-samples/sentry-samples-console-opentelemetry-noagent/README.md index 9e4b9e3e8a..bc918c5824 100644 --- a/sentry-samples/sentry-samples-console-opentelemetry-noagent/README.md +++ b/sentry-samples/sentry-samples-console-opentelemetry-noagent/README.md @@ -1,6 +1,6 @@ # Sentry Sample Console -Sample application showing how to use Sentry manually without any framework integration. +Sample application showing how to use Sentry with OpenTelemetry manually without any framework integration and without java agent. ## How to run? From 44d5b429da3b780eda69633c3b91d65485dd6aab Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Tue, 10 Dec 2024 16:24:53 +0100 Subject: [PATCH 03/12] update opentelemetry and optentelemetry agent readme --- sentry-opentelemetry/README.md | 35 +++++++++++++++++-- .../sentry-opentelemetry-agent/README.md | 7 +--- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/sentry-opentelemetry/README.md b/sentry-opentelemetry/README.md index 02c5e3f1ae..47a8113568 100644 --- a/sentry-opentelemetry/README.md +++ b/sentry-opentelemetry/README.md @@ -21,8 +21,7 @@ application. Please see the module [README](sentry-opentelemetry-agent/README.md This contains customizations to the OpenTelemetry Java Agent such as registering the `SentrySpanProcessor` and `SentryPropagator` as well as providing default properties that -enable the `sentry` propagator and disable exporters so our agent doesn't trigger lots of log -warnings due to OTLP server not being there. This can also be used without the agent. +enable the `sentry` propagator. This can also be used without the agent. ### `sentry-opentelemetry-bootstrap` @@ -40,3 +39,35 @@ Contains `SentrySpanProcessor` and `SentryPropagator` which are used by our Java be used when manually instrumenting using OpenTelemetry. If you want to use OpenTelemetry without the agent but still want some configuration convenience, you should rather use the `sentry-opentelemetry-agentcustomization` module. + +## Running without an Agent +If you want to use Sentry with OpenTelemetry without an agent, you can do so by adding the `sentry-opentelemetry-agentcustomization` +and `sentryopentelemetry-bootstrap` modules as dependencies to your project. + +You can then initialize Sentry with OpenTelemetry like this: + +```java +// Initialize OpenTelemetry by using the AutoConfiguredOpenTelemetrySdk which automatically +// registers the `SentrySpanProcessor` and `SentryPropagator` and others. +// Additionally, you can disable the OTEL exporters to avoid seeing error messages in the logs. +final OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.builder() + .addPropertiesSupplier(() -> { + final Map properties = new HashMap<>(); + properties.put("otel.logs.exporter", "none"); + properties.put("otel.metrics.exporter", "none"); + properties.put("otel.traces.exporter", "none"); + return properties; + }) + .build().getOpenTelemetrySdk(); + +// Set the global OpenTelemetry instance +GlobalOpenTelemetry.set(sdk); + +// Initialize Sentry +Sentry.init( + options -> { + options.setDsn("..."); + ... + } +) +``` diff --git a/sentry-opentelemetry/sentry-opentelemetry-agent/README.md b/sentry-opentelemetry/sentry-opentelemetry-agent/README.md index 92ddb89a1c..321f1b2696 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-agent/README.md +++ b/sentry-opentelemetry/sentry-opentelemetry-agent/README.md @@ -22,22 +22,17 @@ For more details on configuring Sentry via `sentry.properties` please see the As an alternative to the `SENTRY_PROPERTIES_FILE` environment variable you can provide individual settings as environment variables (e.g. `SENTRY_DSN=...`) or you may initialize `Sentry` inside -your target application. If you do so, please make sure to set the `instrumenter` to `otel`, e.g. -like this: +your target application: ``` Sentry.init( options -> { options.setDsn("..."); ... - options.setInstrumenter(Instrumenter.OTEL); } ) ``` -Using the `otel` instrumenter will ensure `Sentry` instrumentation will be done via OpenTelemetry -and integrations as well as direct interactions with transactions and spans have no effect. - ## Controlling auto initialization of Sentry By default if you pass either `SENTRY_DSN` or `SENTRY_PROPERTIES_FILE` as environment variable, From 3d8511bf4e3cc413813f17420bb9e7f87d7e396f Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Tue, 10 Dec 2024 16:27:16 +0100 Subject: [PATCH 04/12] bind transaction to scope so that the message is attached to the trace --- .../src/main/java/io/sentry/samples/console/Main.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java b/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java index a0c0d5dd9e..e12ab5a0db 100644 --- a/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java +++ b/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java @@ -86,10 +86,10 @@ public static void main(String[] args) throws InterruptedException { options.setTracesSampler( context -> { // only 10% of transactions with "/product" prefix will be collected - if (!context.getTransactionContext().getName().startsWith("/products")) { + if (context.getTransactionContext().getName().startsWith("/products")) { return 0.1; } else { - return 0.5; + return 1.0; } }); }); @@ -155,7 +155,9 @@ public static void main(String[] args) throws InterruptedException { // // Transactions collect execution time of the piece of code that's executed between the start // and finish of transaction. - ITransaction transaction = Sentry.startTransaction("transaction name", "op"); + final TransactionOptions options = new TransactionOptions(); + options.setBindToScope(true); + ITransaction transaction = Sentry.startTransaction("transaction name", "op", options); // Transactions can contain one or more Spans ISpan outerSpan = transaction.startChild("child"); Thread.sleep(100); From cb5dec263cfadc3d08a401aaf373dd84f0b0dc9a Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Tue, 10 Dec 2024 16:28:37 +0100 Subject: [PATCH 05/12] initialize otel using AutoConfiguredOpenTelemetrySdk to bind SPI provided classes --- .../java/io/sentry/samples/console/Main.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java b/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java index c27aad737b..deed2f6ec4 100644 --- a/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java +++ b/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java @@ -4,6 +4,9 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.StatusCode; import io.opentelemetry.context.Scope; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder; import io.sentry.Breadcrumb; import io.sentry.EventProcessor; import io.sentry.Hint; @@ -17,10 +20,23 @@ import io.sentry.protocol.Message; import io.sentry.protocol.User; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; public class Main { public static void main(String[] args) throws InterruptedException { + final OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.builder() + .addPropertiesSupplier(() -> { + final Map properties = new HashMap<>(); + properties.put("otel.logs.exporter", "none"); + properties.put("otel.metrics.exporter", "none"); + properties.put("otel.traces.exporter", "none"); + return properties; + }) + .build().getOpenTelemetrySdk(); + GlobalOpenTelemetry.set(sdk); + Sentry.init( options -> { // NOTE: Replace the test DSN below with YOUR OWN DSN to see the events from this app in From 4ab84f202851d91bb12d396594d4c4c8fd0bdf3b Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Tue, 10 Dec 2024 15:37:06 +0000 Subject: [PATCH 06/12] Format code --- .../java/io/sentry/samples/console/Main.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java b/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java index deed2f6ec4..c840d6652b 100644 --- a/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java +++ b/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java @@ -6,7 +6,6 @@ import io.opentelemetry.context.Scope; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder; import io.sentry.Breadcrumb; import io.sentry.EventProcessor; import io.sentry.Hint; @@ -26,15 +25,18 @@ public class Main { public static void main(String[] args) throws InterruptedException { - final OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.builder() - .addPropertiesSupplier(() -> { - final Map properties = new HashMap<>(); - properties.put("otel.logs.exporter", "none"); - properties.put("otel.metrics.exporter", "none"); - properties.put("otel.traces.exporter", "none"); - return properties; - }) - .build().getOpenTelemetrySdk(); + final OpenTelemetrySdk sdk = + AutoConfiguredOpenTelemetrySdk.builder() + .addPropertiesSupplier( + () -> { + final Map properties = new HashMap<>(); + properties.put("otel.logs.exporter", "none"); + properties.put("otel.metrics.exporter", "none"); + properties.put("otel.traces.exporter", "none"); + return properties; + }) + .build() + .getOpenTelemetrySdk(); GlobalOpenTelemetry.set(sdk); Sentry.init( From 2286edd80d693624f33d7738216b5f3ca782929b Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Tue, 10 Dec 2024 17:06:41 +0100 Subject: [PATCH 07/12] format, make transaction current, so that it is sent to sentry --- .../java/io/sentry/samples/console/Main.java | 85 ++++++++++--------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java b/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java index deed2f6ec4..bb5f61a07b 100644 --- a/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java +++ b/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java @@ -6,7 +6,6 @@ import io.opentelemetry.context.Scope; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder; import io.sentry.Breadcrumb; import io.sentry.EventProcessor; import io.sentry.Hint; @@ -26,15 +25,18 @@ public class Main { public static void main(String[] args) throws InterruptedException { - final OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.builder() - .addPropertiesSupplier(() -> { - final Map properties = new HashMap<>(); - properties.put("otel.logs.exporter", "none"); - properties.put("otel.metrics.exporter", "none"); - properties.put("otel.traces.exporter", "none"); - return properties; - }) - .build().getOpenTelemetrySdk(); + final OpenTelemetrySdk sdk = + AutoConfiguredOpenTelemetrySdk.builder() + .addPropertiesSupplier( + () -> { + final Map properties = new HashMap<>(); + properties.put("otel.logs.exporter", "none"); + properties.put("otel.metrics.exporter", "none"); + properties.put("otel.traces.exporter", "none"); + return properties; + }) + .build() + .getOpenTelemetrySdk(); GlobalOpenTelemetry.set(sdk); Sentry.init( @@ -180,40 +182,47 @@ public static void main(String[] args) throws InterruptedException { // Transactions collect execution time of the piece of code that's executed between the start // and finish of transaction. ITransaction transaction = Sentry.startTransaction("transaction name", "op"); - // Transactions can contain one or more Spans - ISpan outerSpan = transaction.startChild("child"); - Thread.sleep(100); - // Spans create a tree structure. Each span can have one ore more spans inside. - ISpan innerSpan = outerSpan.startChild("jdbc", "select * from product where id = :id"); - innerSpan.setStatus(SpanStatus.OK); - Thread.sleep(300); - // Finish the span and mark the end time of the span execution. - // Note: finishing spans does not send them to Sentry - innerSpan.finish(); - try (ISentryLifecycleToken outerScope = outerSpan.makeCurrent()) { - Span otelSpan = - GlobalOpenTelemetry.get() - .getTracer("demoTracer", "1.0.0") - .spanBuilder("otelSpan") - .startSpan(); - try (Scope innerScope = otelSpan.makeCurrent()) { - otelSpan.setAttribute("otel-attribute", "attribute-value"); - Thread.sleep(150); - otelSpan.setStatus(StatusCode.OK); + try (ISentryLifecycleToken transactionScope = transaction.makeCurrent()) { + // Transactions can contain one or more Spans + ISpan outerSpan = transaction.startChild("child"); + Thread.sleep(100); + // Spans create a tree structure. Each span can have one ore more spans inside. + ISpan innerSpan = outerSpan.startChild("jdbc", "select * from product where id = :id"); + innerSpan.setStatus(SpanStatus.OK); + Thread.sleep(300); + // Finish the span and mark the end time of the span execution. + // Note: finishing spans does not send them to Sentry + innerSpan.finish(); + try (ISentryLifecycleToken outerScope = outerSpan.makeCurrent()) { + Span otelSpan = + GlobalOpenTelemetry.get() + .getTracer("demoTracer", "1.0.0") + .spanBuilder("otelSpan") + .startSpan(); + try (Scope innerScope = otelSpan.makeCurrent()) { + otelSpan.setAttribute("otel-attribute", "attribute-value"); + Thread.sleep(150); + otelSpan.setStatus(StatusCode.OK); + } finally { + otelSpan.end(); + } + // Every SentryEvent reported during the execution of the transaction or a span, will have + // trace + // context attached + Sentry.captureException( + new RuntimeException("this exception is connected to the outerSpan")); + } finally { - otelSpan.end(); + outerSpan.finish(SpanStatus.OK); } + } finally { + // marks transaction as finished and sends it together with all child spans to Sentry + transaction.finish(); } - // Every SentryEvent reported during the execution of the transaction or a span, will have trace - // context attached - Sentry.captureMessage("this message is connected to the outerSpan"); - outerSpan.finish(); - // marks transaction as finished and sends it together with all child spans to Sentry - transaction.finish(); // All events that have not been sent yet are being flushed on JVM exit. Events can be also // flushed manually: - // Sentry.close(); + // Sentry.close(); } private static class SomeEventProcessor implements EventProcessor { From 1c79edfb6e4eabb94dace49293de4f3a8cc8ed2b Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Mon, 16 Dec 2024 08:38:53 +0100 Subject: [PATCH 08/12] fix import --- .../src/main/java/io/sentry/samples/console/Main.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java b/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java index e12ab5a0db..dbcb30063c 100644 --- a/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java +++ b/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java @@ -9,6 +9,7 @@ import io.sentry.SentryEvent; import io.sentry.SentryLevel; import io.sentry.SpanStatus; +import io.sentry.TransactionOptions; import io.sentry.protocol.Message; import io.sentry.protocol.User; import java.util.Collections; From 8e9ce937f3d730d5d7e84ebfb3078186f3e78f0c Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Tue, 17 Dec 2024 12:36:26 +0100 Subject: [PATCH 09/12] add java options and new agentless module to readme --- sentry-opentelemetry/README.md | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/sentry-opentelemetry/README.md b/sentry-opentelemetry/README.md index 47a8113568..fcd352d52e 100644 --- a/sentry-opentelemetry/README.md +++ b/sentry-opentelemetry/README.md @@ -21,7 +21,7 @@ application. Please see the module [README](sentry-opentelemetry-agent/README.md This contains customizations to the OpenTelemetry Java Agent such as registering the `SentrySpanProcessor` and `SentryPropagator` as well as providing default properties that -enable the `sentry` propagator. This can also be used without the agent. +enable the `sentry` propagator. ### `sentry-opentelemetry-bootstrap` @@ -38,31 +38,42 @@ you also need this module as a dependency. Contains `SentrySpanProcessor` and `SentryPropagator` which are used by our Java Agent but can also be used when manually instrumenting using OpenTelemetry. If you want to use OpenTelemetry without the agent but still want some configuration convenience, you should rather use the -`sentry-opentelemetry-agentcustomization` module. +`sentry-opentelemetry-agentless` module. + +### `sentry-opentelemetry-agentless` +Combines all modules and dependencies needed to use Sentry with OpenTelemetry without the agent. ## Running without an Agent -If you want to use Sentry with OpenTelemetry without an agent, you can do so by adding the `sentry-opentelemetry-agentcustomization` -and `sentryopentelemetry-bootstrap` modules as dependencies to your project. +If you want to use Sentry with OpenTelemetry without an agent, you can do so by adding the `sentry-opentelemetry-agentless` module as dependencies to your project. + +And run your application with the following JVM arguments: +``` +-Dotel.java.global-autoconfigure.enabled=true +``` +You may also want to set the following environment variables to if you do not use OTEL exporters: +`OTEL_LOGS_EXPORTER=none;OTEL_METRICS_EXPORTER=none;OTEL_TRACES_EXPORTER=none` -You can then initialize Sentry with OpenTelemetry like this: +Alternatively you can initialize OpenTelemetry programmatically like this: ```java // Initialize OpenTelemetry by using the AutoConfiguredOpenTelemetrySdk which automatically // registers the `SentrySpanProcessor` and `SentryPropagator` and others. -// Additionally, you can disable the OTEL exporters to avoid seeing error messages in the logs. -final OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.builder() +// Also, you need to disable the OTEL exporters if you do not use them. +AutoConfiguredOpenTelemetrySdk.builder() + .setResultAsGlobal() .addPropertiesSupplier(() -> { - final Map properties = new HashMap<>(); +final Map properties = new HashMap<>(); properties.put("otel.logs.exporter", "none"); properties.put("otel.metrics.exporter", "none"); properties.put("otel.traces.exporter", "none"); return properties; }) - .build().getOpenTelemetrySdk(); + .build(); +``` -// Set the global OpenTelemetry instance -GlobalOpenTelemetry.set(sdk); +And then initialize Sentry as usual: +```java // Initialize Sentry Sentry.init( options -> { From 0926957cea21e2565d670b6de77f7e42f6f7b5fe Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Tue, 7 Jan 2025 16:17:06 +0100 Subject: [PATCH 10/12] update readmes --- sentry-opentelemetry/README.md | 5 +- .../sentry-opentelemetry-agent/README.md | 23 ++++--- .../README.md | 54 ++++------------- .../sentry-opentelemetry-agentless/README.md | 60 ++++++++++--------- .../README.md | 2 +- 5 files changed, 62 insertions(+), 82 deletions(-) diff --git a/sentry-opentelemetry/README.md b/sentry-opentelemetry/README.md index fcd352d52e..6391fd32ca 100644 --- a/sentry-opentelemetry/README.md +++ b/sentry-opentelemetry/README.md @@ -38,11 +38,14 @@ you also need this module as a dependency. Contains `SentrySpanProcessor` and `SentryPropagator` which are used by our Java Agent but can also be used when manually instrumenting using OpenTelemetry. If you want to use OpenTelemetry without the agent but still want some configuration convenience, you should rather use the -`sentry-opentelemetry-agentless` module. +`sentry-opentelemetry-agentless` module or the `sentry-opentelemetry-agentless-spring` module if you are using Spring Boot. ### `sentry-opentelemetry-agentless` Combines all modules and dependencies needed to use Sentry with OpenTelemetry without the agent. +### `sentry-opentelemetry-agentless-spring` +Combines all modules and dependencies needed to use Sentry with OpenTelemetry in SpringBoot without an agent. + ## Running without an Agent If you want to use Sentry with OpenTelemetry without an agent, you can do so by adding the `sentry-opentelemetry-agentless` module as dependencies to your project. diff --git a/sentry-opentelemetry/sentry-opentelemetry-agent/README.md b/sentry-opentelemetry/sentry-opentelemetry-agent/README.md index 321f1b2696..55646f3b16 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-agent/README.md +++ b/sentry-opentelemetry/sentry-opentelemetry-agent/README.md @@ -21,8 +21,14 @@ For more details on configuring Sentry via `sentry.properties` please see the [docs page](https://docs.sentry.io/platforms/java/configuration/). As an alternative to the `SENTRY_PROPERTIES_FILE` environment variable you can provide individual -settings as environment variables (e.g. `SENTRY_DSN=...`) or you may initialize `Sentry` inside -your target application: +settings as environment variables (e.g. `SENTRY_DSN=...`). + +## Controlling auto initialization of Sentry + +By default, if you pass either `SENTRY_DSN` or `SENTRY_PROPERTIES_FILE` as environment variable, +Sentry will automatically be initialized by this agent. To disable this behaviour, you can set +`SENTRY_AUTO_INIT=false` as environment variable. You will then have to initialize Sentry inside +the target application: ``` Sentry.init( @@ -33,13 +39,6 @@ Sentry.init( ) ``` -## Controlling auto initialization of Sentry - -By default if you pass either `SENTRY_DSN` or `SENTRY_PROPERTIES_FILE` as environment variable, -Sentry will automatically be initialized by this agent. To disable this behaviour, you can set -`SENTRY_AUTO_INIT=false` as environment variable. You will then have to initialize Sentry inside -the target application. - ## Debugging To enable debug logging for Sentry, please provide `SENTRY_DEBUG=true` as environment variable or @@ -57,6 +56,7 @@ Example log message: ``` ERROR io.opentelemetry.exporter.internal.grpc.OkHttpGrpcExporter - Failed to export spans. The request could not be executed. Full error message: Failed to connect to localhost/[0:0:0:0:0:0:0:1]:4317 ERROR io.opentelemetry.exporter.internal.grpc.OkHttpGrpcExporter - Failed to export metrics. The request could not be executed. Full error message: Failed to connect to localhost/[0:0:0:0:0:0:0:1]:4317 +ERROR io.opentelemetry.exporter.internal.http.HttpExporter - Failed to export logs. The request could not be executed. Full error message: Failed to connect to localhost/[0:0:0:0:0:0:0:1]:4318 ``` ### Traces @@ -68,3 +68,8 @@ see [OpenTelemetry GitHub](https://github.com/open-telemetry/opentelemetry-java/ To turn off exporting of metrics you can set `OTEL_METRICS_EXPORTER=none` see [OpenTelemetry GitHub](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure#otlp-exporter-span-metric-and-log-exporters) + +### Logs + +To turn off log exporting, set `OTEL_LOGS_EXPORTER=none` +see [OpenTelemetry GitHub](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure#otlp-exporter-span-metric-and-log-exporters). diff --git a/sentry-opentelemetry/sentry-opentelemetry-agentless-spring/README.md b/sentry-opentelemetry/sentry-opentelemetry-agentless-spring/README.md index b808195c90..7fda913fac 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-agentless-spring/README.md +++ b/sentry-opentelemetry/sentry-opentelemetry-agentless-spring/README.md @@ -2,53 +2,21 @@ *NOTE: Our OpenTelemetry modules are still experimental. Any feedback is welcome.* +This module allows the use of Sentry with OpenTelemetry in SpringBoot without an agent by using the OpenTelemetry Spring Boot Starter. +For guidance on when to use this module instead of the agent, please have a look at the [OpenTelemetry Spring Boot Starter documentation](https://opentelemetry.io/docs/zero-code/java/spring-boot-starter/). + ## How to use it -Add the latest `sentry-opentelemetry-agentless-spring` module as a dependency and add a `sentry.properties` -configuration file to your project that could look like this: +Add the latest `sentry-opentelemetry-agentless-spring` module as a dependency to your Sentry enabled [SpringBoot](https://docs.sentry.io/platforms/java/guides/spring-boot/) application and add the following to your `application.properties`: ```properties -# NOTE: Replace the test DSN below with YOUR OWN DSN to see the events from this app in your Sentry project/dashboard -dsn=https://502f25099c204a2fbf4cb16edc5975d1@o447951.ingest.sentry.io/5428563 -traces-sample-rate=1.0 +# OTEL configuration +otel.propagators=tracecontext,baggage,sentry +otel.logs.exporter=none +otel.metrics.exporter=none +otel.traces.exporter=none ``` -For more details on configuring Sentry via `sentry.properties` please see the -[docs page](https://docs.sentry.io/platforms/java/configuration/). - -As an alternative to the `SENTRY_PROPERTIES_FILE` environment variable you can provide individual -settings as environment variables (e.g. `SENTRY_DSN=...`) or you may initialize `Sentry` inside -your target application. If you do so, please make sure to apply OpenTelemetry specific options, e.g. -like this: - -``` -Sentry.init( - options -> { - options.setDsn("..."); - ... - OpenTelemetryUtil.applyOpenTelemetryOptions(options, false); - } -) -``` - -## Getting rid of exporter error messages - -In case you are using this module without needing to use any OpenTelemetry exporters you can add -the following environment variables to turn off exporters and stop seeing error messages about -servers not being reachable in the logs. - -Example log message: -``` -ERROR io.opentelemetry.exporter.internal.grpc.OkHttpGrpcExporter - Failed to export spans. The request could not be executed. Full error message: Failed to connect to localhost/[0:0:0:0:0:0:0:1]:4317 -ERROR io.opentelemetry.exporter.internal.grpc.OkHttpGrpcExporter - Failed to export metrics. The request could not be executed. Full error message: Failed to connect to localhost/[0:0:0:0:0:0:0:1]:4317 -``` - -### Traces - -To turn off exporting of traces you can set `OTEL_TRACES_EXPORTER=none` -see [OpenTelemetry GitHub](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure#otlp-exporter-span-metric-and-log-exporters) - -### Metrics +This module will automatically configure OpenTelemetry and Sentry for you. -To turn off exporting of metrics you can set `OTEL_METRICS_EXPORTER=none` -see [OpenTelemetry GitHub](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure#otlp-exporter-span-metric-and-log-exporters) +With the dependency and configuration in place, just run your SpringBoot application as usual. diff --git a/sentry-opentelemetry/sentry-opentelemetry-agentless/README.md b/sentry-opentelemetry/sentry-opentelemetry-agentless/README.md index 9ce3319bae..7fd9ee156b 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-agentless/README.md +++ b/sentry-opentelemetry/sentry-opentelemetry-agentless/README.md @@ -17,38 +17,42 @@ For more details on configuring Sentry via `sentry.properties` please see the [docs page](https://docs.sentry.io/platforms/java/configuration/). As an alternative to the `SENTRY_PROPERTIES_FILE` environment variable you can provide individual -settings as environment variables (e.g. `SENTRY_DSN=...`) or you may initialize `Sentry` inside -your target application. If you do so, please make sure to apply OpenTelemetry specific options, e.g. -like this: +settings as environment variables (e.g. `SENTRY_DSN=...`). +Run your application with the following JVM arguments: ``` -Sentry.init( - options -> { - options.setDsn("..."); - ... - OpenTelemetryUtil.applyOpenTelemetryOptions(options, false); - } -) +-Dotel.java.global-autoconfigure.enabled=true ``` -## Getting rid of exporter error messages - -In case you are using this module without needing to use any OpenTelemetry exporters you can add -the following environment variables to turn off exporters and stop seeing error messages about -servers not being reachable in the logs. - -Example log message: -``` -ERROR io.opentelemetry.exporter.internal.grpc.OkHttpGrpcExporter - Failed to export spans. The request could not be executed. Full error message: Failed to connect to localhost/[0:0:0:0:0:0:0:1]:4317 -ERROR io.opentelemetry.exporter.internal.grpc.OkHttpGrpcExporter - Failed to export metrics. The request could not be executed. Full error message: Failed to connect to localhost/[0:0:0:0:0:0:0:1]:4317 +You may also want to set the following environment variables to if you do not use OTEL exporters: +`OTEL_LOGS_EXPORTER=none;OTEL_METRICS_EXPORTER=none;OTEL_TRACES_EXPORTER=none` + +Alternatively you can initialize OpenTelemetry programmatically like this: + +```java +// Initialize OpenTelemetry by using the AutoConfiguredOpenTelemetrySdk which automatically +// registers the `SentrySpanProcessor` and `SentryPropagator` and others. +// Also, you need to disable the OTEL exporters if you do not use them. +AutoConfiguredOpenTelemetrySdk.builder() + .setResultAsGlobal() + .addPropertiesSupplier(() -> { +final Map properties = new HashMap<>(); + properties.put("otel.logs.exporter", "none"); + properties.put("otel.metrics.exporter", "none"); + properties.put("otel.traces.exporter", "none"); + return properties; + }) + .build(); ``` -### Traces +If you're not using `sentry.properties` or environment variables you can then initialize Sentry programmatically as usual: -To turn off exporting of traces you can set `OTEL_TRACES_EXPORTER=none` -see [OpenTelemetry GitHub](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure#otlp-exporter-span-metric-and-log-exporters) - -### Metrics - -To turn off exporting of metrics you can set `OTEL_METRICS_EXPORTER=none` -see [OpenTelemetry GitHub](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure#otlp-exporter-span-metric-and-log-exporters) +```java +// Initialize Sentry +Sentry.init( + options -> { + options.setDsn("..."); + ... + } +) +``` diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/README.md b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/README.md index 89a8e603a3..4a5f2a7739 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/README.md +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/README.md @@ -1,6 +1,6 @@ # Sentry Sample Spring Boot 3.0+ -Sample application showing how to use Sentry with [Spring boot](http://spring.io/projects/spring-boot) from version `3.0` onwards integrated with the [OpenTelemetry Spring Boot Starter](https://opentelemetry.io/docs/zero-code/java/spring-boot-starter/). +Sample application showing how to use Sentry with [Spring boot](http://spring.io/projects/spring-boot) from version `3.0` onwards integrated with the [OpenTelemetry Spring Boot Starter](https://opentelemetry.io/docs/zero-code/java/spring-boot-starter/) without an agent. ## How to run? From ef4ff97add434417d089d4fcce6ebb3705b27629 Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Mon, 13 Jan 2025 09:05:01 +0100 Subject: [PATCH 11/12] fix typos, add comment about attaching transaction to scope, use shorter OTEL AutoInit --- .../java/io/sentry/samples/console/Main.java | 32 +++++++++---------- .../java/io/sentry/samples/console/Main.java | 3 +- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java b/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java index bb5f61a07b..bda2b700a3 100644 --- a/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java +++ b/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java @@ -25,19 +25,17 @@ public class Main { public static void main(String[] args) throws InterruptedException { - final OpenTelemetrySdk sdk = - AutoConfiguredOpenTelemetrySdk.builder() - .addPropertiesSupplier( - () -> { - final Map properties = new HashMap<>(); - properties.put("otel.logs.exporter", "none"); - properties.put("otel.metrics.exporter", "none"); - properties.put("otel.traces.exporter", "none"); - return properties; - }) - .build() - .getOpenTelemetrySdk(); - GlobalOpenTelemetry.set(sdk); + + AutoConfiguredOpenTelemetrySdk.builder() + .setResultAsGlobal() + .addPropertiesSupplier( () -> { + final Map properties = new HashMap<>(); + properties.put("otel.logs.exporter", "none"); + properties.put("otel.metrics.exporter", "none"); + properties.put("otel.traces.exporter", "none"); + return properties; + }) + .build(); Sentry.init( options -> { @@ -181,12 +179,13 @@ public static void main(String[] args) throws InterruptedException { // // Transactions collect execution time of the piece of code that's executed between the start // and finish of transaction. + // Transactions need to be bound to scope in order to have `Messages` or `Exceptions` linked to them ITransaction transaction = Sentry.startTransaction("transaction name", "op"); try (ISentryLifecycleToken transactionScope = transaction.makeCurrent()) { // Transactions can contain one or more Spans ISpan outerSpan = transaction.startChild("child"); Thread.sleep(100); - // Spans create a tree structure. Each span can have one ore more spans inside. + // Spans create a tree structure. Each span can have one or more spans inside. ISpan innerSpan = outerSpan.startChild("jdbc", "select * from product where id = :id"); innerSpan.setStatus(SpanStatus.OK); Thread.sleep(300); @@ -209,8 +208,7 @@ public static void main(String[] args) throws InterruptedException { // Every SentryEvent reported during the execution of the transaction or a span, will have // trace // context attached - Sentry.captureException( - new RuntimeException("this exception is connected to the outerSpan")); + Sentry.captureMessage("this message is connected to the outerSpan"); } finally { outerSpan.finish(SpanStatus.OK); @@ -222,7 +220,7 @@ public static void main(String[] args) throws InterruptedException { // All events that have not been sent yet are being flushed on JVM exit. Events can be also // flushed manually: - // Sentry.close(); + // Sentry.close(); } private static class SomeEventProcessor implements EventProcessor { diff --git a/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java b/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java index dbcb30063c..c020593503 100644 --- a/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java +++ b/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java @@ -156,13 +156,14 @@ public static void main(String[] args) throws InterruptedException { // // Transactions collect execution time of the piece of code that's executed between the start // and finish of transaction. + // Transactions need to be bound to scope in order to have `Messages` or `Exceptions` linked to them final TransactionOptions options = new TransactionOptions(); options.setBindToScope(true); ITransaction transaction = Sentry.startTransaction("transaction name", "op", options); // Transactions can contain one or more Spans ISpan outerSpan = transaction.startChild("child"); Thread.sleep(100); - // Spans create a tree structure. Each span can have one ore more spans inside. + // Spans create a tree structure. Each span can have one or more spans inside. ISpan innerSpan = outerSpan.startChild("jdbc", "select * from product where id = :id"); innerSpan.setStatus(SpanStatus.OK); Thread.sleep(300); From 1836553ccd38ada3de99d63c52ba57617aad8312 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Mon, 13 Jan 2025 08:08:44 +0000 Subject: [PATCH 12/12] Format code --- .../java/io/sentry/samples/console/Main.java | 23 ++++++++++--------- .../java/io/sentry/samples/console/Main.java | 3 ++- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java b/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java index bda2b700a3..3cb4293b14 100644 --- a/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java +++ b/sentry-samples/sentry-samples-console-opentelemetry-noagent/src/main/java/io/sentry/samples/console/Main.java @@ -4,7 +4,6 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.StatusCode; import io.opentelemetry.context.Scope; -import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.sentry.Breadcrumb; import io.sentry.EventProcessor; @@ -27,15 +26,16 @@ public class Main { public static void main(String[] args) throws InterruptedException { AutoConfiguredOpenTelemetrySdk.builder() - .setResultAsGlobal() - .addPropertiesSupplier( () -> { - final Map properties = new HashMap<>(); - properties.put("otel.logs.exporter", "none"); - properties.put("otel.metrics.exporter", "none"); - properties.put("otel.traces.exporter", "none"); - return properties; - }) - .build(); + .setResultAsGlobal() + .addPropertiesSupplier( + () -> { + final Map properties = new HashMap<>(); + properties.put("otel.logs.exporter", "none"); + properties.put("otel.metrics.exporter", "none"); + properties.put("otel.traces.exporter", "none"); + return properties; + }) + .build(); Sentry.init( options -> { @@ -179,7 +179,8 @@ public static void main(String[] args) throws InterruptedException { // // Transactions collect execution time of the piece of code that's executed between the start // and finish of transaction. - // Transactions need to be bound to scope in order to have `Messages` or `Exceptions` linked to them + // Transactions need to be bound to scope in order to have `Messages` or `Exceptions` linked to + // them ITransaction transaction = Sentry.startTransaction("transaction name", "op"); try (ISentryLifecycleToken transactionScope = transaction.makeCurrent()) { // Transactions can contain one or more Spans diff --git a/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java b/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java index c020593503..d17c683aec 100644 --- a/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java +++ b/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java @@ -156,7 +156,8 @@ public static void main(String[] args) throws InterruptedException { // // Transactions collect execution time of the piece of code that's executed between the start // and finish of transaction. - // Transactions need to be bound to scope in order to have `Messages` or `Exceptions` linked to them + // Transactions need to be bound to scope in order to have `Messages` or `Exceptions` linked to + // them final TransactionOptions options = new TransactionOptions(); options.setBindToScope(true); ITransaction transaction = Sentry.startTransaction("transaction name", "op", options);