sentry-java icon indicating copy to clipboard operation
sentry-java copied to clipboard

SDK for Quarkus

Open henka-rl opened this issue 2 years ago • 13 comments

Problem Statement

I would like Sentry to implement an SDK for Quarkus in the same way as for Spring Boot

Solution Brainstorm

No response

henka-rl avatar Sep 22 '22 06:09 henka-rl

Routing to @getsentry/team-mobile for triage. ⏲️

getsentry-release avatar Sep 22 '22 15:09 getsentry-release

Hello @henka-rl there seems to be https://github.com/quarkiverse/quarkus-logging-sentry . I'm not sure about the state of it. At the moment we don't have any concrete plans of adding any quarkus integration but if there are enough people asking for it we might look into it in the future. Which features would you like to see if we were to build an integration?

adinauer avatar Sep 23 '22 05:09 adinauer

@adinauer feel free to transfer this issue to sentry-java repo.

marandaneto avatar Sep 23 '22 06:09 marandaneto

Yes, I know about https://github.com/quarkiverse/quarkus-logging-sentry. But I believe that implementation just initialize Sentry. I can't see that is an automatic instrumentation for http as in your Spring Boot SDK. I would like to see the same features as you have for Spring Boot

henka-rl avatar Sep 23 '22 06:09 henka-rl

On the Quarkus side there is this issue: https://github.com/quarkusio/quarkus/issues/19798 It used to be on the Current quarter roadmap but no longer on the new planning.

sudo-plz avatar Dec 29 '22 09:12 sudo-plz

Yes, I know about https://github.com/quarkiverse/quarkus-logging-sentry. But I believe that implementation just initialize Sentry. I can't see that is an automatic instrumentation for http as in your Spring Boot SDK.

@henka-rl I don't know if this is still relevant to you 9 months after your original comment, but I just tried setting up quarkus-logging-sentry (version 2.0.1 as of writing this) and successfully got an error logged in Sentry by throwing an exception inside an HTTP endpoint

LaurentTreguier avatar May 29 '23 19:05 LaurentTreguier

@LaurentTreguier I believe what @henka-rl meant was transactions as in our performance product.

adinauer avatar May 30 '23 07:05 adinauer

Ah, I see; that makes more sense indeed

LaurentTreguier avatar May 30 '23 07:05 LaurentTreguier

Yes, it's support for transactions I'm looking for.

henka-rl avatar May 30 '23 10:05 henka-rl

After some research and quite a bit of head-scratching, I managed to get something using OpenTelemetry. Here are the general steps:

  • I made a Sentry extension very much like quarkus-logging-sentry, as a subproject of my main project
  • I added the following dependencies to said extension subproject:
    • io.quarkus:quarkus-opentelemetry (deployment and runtime)
    • io.sentry:sentry-opentelemetry-core (deployment and runtime)
    • io.sentry:sentry-jul (runtime only)
    • io.opentelemetry.instrumentation:opentelemetry-jdbc (runtime only)
  • Having the Sentry.init in my project means I could set it up for OpenTelemetry, as per Sentry's documentation
  • I made a bean producing a SentrySpanProcessor singleton, and added it to the extension's deployment processor since it is needed at runtime (it will get picked up by quarkus-opentelemetry)
  • I implemented a custom ConfigurablePropagatorProvider that provides a SentryPropagator with the "sentry" name
  • I added a META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.ConfigurablePropagatorProvider file with the fully qualified name of said propagator
  • Finally, I added quarkus.otel.propagators=tracecontext,baggage,sentry inside application.properties, making OpenTelemetry use the Sentry propagator

This should be all that's needed; although I'm guessing the new classes should also added as reflective classes in order to work in native builds (which I haven't tested).

All in all, it involves a bit of manual work; but I got call transactions in Sentry (correctly linked to issues when needed), as well as some JDBC stuff.

Edit 1: the result of my experimentation is here: https://github.com/fyreplace/fyreplace-api-quarkus

Edit 2 : I added a META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider with a value od io.quarkus.opentelemetry.runtime.tracing.spi.SpanExporterCDIProvider, as suggested in https://github.com/quarkusio/quarkus/discussions/33349, and it seemed to also work when building in native mode

LaurentTreguier avatar Jun 04 '23 09:06 LaurentTreguier

Thanks for sharing @LaurentTreguier. I guess the provider for SentryPropagator is something we could add to the SDK package itself. I've added it to https://github.com/getsentry/sentry-java/issues/2419

adinauer avatar Jun 05 '23 05:06 adinauer

Hello.

(Apologies in advance if this question should belong in it's own thread - I can create if needs be - but is related to this one.)

In the absence of a Quarkus SDK, what is the recommended way to manually instrument code for performance and error data given the reactive nature of a Quarkus app - see: https://quarkus.io/version/main/guides/mutiny-primer

Specifically for the setting of tags that only relate to the current request (like a user_id pulled from jwt token passed with the an API request). Reading the docs it wasn't clear to me how scopes should be used in the context of a Quarkus app.

In the example below I am using the SLF4J mapped diagnostic context (MDC) to store a user_id at the start of an API request then using beforeSend and beforeSendTransaction to set it on the event.

Is this a safe and acceptable pattern? Are there other recommendations?

Thanks - Colin

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import io.quarkus.runtime.StartupEvent;

@ApplicationScoped
public class SentryConfig {

  void onStart(@Observes StartupEvent ev) {
    Sentry.init(
      options -> {
          options.setDsn("https://my.dsn");
          options.setTracesSampleRate(1.0);
          options.setEnvironment("development");
          options.setTag("global_tag", "always-the-same");
          options.setBeforeSend((event, hint) -> {
              event.setTag("user_id", MDC.get("user_id"));
              return event;
          });
          options.setBeforeSendTransaction((event, hint) -> {
              event.setTag("user_id", MDC.get("user_id"));
              return event;
          });
      });

colin-mckenzie-addepar avatar Nov 10 '23 16:11 colin-mckenzie-addepar

@colin-mckenzie-addepar I'm not familiar with Quarkus but this should work in theory. Maybe another Quarkus user can help you out here in case you run into problems.

adinauer avatar Nov 13 '23 07:11 adinauer