Pular para conteúdo

Observabilidade — Sentry/GlitchTip

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-07-13

Recipe da casa: captura todo log ERROR (inclui exceção não-tratada) sem tocar o negócio, via o SentryAppender do logback. Não há mais o plugin io.sentry.jvm.gradle (era inerte — source context e auto-install desligados).

  • Dependência: io.sentry:sentry-logback (traz o sentry-core transitivo; a API io.sentry.Sentry continua disponível para capturas explícitas/breadcrumbs).
  • logback.xml: um <appender name="SENTRY" class="io.sentry.logback.SentryAppender"> com minimumEventLevel=ERROR, referenciado no <root>. Sem <dsn> no appender de propósito.
  • SentryInitializer.initFromEnvironment() faz o Sentry.init() no main(), ANTES de Micronaut.run — a partir de SENTRY_DSN, só em prod (não em dev/test, via MICRONAUT_ENVIRONMENTS). Sem DSN → Sentry desabilitado → o appender vira no-op (não spamma). Inicializar antes do contexto é de propósito: um crash de startup (ex.: validação Flyway ao criar o DataSource) precisa sair com a tag cliente. Quando era um @EventListener(StartupEvent), esses erros iam ao GlitchTip sem a tag (o StartupEvent só dispara se o contexto sobe).

Assim, em produção com DSN todo log.error(...) (com a exceção anexada) vira evento no GlitchTip; em dev/local não. Capturas explícitas (Sentry.captureException) seguem valendo (ex.: XadmService reporta erros de origens conhecidas). Evite log.error displicente — vira ruído no GlitchTip.

Projeto único + tag de cliente (multi-tenant)

O integrador roda um recurso Coolify por cliente, mas há um único projeto GlitchTip (integrador, provisionado pela /xadm-setup — DSN público em docs/app.json features.glitchtip.dsn). Para distinguir os eventos por cliente sem projetos separados, o SentryInitializer marca toda ocorrência com a tag cliente (fonte: env CLIENTE). No GlitchTip, filtre/agrupe por cliente para isolar o tenant.

  • DSN é o mesmo para todos os deploys → configure o mesmo SENTRY_DSN em cada recurso de cliente no Coolify (a provisão não injeta sozinha: o app não tem production_url único).
  • CLIENTE já existe no application.yml (${CLIENTE:Cliente}); sem ele, os eventos ficam sem a tag (ou com o placeholder), sinalizando recurso mal-configurado.

Código: src/main/resources/logback.xml, comum/SentryInitializer (método configure).