From 49ea072fc064e3ca42fbd52d72d5035f84c5133a Mon Sep 17 00:00:00 2001 From: imcom Date: Wed, 11 Dec 2024 16:44:17 +0800 Subject: [PATCH] feat: add sentry support to capture unexpected crashes doc: add readme entry and sentry doc --- README.md | 1 + cmd/gobgpd/main.go | 77 +++++++++++++++++++++++++++++------------- docs/sources/sentry.md | 30 ++++++++++++++++ go.mod | 3 +- go.sum | 4 +++ 5 files changed, 91 insertions(+), 24 deletions(-) create mode 100644 docs/sources/sentry.md diff --git a/README.md b/README.md index 39b6ff714..3e2443324 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ Try [a binary release](https://github.com/osrg/gobgp/releases/latest). - [Confederation](docs/sources/bgp-confederation.md) - Data Center Networking - [Unnumbered BGP](docs/sources/unnumbered-bgp.md) +- [Sentry](docs/sources/sentry.md) ### Externals diff --git a/cmd/gobgpd/main.go b/cmd/gobgpd/main.go index 24cb34bdf..2fbc3e8f2 100644 --- a/cmd/gobgpd/main.go +++ b/cmd/gobgpd/main.go @@ -31,6 +31,7 @@ import ( "time" "github.com/coreos/go-systemd/v22/daemon" + "github.com/getsentry/sentry-go" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/jessevdk/go-flags" "github.com/kr/pretty" @@ -54,32 +55,36 @@ func main() { signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGINT) var opts struct { - ConfigFile string `short:"f" long:"config-file" description:"specifying a config file"` - ConfigType string `short:"t" long:"config-type" description:"specifying config type (toml, yaml, json)" default:"toml"` - ConfigAutoReload bool `short:"a" long:"config-auto-reload" description:"activate config auto reload on changes"` - ConfigStrict bool `long:"config-strict" description:"make any config error fatal"` - LogLevel string `short:"l" long:"log-level" description:"specifying log level"` - LogPlain bool `short:"p" long:"log-plain" description:"use plain format for logging (json by default)"` - UseSyslog string `short:"s" long:"syslog" description:"use syslogd"` - Facility string `long:"syslog-facility" description:"specify syslog facility"` - DisableStdlog bool `long:"disable-stdlog" description:"disable standard logging"` - CPUs int `long:"cpus" description:"specify the number of CPUs to be used"` - GrpcHosts string `long:"api-hosts" description:"specify the hosts that gobgpd listens on" default:":50051"` - GracefulRestart bool `short:"r" long:"graceful-restart" description:"flag restart-state in graceful-restart capability"` - Dry bool `short:"d" long:"dry-run" description:"check configuration"` - PProfHost string `long:"pprof-host" description:"specify the host that gobgpd listens on for pprof and metrics" default:"localhost:6060"` - PProfDisable bool `long:"pprof-disable" description:"disable pprof profiling"` - MetricsPath string `long:"metrics-path" description:"specify path for prometheus metrics, empty value disables them" default:"/metrics"` - UseSdNotify bool `long:"sdnotify" description:"use sd_notify protocol"` - TLS bool `long:"tls" description:"enable TLS authentication for gRPC API"` - TLSCertFile string `long:"tls-cert-file" description:"The TLS cert file"` - TLSKeyFile string `long:"tls-key-file" description:"The TLS key file"` - TLSClientCAFile string `long:"tls-client-ca-file" description:"Optional TLS client CA file to authenticate clients against"` - Version bool `long:"version" description:"show version number"` + ConfigFile string `short:"f" long:"config-file" description:"specifying a config file"` + ConfigType string `short:"t" long:"config-type" description:"specifying config type (toml, yaml, json)" default:"toml"` + ConfigAutoReload bool `short:"a" long:"config-auto-reload" description:"activate config auto reload on changes"` + ConfigStrict bool `long:"config-strict" description:"make any config error fatal"` + LogLevel string `short:"l" long:"log-level" description:"specifying log level"` + LogPlain bool `short:"p" long:"log-plain" description:"use plain format for logging (json by default)"` + UseSyslog string `short:"s" long:"syslog" description:"use syslogd"` + Facility string `long:"syslog-facility" description:"specify syslog facility"` + DisableStdlog bool `long:"disable-stdlog" description:"disable standard logging"` + CPUs int `long:"cpus" description:"specify the number of CPUs to be used"` + GrpcHosts string `long:"api-hosts" description:"specify the hosts that gobgpd listens on" default:":50051"` + GracefulRestart bool `short:"r" long:"graceful-restart" description:"flag restart-state in graceful-restart capability"` + Dry bool `short:"d" long:"dry-run" description:"check configuration"` + PProfHost string `long:"pprof-host" description:"specify the host that gobgpd listens on for pprof and metrics" default:"localhost:6060"` + PProfDisable bool `long:"pprof-disable" description:"disable pprof profiling"` + MetricsPath string `long:"metrics-path" description:"specify path for prometheus metrics, empty value disables them" default:"/metrics"` + UseSdNotify bool `long:"sdnotify" description:"use sd_notify protocol"` + TLS bool `long:"tls" description:"enable TLS authentication for gRPC API"` + TLSCertFile string `long:"tls-cert-file" description:"The TLS cert file"` + TLSKeyFile string `long:"tls-key-file" description:"The TLS key file"` + TLSClientCAFile string `long:"tls-client-ca-file" description:"Optional TLS client CA file to authenticate clients against"` + Version bool `long:"version" description:"show version number"` + SentryDSN string `long:"sentry-dsn" description:"Sentry DSN" default:""` + SentryEnvironment string `long:"sentry-environment" description:"Sentry environment" default:"development"` + SentrySampleRate float64 `long:"sentry-sample-rate" description:"Sentry traces sample rate" default:"1.0"` + SentryDebug bool `long:"sentry-debug" description:"Sentry debug mode"` } _, err := flags.Parse(&opts) if err != nil { - os.Exit(1) + logger.Fatalf("Error parsing flags: %v", err) } if opts.Version { @@ -87,6 +92,32 @@ func main() { os.Exit(0) } + // if Sentry DSN is provided, initialize Sentry + // We would like to capture errors and exceptions, but not traces + if opts.SentryDSN != "" { + logger.Debugf("Initializing Sentry, Env: %s, Release: %s, SampleRate: %f, Debug: %t", + opts.SentryEnvironment, version.Version(), opts.SentrySampleRate, opts.SentryDebug) + err := sentry.Init(sentry.ClientOptions{ + Dsn: opts.SentryDSN, + SampleRate: opts.SentrySampleRate, + Debug: opts.SentryDebug, + Release: version.Version(), + Environment: opts.SentryEnvironment, + // Disable tracing as it's not relevant for now + EnableTracing: false, + TracesSampleRate: 0.0, + }) + if err != nil { + logger.Fatalf("sentry.Init: %s", err) + } + // Flush buffered events before the program terminates. + defer sentry.Flush(2 * time.Second) + + if opts.SentryDebug { + sentry.CaptureMessage("Sentry debug mode enabled on gobgpd") + } + } + if opts.CPUs == 0 { runtime.GOMAXPROCS(runtime.NumCPU()) } else { diff --git a/docs/sources/sentry.md b/docs/sources/sentry.md new file mode 100644 index 000000000..8622fb17e --- /dev/null +++ b/docs/sources/sentry.md @@ -0,0 +1,30 @@ +# Sentry + +GoBGP supports Sentry for error and exception tracking. + +To enable Sentry, set the `--sentry-dsn` flag to your Sentry DSN. + +```bash +$ gobgpd --sentry-dsn= +``` + +In addition, you can set the `--sentry-environment` flag to your Sentry environment. + +```bash +$ gobgpd --sentry-dsn= --sentry-environment= +``` + +You can also set the `--sentry-sample-rate` flag to the sample rate of Sentry traces. + +```bash +$ gobgpd --sentry-dsn= --sentry-sample-rate= +``` + +Finally, you can set the `--sentry-debug` flag to enable Sentry debug mode. + +```bash +$ gobgpd --sentry-dsn= --sentry-debug=true +``` + +When Sentry debug mode is enabled, there is a message logged to Sentry when the program starts. +This is particularly useful to verify that Sentry is working as expected. diff --git a/go.mod b/go.mod index 432883cda..fa7b09225 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/fsnotify/fsnotify v1.6.0 github.com/go-test/deep v1.1.0 github.com/google/go-cmp v0.5.9 - github.com/google/uuid v1.3.1 + github.com/google/uuid v1.6.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/jessevdk/go-flags v1.5.0 github.com/k-sone/critbitgo v1.4.0 @@ -31,6 +31,7 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/eapache/queue v1.1.0 // indirect + github.com/getsentry/sentry-go v0.30.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index 6498f6773..c636952a3 100644 --- a/go.sum +++ b/go.sum @@ -75,6 +75,8 @@ github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0X github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/getsentry/sentry-go v0.30.0 h1:lWUwDnY7sKHaVIoZ9wYqRHJ5iEmoc0pqcRqFkosKzBo= +github.com/getsentry/sentry-go v0.30.0/go.mod h1:WU9B9/1/sHDqeV8T+3VwwbjeR5MSXs/6aqG3mqZrezA= 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= @@ -140,6 +142,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=