After writing this article I've revised my approach. See this follow up article for details. The approach below still works, with some caveats.
We are trying out Sentry for error alerting at Focused Labs, and I wanted to set it up in my Spring Boot backend. For the most part, Sentry has been super easy to add to a project, but I hit a few little snags with the Spring Boot integration that I wanted to share with the community.
I'll keep this short, this is what I ended up with:
build.gradle.kts
:
implementation("io.sentry:sentry-spring-boot-starter:1.7.30")
implementation("io.sentry:sentry-logback:1.7.30")
In some scenarios, this may lead to duplicate errors. The official docs warn against including both sentry-spring
(which is pulled in by sentry-spring-boot-starter
) and sentry-logback
. Which makes sense since the Spring integration with Sentry is handling exceptions and sending them to Sentry and the Logback integration is watching logs, and then sending them to Sentry.
We are using GraphQL in our backend, so the sentry-spring
behavior wasn't catching our exceptions since they are exclusively catching errors in the context of an MVC controller. Still, potentially, an exception would both be logged and caught by the Sentry exception handler, resulting in a duplicate error. If this becomes an issue, I'll have to revisit my dependencies.
This is why I am bothering with sentry-spring-boot-starter
application.yaml
:
---
sentry:
dsn: '<my-dsn>'
stacktrace:
app-packages:
- com.mypackage
spring:
profiles:
active: dev
---
spring:
profiles: dev
sentry:
enabled: false
environment: dev
---
spring:
profiles: production
sentry:
environment: production
Sweet sweet YAML.
Thanks to the configuration support in sentry-spring-boot-starter
I can just locate my Sentry configuration right next to the rest of my Spring Boot configuration.
logback-spring.xml
:
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<appender name="SENTRY" class="io.sentry.logback.SentryAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="SENTRY"/>
</root>
</configuration>
By using include
here, I am able to defer to the default Spring Boot log configuration and only override what I absolutely need to. In this case, adding an additional appender to the root
logger.
And that's it! It looks straight forward when laid out here, but took a few iterations to get everything working. Hopefully, this helps other people out with the same process.
Top comments (2)
Great article! It's true that the duplicate event captured isn't ideal but sounds like we can solve that with a dedupe strategy based on weakref. We've done that in different SDKs.
Raised an issue here: github.com/getsentry/sentry-java/i...
Thanks! Glad it was helpful.