From e5d5672cd4e1c4838252c8f7d55d07b9be9f83a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Fri, 22 Nov 2024 11:54:00 +0100 Subject: [PATCH 1/3] add readme for slog integration --- slog/README.MD | 92 ++++++++++++++++++++++++++++++++++++++++++++++ slog/common.go | 2 +- slog/converter.go | 26 ++++++++----- slog/sentryslog.go | 1 - 4 files changed, 109 insertions(+), 12 deletions(-) create mode 100644 slog/README.MD diff --git a/slog/README.MD b/slog/README.MD new file mode 100644 index 000000000..cc9d1e1c9 --- /dev/null +++ b/slog/README.MD @@ -0,0 +1,92 @@ +

+ + + +
+

+ +# Official Sentry Integration for slog + +**Go.dev Documentation:** https://pkg.go.dev/github.com/getsentry/sentry-go/sentryslog +**Example Usage:** https://github.com/getsentry/sentry-go/tree/master/_examples/slog + +--- + +## Installation + +```sh +go get github.com/getsentry/sentry-go/sentryslog +``` + +## Usage + +```go +package main + +import ( + "context" + "log/slog" + + "github.com/getsentry/sentry-go" + "github.com/your-repo/slog-sentry" +) + +func main() { + // Initialize Sentry + err := sentry.Init(sentry.ClientOptions{ + Dsn: "your-public-dsn", + Debug: true, + }) + if err != nil { + panic(err) + } + defer sentry.Flush(5 * time.Second) + + // Set up slog with Sentry handler + handler := slogSentry.Option{ + Level: slog.LevelError, // Minimum log level + AddSource: true, // Include file/line source info + }.NewSentryHandler() + logger := slog.New(handler) + + // Example logging + logger.Info("This will not be sent to Sentry") + logger.Error("An error occurred", "user", "test-user") +} +``` + +## Configuration + +The slog-sentry package offers several options to customize how logs are handled and sent to Sentry. These are specified through the Option struct: + +- `Level`: Minimum log level to send to Sentry. Defaults to `slog.LevelDebug`. + +- `Hub`: Custom Sentry hub to use; defaults to the current Sentry hub if not set. + +- `Converter`: Custom function to transform logs into Sentry events (default is DefaultConverter). + +- `AttrFromContext`: Functions to extract additional attributes from the context. + +- `AddSource`: Include file/line source info in Sentry events. Defaults to `false`. + +- `ReplaceAttr`: Allows modification or filtering of attributes before sending to Sentry. + + +### Example Customization + +```go +handler := slogSentry.Option{ + Level: slog.LevelWarn, + Converter: func(addSource bool, replaceAttr func([]string, slog.Attr) slog.Attr, attrs []slog.Attr, groups []string, record *slog.Record, hub *sentry.Hub) *sentry.Event { + // Custom conversion logic + return &sentry.Event{ + Message: record.Message, + } + }, + AddSource: true, +}.NewSentryHandler() +``` + +## Notes + +- Always call Flush to ensure all events are sent to Sentry before program termination diff --git a/slog/common.go b/slog/common.go index afa74b7fa..8fd63a344 100644 --- a/slog/common.go +++ b/slog/common.go @@ -90,7 +90,7 @@ func mergeAttrValues(values ...slog.Value) slog.Value { } func groupValuesByKey(attrs []slog.Attr) map[string][]slog.Value { - result := map[string][]slog.Value{} + result := make(map[string][]slog.Value) for _, item := range attrs { key := item.Key diff --git a/slog/converter.go b/slog/converter.go index 0e2fcd3e3..34f48b9a2 100644 --- a/slog/converter.go +++ b/slog/converter.go @@ -112,16 +112,22 @@ func handleUserAttributes(v slog.Value, event *sentry.Event) { func handleRequestAttributes(v slog.Value, event *sentry.Event) { if req, ok := v.Any().(http.Request); ok { event.Request = sentry.NewRequest(&req) - } else if req, ok := v.Any().(*http.Request); ok { + return + } + if req, ok := v.Any().(*http.Request); ok { event.Request = sentry.NewRequest(req) - } else { - if tm, ok := v.Any().(encoding.TextMarshaler); ok { - data, err := tm.MarshalText() - if err == nil { - event.User.Data["request"] = string(data) - } else { - event.User.Data["request"] = fmt.Sprintf("%v", v.Any()) - } - } + return + } + + event.User.Data["request"] = fmt.Sprintf("%v", v.Any()) + + tm, ok := v.Any().(encoding.TextMarshaler) + if !ok { + return + } + + data, err := tm.MarshalText() + if err == nil { + event.User.Data["request"] = string(data) } } diff --git a/slog/sentryslog.go b/slog/sentryslog.go index 26538a6c1..362050f36 100644 --- a/slog/sentryslog.go +++ b/slog/sentryslog.go @@ -8,7 +8,6 @@ import ( ) // Majority of the code in this package is derived from https://github.com/samber/slog-sentry AND https://github.com/samber/slog-common -// Smaller changes have been implemented to remove dependency on packages that are not available in the standard library of Go 1.18 // MIT License // Copyright (c) 2023 Samuel Berthe From d22a6d5a383ffd3a9f09d36eafb1690cb9abf78c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Fri, 22 Nov 2024 11:58:54 +0100 Subject: [PATCH 2/3] partially revert converter --- slog/converter.go | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/slog/converter.go b/slog/converter.go index 34f48b9a2..3c7cb1eb0 100644 --- a/slog/converter.go +++ b/slog/converter.go @@ -114,20 +114,18 @@ func handleRequestAttributes(v slog.Value, event *sentry.Event) { event.Request = sentry.NewRequest(&req) return } + if req, ok := v.Any().(*http.Request); ok { event.Request = sentry.NewRequest(req) return } - event.User.Data["request"] = fmt.Sprintf("%v", v.Any()) - - tm, ok := v.Any().(encoding.TextMarshaler) - if !ok { - return - } - - data, err := tm.MarshalText() - if err == nil { - event.User.Data["request"] = string(data) + if tm, ok := v.Any().(encoding.TextMarshaler); ok { + data, err := tm.MarshalText() + if err == nil { + event.User.Data["request"] = string(data) + } else { + event.User.Data["request"] = fmt.Sprintf("%v", v.Any()) + } } } From 471c3e3dd7c24221528ab7ab2e0781fb2b46dd22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Fri, 22 Nov 2024 12:01:52 +0100 Subject: [PATCH 3/3] completely revert convertor --- slog/converter.go | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/slog/converter.go b/slog/converter.go index 3c7cb1eb0..0e2fcd3e3 100644 --- a/slog/converter.go +++ b/slog/converter.go @@ -112,20 +112,16 @@ func handleUserAttributes(v slog.Value, event *sentry.Event) { func handleRequestAttributes(v slog.Value, event *sentry.Event) { if req, ok := v.Any().(http.Request); ok { event.Request = sentry.NewRequest(&req) - return - } - - if req, ok := v.Any().(*http.Request); ok { + } else if req, ok := v.Any().(*http.Request); ok { event.Request = sentry.NewRequest(req) - return - } - - if tm, ok := v.Any().(encoding.TextMarshaler); ok { - data, err := tm.MarshalText() - if err == nil { - event.User.Data["request"] = string(data) - } else { - event.User.Data["request"] = fmt.Sprintf("%v", v.Any()) + } else { + if tm, ok := v.Any().(encoding.TextMarshaler); ok { + data, err := tm.MarshalText() + if err == nil { + event.User.Data["request"] = string(data) + } else { + event.User.Data["request"] = fmt.Sprintf("%v", v.Any()) + } } } }