// Copyright 2022 Molecula Corp. (DBA FeatureBase). // SPDX-License-Identifier: Apache-2.0 package monitor import ( "context" "flag" "fmt" "log" "time" sentry "github.com/getsentry/sentry-go" ) const ( LevelPanic = iota LevelError LevelWarn LevelInfo LevelDebug ) var isOn bool // Initialiazing Sentry with particular settings func InitErrorMonitor(version string) { isOn = true err := sentry.Init(sentry.ClientOptions{ Dsn: getDSN(), AttachStacktrace: true, Debug: false, TracesSampleRate: 1, Release: version, }) sentry.ConfigureScope(func(scope *sentry.Scope) { scope.SetUser(sentry.User{IPAddress: "{{auto}}"}) }) if err != nil { log.Fatalf("sentry.Init: %s", err) } CaptureMessage("Session:Started") go monitorRun() } // CaptureMessage sends a message to Sentry. func CaptureMessage(message string) { if !isOn || isTest() { return } sentry.CaptureMessage(message) defer sentry.Flush(2 * time.Second) } // CaptureException sends an error to Sentry. func CaptureException(level int, format string, v ...interface{}) { if !isOn || isTest() { return } if level > LevelWarn { return } err := fmt.Errorf(format, v...) sentry.CaptureException(err) defer sentry.Flush(2 * time.Second) } // monitorRun runs in a goroutine and sends a heartbeat to Sentry every 24 hours. func monitorRun() { for i := 0; ; i++ { CaptureMessage(fmt.Sprintf("Session:%d", i)) time.Sleep(24 * time.Hour) } } // IsOn returns true if the monitor is enabled. func IsOn() bool { return isOn } // isTest returns true if execution is part of test func isTest() bool { return flag.Lookup("test.v") != nil } // DSN identifies which sentry project to report to func getDSN() string { if isTest() { return "https://13194f56bf7b4e049fab181d489dd297@o1007484.ingest.sentry.io/6493546" } return "https://a6c854a5aa2a4c5cb5baaf01e6968a77@o1007484.ingest.sentry.io/6448164" } // Wrappers around Sentry's span to minimize exposure of sentry elsewhere in the codebase and for single-responsibility func StartSpan(ctx context.Context, txType, txName string) *sentry.Span { if !isOn || isTest() { return &sentry.Span{} } return sentry.StartSpan(ctx, txType, sentry.TransactionName(txName)) } func Finish(span *sentry.Span) { if !isOn || isTest() { return } span.Finish() }