diff --git a/.env.example b/.env.example index dfdb314e..5747c728 100644 --- a/.env.example +++ b/.env.example @@ -20,3 +20,5 @@ API_PORT=9876 API_RATE_LIMIT=20 API_PROMETHEUS_ENABLED=false API_REQUEST_TIMEOUT=10 +SENTRY_DSN= +CELENIUM_ENV=production diff --git a/build/dipdup.yml b/build/dipdup.yml index eafb357b..1ca5280c 100644 --- a/build/dipdup.yml +++ b/build/dipdup.yml @@ -33,6 +33,9 @@ api: prometheus: ${API_PROMETHEUS_ENABLED:-true} request_timeout: ${API_REQUEST_TIMEOUT:-30} blob_receiver: dal_api + sentry_dsn: ${SENTRY_DSN} + +environment: ${CELENIUM_ENV:-production} profiler: server: ${PROFILER_SERVER} diff --git a/cmd/api/config.go b/cmd/api/config.go index 42c8146a..5dcfbbfb 100644 --- a/cmd/api/config.go +++ b/cmd/api/config.go @@ -15,6 +15,7 @@ type Config struct { ApiConfig ApiConfig `validate:"required" yaml:"api"` Profiler *profiler.Config `validate:"omitempty" yaml:"profiler"` Indexer indexerConfig.Indexer `validate:"required" yaml:"indexer"` + Environment string `validate:"omitempty,oneof=development production" yaml:"environment"` } type ApiConfig struct { @@ -23,4 +24,5 @@ type ApiConfig struct { Prometheus bool `validate:"omitempty" yaml:"prometheus"` RequestTimeout int `validate:"omitempty,min=1" yaml:"request_timeout"` BlobReceiver string `validate:"required" yaml:"blob_receiver"` + SentryDsn string `validate:"omitempty" yaml:"sentry_dsn"` } diff --git a/cmd/api/handler/error.go b/cmd/api/handler/error.go index 5d7fbe57..e112cdc7 100644 --- a/cmd/api/handler/error.go +++ b/cmd/api/handler/error.go @@ -6,6 +6,7 @@ package handler import ( "net/http" + sentryecho "github.com/getsentry/sentry-go/echo" "github.com/labstack/echo/v4" "github.com/pkg/errors" ) @@ -31,6 +32,9 @@ func badRequestError(c echo.Context, err error) error { } func internalServerError(c echo.Context, err error) error { + if hub := sentryecho.GetHubFromContext(c); hub != nil { + hub.CaptureMessage(err.Error()) + } return c.JSON(http.StatusInternalServerError, Error{ Message: err.Error(), }) diff --git a/cmd/api/init.go b/cmd/api/init.go index 520f8f2f..4fb67802 100644 --- a/cmd/api/init.go +++ b/cmd/api/init.go @@ -19,10 +19,13 @@ import ( "github.com/celenium-io/celestia-indexer/internal/storage/postgres" nodeApi "github.com/celenium-io/celestia-indexer/pkg/node/dal" "github.com/dipdup-net/go-lib/config" + "github.com/getsentry/sentry-go" + sentryecho "github.com/getsentry/sentry-go/echo" "github.com/grafana/pyroscope-go" "github.com/labstack/echo-contrib/echoprometheus" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" + "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" echoSwagger "github.com/swaggo/echo-swagger" @@ -108,7 +111,7 @@ func gzipSkipper(c echo.Context) bool { return false } -func initEcho(cfg ApiConfig) *echo.Echo { +func initEcho(cfg ApiConfig, env string) *echo.Echo { e := echo.New() e.Validator = handler.NewCelestiaApiValidator() e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ @@ -188,6 +191,10 @@ func initEcho(cfg ApiConfig) *echo.Echo { } + if err := initSentry(e, cfg.SentryDsn, env); err != nil { + log.Err(err).Msg("sentry") + } + return e } @@ -296,6 +303,28 @@ func initHandlers(ctx context.Context, e *echo.Echo, cfg Config, db postgres.Sto } } +func initSentry(e *echo.Echo, dsn, environment string) error { + if dsn == "" { + return nil + } + + if err := sentry.Init(sentry.ClientOptions{ + Dsn: dsn, + AttachStacktrace: true, + Environment: environment, + BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { + log.Info().Str("message", "sentry").Msg(event.Message) + return event + }, + }); err != nil { + return errors.Wrap(err, "initialization") + } + + e.Use(sentryecho.New(sentryecho.Options{})) + + return nil +} + var ( wsManager *websocket.Manager ) diff --git a/cmd/api/main.go b/cmd/api/main.go index 36004e3b..1cf5aa00 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -42,7 +42,7 @@ func main() { ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM, syscall.SIGINT) db := initDatabase(cfg.Database) - e := initEcho(cfg.ApiConfig) + e := initEcho(cfg.ApiConfig, cfg.Environment) initHandlers(ctx, e, *cfg, db) go func() { @@ -54,8 +54,10 @@ func main() { <-ctx.Done() cancel() - if err := wsManager.Close(); err != nil { - e.Logger.Fatal(err) + if wsManager != nil { + if err := wsManager.Close(); err != nil { + e.Logger.Fatal(err) + } } if err := e.Shutdown(ctx); err != nil { diff --git a/go.mod b/go.mod index 81d58242..05568fdc 100644 --- a/go.mod +++ b/go.mod @@ -97,6 +97,7 @@ require ( github.com/felixge/httpsnoop v1.0.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/getsentry/sentry-go v0.25.0 // indirect github.com/go-faster/city v1.0.1 // indirect github.com/go-faster/errors v0.6.1 // indirect github.com/go-kit/kit v0.12.0 // indirect @@ -264,9 +265,9 @@ require ( replace ( github.com/cosmos/cosmos-sdk => github.com/celestiaorg/cosmos-sdk v1.18.3-sdk-v0.46.14 - github.com/tendermint/tendermint => github.com/celestiaorg/celestia-core v1.29.0-tm-v0.34.29 github.com/filecoin-project/dagstore => github.com/celestiaorg/dagstore v0.0.0-20230413141458-735ab09a15d6 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/ipfs/go-verifcid => github.com/celestiaorg/go-verifcid v0.0.1-lazypatch github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + github.com/tendermint/tendermint => github.com/celestiaorg/celestia-core v1.29.0-tm-v0.34.29 ) diff --git a/go.sum b/go.sum index ed0ca9d8..d3394ba8 100644 --- a/go.sum +++ b/go.sum @@ -443,6 +443,8 @@ github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI= +github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw=