Add basic support for sentry

This commit is contained in:
Eli Ribble 2026-01-29 15:48:15 +00:00
parent ef38aaf041
commit d9ccdd41b2
No known key found for this signature in database
4 changed files with 58 additions and 7 deletions

View file

@ -28,6 +28,7 @@ var (
PGDSN string PGDSN string
PhoneNumberReport phonenumbers.PhoneNumber PhoneNumberReport phonenumbers.PhoneNumber
PhoneNumberReportStr string PhoneNumberReportStr string
SentryDSN string
TwilioAuthToken string TwilioAuthToken string
TwilioAccountSID string TwilioAccountSID string
TwilioMessagingServiceSID string TwilioMessagingServiceSID string
@ -139,6 +140,10 @@ func Parse() (err error) {
} }
PhoneNumberReport = *p PhoneNumberReport = *p
SentryDSN = os.Getenv("SENTRY_DSN")
if SentryDSN == "" {
return fmt.Errorf("You must specify a non-empty SENTRY_DSN")
}
TwilioAccountSID = os.Getenv("TWILIO_ACCOUNT_SID") TwilioAccountSID = os.Getenv("TWILIO_ACCOUNT_SID")
if TwilioAccountSID == "" { if TwilioAccountSID == "" {
return fmt.Errorf("You must specify a non-empty TWILIO_ACCOUNT_SID") return fmt.Errorf("You must specify a non-empty TWILIO_ACCOUNT_SID")

2
go.mod
View file

@ -40,6 +40,8 @@ require (
github.com/beevik/etree v1.1.0 // indirect github.com/beevik/etree v1.1.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/getsentry/sentry-go v0.42.0 // indirect
github.com/getsentry/sentry-go/zerolog v0.42.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect github.com/go-ini/ini v1.67.0 // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang/mock v1.6.0 // indirect github.com/golang/mock v1.6.0 // indirect

4
go.sum
View file

@ -59,6 +59,10 @@ github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0o
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/getsentry/sentry-go v0.42.0 h1:eeFMACuZTbUQf90RE8dE4tXeSe4CZyfvR1MBL7RLEt8=
github.com/getsentry/sentry-go v0.42.0/go.mod h1:eRXCoh3uvmjQLY6qu63BjUZnaBu5L5WhMV1RwYO8W5s=
github.com/getsentry/sentry-go/zerolog v0.42.0 h1:FDvGyxz7IGW8bzomAJuEFiEToq89PrOLsxQ28XYLsDc=
github.com/getsentry/sentry-go/zerolog v0.42.0/go.mod h1:cY2lSFOu3cJXhvJuUfcBeyq19QRPYt6OIAvpdwhKkfE=
github.com/go-chi/chi/v5 v5.2.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.2.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=

54
main.go
View file

@ -19,6 +19,9 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/platform/text" "github.com/Gleipnir-Technology/nidus-sync/platform/text"
"github.com/Gleipnir-Technology/nidus-sync/public-report" "github.com/Gleipnir-Technology/nidus-sync/public-report"
nidussync "github.com/Gleipnir-Technology/nidus-sync/sync" nidussync "github.com/Gleipnir-Technology/nidus-sync/sync"
"github.com/getsentry/sentry-go"
sentryhttp "github.com/getsentry/sentry-go/http"
"github.com/getsentry/sentry-go/zerolog"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware" "github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/hostrouter" "github.com/go-chi/hostrouter"
@ -27,38 +30,75 @@ import (
) )
func main() { func main() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
err := config.Parse() err := config.Parse()
if err != nil { if err != nil {
log.Error().Err(err).Msg("Failed to parse config") log.Error().Err(err).Msg("Failed to parse config")
os.Exit(1) os.Exit(1)
} }
log.Info().Msg("Starting...") log.Info().Msg("Starting...")
err = sentry.Init(sentry.ClientOptions{
Debug: !config.IsProductionEnvironment(),
Dsn: config.SentryDSN,
EnableTracing: true,
SendDefaultPII: true,
TracesSampleRate: 1.0,
})
if err != nil {
log.Error().Err(err).Msg("Failed to start sentry connection")
os.Exit(2)
}
defer sentry.Flush(2 * time.Second)
sentryWriter, err := sentryzerolog.New(sentryzerolog.Config{
ClientOptions: sentry.ClientOptions{
Dsn: config.SentryDSN,
},
Options: sentryzerolog.Options{
Levels: []zerolog.Level{zerolog.ErrorLevel, zerolog.FatalLevel, zerolog.PanicLevel},
WithBreadcrumbs: true,
FlushTimeout: 3 * time.Second,
},
})
if err != nil {
log.Fatal().Err(err).Msg("Failed to create sentry writer")
os.Exit(2)
}
defer sentryWriter.Close()
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
log.Logger = log.Output(zerolog.MultiLevelWriter(zerolog.ConsoleWriter{Out: os.Stderr}, sentryWriter))
err = db.InitializeDatabase(context.TODO(), config.PGDSN) err = db.InitializeDatabase(context.TODO(), config.PGDSN)
if err != nil { if err != nil {
log.Error().Err(err).Msg("Failed to connect to database") log.Error().Err(err).Msg("Failed to connect to database")
os.Exit(2) os.Exit(3)
} }
err = email.LoadTemplates() err = email.LoadTemplates()
if err != nil { if err != nil {
log.Error().Err(err).Msg("Failed to load email templates") log.Error().Err(err).Msg("Failed to load email templates")
os.Exit(3) os.Exit(4)
} }
err = text.StoreSources() err = text.StoreSources()
if err != nil { if err != nil {
log.Error().Err(err).Msg("Failed to store text source phone numbers") log.Error().Err(err).Msg("Failed to store text source phone numbers")
os.Exit(4) os.Exit(5)
} }
router_logger := log.With().Logger() router_logger := log.With().Logger()
sentryMiddleware := sentryhttp.New(sentryhttp.Options{
Repanic: true,
})
r := chi.NewRouter() r := chi.NewRouter()
r.Use(LoggerMiddleware(&router_logger)) r.Use(LoggerMiddleware(&router_logger))
r.Use(middleware.RequestID)
r.Use(middleware.RealIP) r.Use(middleware.RealIP)
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(sentryMiddleware.Handle)
r.Use(auth.NewSessionManager().LoadAndSave) r.Use(auth.NewSessionManager().LoadAndSave)
hr := hostrouter.New() hr := hostrouter.New()
@ -81,7 +121,7 @@ func main() {
err = llm.CreateOpenAIClient(ctx, &openai_logger) err = llm.CreateOpenAIClient(ctx, &openai_logger)
if err != nil { if err != nil {
log.Error().Err(err).Msg("Failed to start openAI client") log.Error().Err(err).Msg("Failed to start openAI client")
os.Exit(5) os.Exit(6)
} }
background.Start(ctx) background.Start(ctx)
server := &http.Server{ server := &http.Server{