diff --git a/go.mod b/go.mod index 467f011..ab6be91 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/Luzifer/korvike/functions v0.11.0 github.com/Luzifer/rconfig/v2 v2.4.0 github.com/Masterminds/sprig/v3 v3.2.2 + github.com/getsentry/sentry-go v0.14.0 github.com/glebarez/sqlite v1.5.0 github.com/go-irc/irc v2.1.0+incompatible github.com/go-sql-driver/mysql v1.6.0 @@ -17,6 +18,7 @@ require ( github.com/gorilla/websocket v1.5.0 github.com/itchyny/gojq v0.12.9 github.com/mitchellh/hashstructure/v2 v2.0.2 + github.com/orandin/sentrus v1.0.0 github.com/pkg/errors v0.9.1 github.com/robfig/cron/v3 v3.0.1 github.com/sirupsen/logrus v1.9.0 diff --git a/go.sum b/go.sum index 854b751..f0d0de4 100644 --- a/go.sum +++ b/go.sum @@ -70,6 +70,8 @@ github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/getsentry/sentry-go v0.14.0 h1:rlOBkuFZRKKdUnKO+0U3JclRDQKlRu5vVQtkWSQvC70= +github.com/getsentry/sentry-go v0.14.0/go.mod h1:RZPJKSw+adu8PBNygiri/A98FqVr2HtRckJk9XVxJ9I= github.com/glebarez/go-sqlite v1.19.1/go.mod h1:9AykawGIyIcxoSfpYWiX1SgTNHTNsa/FVc75cDkbp4M= github.com/glebarez/go-sqlite v1.19.2 h1:mTtntWN3wk9UNjIf6F7Upqnfq96p+cjhfgCsupUd1hY= github.com/glebarez/go-sqlite v1.19.2/go.mod h1:DoubC3Kn5X6EBvDa2iaxAdIJqPNmY7M/sOCpfa8fus0= @@ -77,6 +79,7 @@ github.com/glebarez/sqlite v1.5.0 h1:+8LAEpmywqresSoGlqjjT+I9m4PseIM3NcerIJ/V7mk github.com/glebarez/sqlite v1.5.0/go.mod h1:0wzXzTvfVJIN2GqRhCdMbnYd+m+aH5/QV7B30rM6NgY= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-irc/irc v2.1.0+incompatible h1:pg7pMVq5OYQbqTxceByD/EN8VIsba7DtKn49rsCnG8Y= github.com/go-irc/irc v2.1.0+incompatible/go.mod h1:jJILTRy8s/qOvusiKifAEfhQMVwft1ZwQaVJnnzmyX4= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -343,12 +346,15 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ= github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= +github.com/orandin/sentrus v1.0.0 h1:rMZKTUdwuhIaC7C6VbvhQPQeO9hBpliODrj7o/NmipM= +github.com/orandin/sentrus v1.0.0/go.mod h1:Mqa1Dcat0IcuD/XPMXUolzuZ74NWptnnX8eRq3gLaSU= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= diff --git a/main.go b/main.go index e036e8d..edf48ac 100644 --- a/main.go +++ b/main.go @@ -16,8 +16,10 @@ import ( "sync" "time" + "github.com/getsentry/sentry-go" "github.com/gofrs/uuid/v3" "github.com/gorilla/mux" + "github.com/orandin/sentrus" "github.com/pkg/errors" "github.com/robfig/cron/v3" log "github.com/sirupsen/logrus" @@ -53,6 +55,7 @@ var ( IRCRateLimit time.Duration `flag:"rate-limit" default:"1500ms" description:"How often to send a message (default: 20/30s=1500ms, if your bot is mod everywhere: 100/30s=300ms, different for known/verified bots)"` LogLevel string `flag:"log-level" default:"info" description:"Log level (debug, info, warn, error, fatal)"` PluginDir string `flag:"plugin-dir" default:"/usr/lib/twitch-bot" description:"Where to find and load plugins"` + SentryDSN string `flag:"sentry-dsn" default:"" description:"Sentry / GlitchTip DSN for error reporting"` StorageConnString string `flag:"storage-conn-string" default:"./storage.db" description:"Connection string for the database"` StorageConnType string `flag:"storage-conn-type" default:"sqlite" description:"One of: mysql, postgres, sqlite"` StorageEncryptionPass string `flag:"storage-encryption-pass" default:"" description:"Passphrase to encrypt secrets inside storage (defaults to twitch-client:twitch-client-secret)"` @@ -84,10 +87,10 @@ var ( version = "dev" ) -func init() { +func initApp() error { rconfig.AutoEnv(true) if err := rconfig.ParseAndValidate(&cfg); err != nil { - log.Fatalf("Unable to parse commandline options: %s", err) + return errors.Wrap(err, "parsing cli options") } if cfg.VersionAndExit { @@ -95,10 +98,22 @@ func init() { os.Exit(0) } - if l, err := log.ParseLevel(cfg.LogLevel); err != nil { - log.WithError(err).Fatal("Unable to parse log level") - } else { - log.SetLevel(l) + l, err := log.ParseLevel(cfg.LogLevel) + if err != nil { + return errors.Wrap(err, "parsing log level") + } + log.SetLevel(l) + + if cfg.SentryDSN != "" { + if err := sentry.Init(sentry.ClientOptions{ + Dsn: cfg.SentryDSN, + Release: strings.Join([]string{"twitch-bot", version}, "@"), + }); err != nil { + return errors.Wrap(err, "initializing sentry sdk") + } + log.AddHook(sentrus.NewHook( + []log.Level{log.ErrorLevel, log.FatalLevel, log.PanicLevel}, + )) } if cfg.StorageEncryptionPass == "" { @@ -108,6 +123,8 @@ func init() { cfg.TwitchClientSecret, }, ":") } + + return nil } func getEventSubSecret() (secret, handle string, err error) { @@ -214,6 +231,10 @@ func handleSubCommand(args []string) { func main() { var err error + if err = initApp(); err != nil { + log.WithError(err).Fatal("initializing application") + } + if db, err = database.New(cfg.StorageConnType, cfg.StorageConnString, cfg.StorageEncryptionPass); err != nil { log.WithError(err).Fatal("Unable to open storage backend") }