diff --git a/cmd/api/main.go b/cmd/api/main.go index 4e02d92..a1f69b3 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -2,6 +2,10 @@ package main import ( "context" + "git.vtb.link/eoefans/internal/pkg/log" + "github.com/getsentry/sentry-go" + "go.uber.org/zap" + "time" "git.vtb.link/eoefans/internal/app" "git.vtb.link/eoefans/internal/app/api/service" @@ -24,7 +28,13 @@ func newAPI() fx.Option { ) } -func lc(lifecycle fx.Lifecycle, ginServer *httpserver.Server, randPicsCache *service.RandomPicsCache) { +func lc( + lifecycle fx.Lifecycle, + ginServer *httpserver.Server, + randPicsCache *service.RandomPicsCache, + logger *zap.Logger, + client *sentry.Client, +) { lifecycle.Append(fx.Hook{ OnStart: func(ctx context.Context) error { return ginServer.Start() @@ -38,4 +48,15 @@ func lc(lifecycle fx.Lifecycle, ginServer *httpserver.Server, randPicsCache *ser return randPicsCache.Run() }, }) + + lifecycle.Append(fx.Hook{ + OnStart: func(ctx context.Context) error { + *logger = *log.ModifyToSentryLogger(logger, client) + return nil + }, + OnStop: func(ctx context.Context) error { + client.Flush(2 * time.Second) + return nil + }, + }) } diff --git a/go.mod b/go.mod index d2a1c13..4972c97 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module git.vtb.link/eoefans go 1.18 require ( + github.com/getsentry/sentry-go v0.18.0 github.com/gin-contrib/zap v0.1.0 github.com/gin-gonic/gin v1.9.0 github.com/go-playground/validator/v10 v10.11.2 @@ -20,10 +21,10 @@ require ( ) require ( + github.com/TheZeroSlave/zapsentry v1.14.0 // indirect github.com/bytedance/sonic v1.8.1 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/getsentry/sentry-go v0.18.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect @@ -34,11 +35,8 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect - github.com/labstack/echo/v4 v4.9.0 // indirect - github.com/labstack/gommon v0.3.1 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -51,8 +49,6 @@ require ( github.com/subosito/gotenv v1.4.2 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.10 // indirect - github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasttemplate v1.2.1 // indirect go.opentelemetry.io/otel v1.13.0 // indirect go.opentelemetry.io/otel/trace v1.13.0 // indirect go.uber.org/atomic v1.10.0 // indirect diff --git a/go.sum b/go.sum index 401322a..93e56c5 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/TheZeroSlave/zapsentry v1.14.0 h1:z6H0lIyKVpdXsP5K8J11b4/+V+QCDLDslZmtXsnduMk= +github.com/TheZeroSlave/zapsentry v1.14.0/go.mod h1:0hUR1Et5tSroEYhWOZcxE2iBqcFkuG7jGGlUmOA7XAs= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= @@ -76,6 +78,7 @@ github.com/gin-contrib/zap v0.1.0/go.mod h1:hvnZaPs478H1PGvRP8w89ZZbyJUiyip4ddiI github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -191,19 +194,11 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY= -github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks= -github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o= -github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -218,6 +213,7 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -261,10 +257,6 @@ github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6 github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.10 h1:eimT6Lsr+2lzmSZxPhLFoOWFmQqwk0fllJJ5hEbTXtQ= github.com/ugorji/go/codec v1.2.10/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -438,8 +430,6 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/internal/app/api/middlewares/sentry.go b/internal/app/api/middlewares/sentry.go deleted file mode 100644 index f58e16f..0000000 --- a/internal/app/api/middlewares/sentry.go +++ /dev/null @@ -1,44 +0,0 @@ -package middlewares - -import ( - "github.com/getsentry/sentry-go" - sentrygin "github.com/getsentry/sentry-go/gin" - "github.com/gin-gonic/gin" - "github.com/pkg/errors" -) - -type SentryConfig struct { - DSN string `json:"dsn" yaml:"dsn" env:"SENTRY_DSN"` - EnableTracing bool `json:"enable_tracing" yaml:"enable_tracing" env:"SENTRY_ENABLE_TRACING"` - // Set TracesSampleRate to 1.0 to capture 100% - // of transactions for performance monitoring. - // We recommend adjusting this value in production, - TracesSampleRate float64 `json:"traces_sample_rate" yaml:"traces_sample_rate" env:"SENTRY_TRACES_SAMPLE_RATE"` -} - -type SendTry struct { - sentryConfig *SentryConfig -} - -func NewSendTry(sentryCfg *SentryConfig) (*SendTry, error) { - return &SendTry{ - sentryConfig: sentryCfg, - }, nil -} - -func (s *SendTry) init() error { - err := sentry.Init(sentry.ClientOptions{ - Dsn: s.sentryConfig.DSN, - EnableTracing: s.sentryConfig.EnableTracing, - TracesSampleRate: s.sentryConfig.TracesSampleRate, - }) - if err != nil { - return errors.Wrapf(err, "failed to initialize sentry") - } - - return nil -} - -func (s *SendTry) Middlewares() func(ctx *gin.Context) { - return sentrygin.New(sentrygin.Options{}) -} diff --git a/internal/app/provide.go b/internal/app/provide.go index 770818d..b70ab49 100644 --- a/internal/app/provide.go +++ b/internal/app/provide.go @@ -6,6 +6,7 @@ import ( "git.vtb.link/eoefans/internal/app/api/service" "git.vtb.link/eoefans/internal/app/api/util/password" "git.vtb.link/eoefans/internal/pkg/cache" + "git.vtb.link/eoefans/internal/pkg/log" "git.vtb.link/eoefans/internal/pkg/smsclient" "go.uber.org/fx" ) @@ -20,6 +21,7 @@ func Provide() fx.Option { fx.Provide(cache.NewGoCache), fx.Provide(smsclient.NewRandomNumberCodeGenerator), fx.Provide(password.NewDefaultPasswordHandler), + fx.Provide(log.NewSentryConfig, log.NewSentry), ) } diff --git a/internal/pkg/log/sentry.go b/internal/pkg/log/sentry.go new file mode 100644 index 0000000..aa94ebd --- /dev/null +++ b/internal/pkg/log/sentry.go @@ -0,0 +1,67 @@ +package log + +import ( + "github.com/TheZeroSlave/zapsentry" + "github.com/getsentry/sentry-go" + "github.com/pkg/errors" + "github.com/spf13/viper" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +type SentryConfig struct { + DSN string `json:"dsn" yaml:"dsn" env:"SENTRY_DSN"` + EnableTracing bool `json:"enable_tracing" yaml:"enable_tracing" env:"SENTRY_ENABLE_TRACING"` + // Set TracesSampleRate to 1.0 to capture 100% + // of transactions for performance monitoring. + // We recommend adjusting this value in production, + TracesSampleRate float64 `json:"traces_sample_rate" yaml:"traces_sample_rate" env:"SENTRY_TRACES_SAMPLE_RATE"` +} + +func NewSentryConfig(v *viper.Viper, logger *zap.Logger) (*SentryConfig, error) { + var err error + o := &SentryConfig{} + if err = v.UnmarshalKey("sentry", o); err != nil { + return nil, errors.Wrap(err, "unmarshal sentry config error") + } + + logger.Info("load sentry config success") + + return o, err +} + +func NewSentry(sentryCfg *SentryConfig) (*sentry.Client, error) { + client, err := sentry.NewClient(sentry.ClientOptions{ + Dsn: sentryCfg.DSN, + EnableTracing: sentryCfg.EnableTracing, + TracesSampleRate: sentryCfg.TracesSampleRate, + }) + if err != nil { + return nil, errors.Wrapf(err, "failed to initialize sentry") + } + + return client, nil +} + +func ModifyToSentryLogger(logger *zap.Logger, client *sentry.Client) *zap.Logger { + cfg := zapsentry.Configuration{ + Level: zapcore.ErrorLevel, //when to send message to sentry + EnableBreadcrumbs: true, // enable sending breadcrumbs to Sentry + BreadcrumbLevel: zapcore.InfoLevel, // at what level should we sent breadcrumbs to sentry + Tags: map[string]string{ + "component": "system", + }, + } + core, err := zapsentry.NewCore(cfg, zapsentry.NewSentryClientFromClient(client)) + + //in case of err it will return noop core. so we can safely attach it + if err != nil { + logger.Warn("failed to init zap", zap.Error(err)) + } + + logger = zapsentry.AttachCoreToLogger(core, logger) + + // to use breadcrumbs feature - create new scope explicitly + // and attach after attaching the core + return logger.With(zapsentry.NewScope()) +}