### Install slog-formatter Go Module Source: https://github.com/samber/slog-formatter/blob/main/README.md Use `go get` to download and install the `slog-formatter` library into your Go project. ```sh go get github.com/samber/slog-formatter ``` -------------------------------- ### Initialize slog-formatter with Multiple Custom Formatters Source: https://github.com/samber/slog-formatter/blob/main/README.md This example demonstrates how to set up `slog-formatter` with three distinct formatters: one to anonymize sensitive data by key, another to enrich error details, and a third to format a custom `User` struct. It shows how to integrate these formatters into a `slog` logger. ```go import ( slogformatter "github.com/samber/slog-formatter" "log/slog" ) formatter1 := slogformatter.FormatByKey("very_private_data", func(v slog.Value) slog.Value { return slog.StringValue("***********") }) formatter2 := slogformatter.ErrorFormatter("error") formatter3 := slogformatter.FormatByType(func(u User) slog.Value { return slog.StringValue(fmt.Sprintf("%s %s", u.firstname, u.lastname)) }) logger := slog.New( slogformatter.NewFormatterHandler(formatter1, formatter2, formatter3)( slog.NewTextHandler(os.Stdout, nil), ), ) err := fmt.Errorf("an error") logger.Error("a message", slog.Any("very_private_data", "abcd"), slog.Any("user", user), slog.Any("err", err)) // outputs: // time=2023-04-10T14:00:0.000000+00:00 level=ERROR msg="a message" error.message="an error" error.type="*errors.errorString" user="John doe" very_private_data="********" ``` -------------------------------- ### Custom log attribute formatting with slogformatter.Format Source: https://github.com/samber/slog-formatter/blob/main/README.md Demonstrates how to use `slogformatter.Format` to apply a custom function to every attribute, allowing for conditional masking or transformation based on groups or keys. For example, hiding all attributes under the 'user' group. ```go slogformatter.NewFormatterHandler( slogformatter.Format(func(groups []string, key string, value slog.Value) slog.Value { // hide everything under "user" group if lo.Contains(groups, "user") { return slog.StringValue("****") } return value }), ) ``` -------------------------------- ### Format Go Errors in slog Logs Source: https://github.com/samber/slog-formatter/blob/main/README.md Provides an example of `slogformatter.ErrorFormatter` to transform Go `error` types into a structured, readable format within `slog` output. This formatter automatically extracts the error message, type, and stacktrace, significantly improving the debuggability of logged errors. ```Go import ( slogformatter "github.com/samber/slog-formatter" "log/slog" ) logger := slog.New( slogformatter.NewFormatterHandler( slogformatter.ErrorFormatter("error"), )( slog.NewTextHandler(os.Stdout, nil), ), ) err := fmt.Errorf("an error") logger.Error("a message", slog.Any("error", err)) // outputs: // { // "time":"2023-04-10T14:00:0.000000+00:00", // "level": "ERROR", // "msg": "a message", // "error": { // "message": "an error", // "type": "*errors.errorString" // "stacktrace": "main.main()\n\t/Users/samber/src/github.com/samber/slog-formatter/example/example.go:108 +0x1c\n" // } // } ``` -------------------------------- ### Development and Testing Commands for slog-formatter Source: https://github.com/samber/slog-formatter/blob/main/README.md Provides command-line instructions for setting up development dependencies using `make tools`, running unit tests with `make test`, and continuously watching tests during development using `make watch-test` for the slog-formatter project. ```bash # Install some dev dependencies make tools # Run tests make test # or make watch-test ``` -------------------------------- ### Apply Chained Formatters with slogformatter.NewFormatterHandler Source: https://github.com/samber/slog-formatter/blob/main/README.md Illustrates the use of `slogformatter.NewFormatterHandler` to combine multiple custom formatters (for key-based anonymization, error enrichment, and type-based formatting of a `User` struct) into a single `slog` handler. This allows for flexible and modular log attribute processing. ```go import ( slogformatter "github.com/samber/slog-formatter" "log/slog" ) type User struct { email string firstname string lastname string } formatter1 := slogformatter.FormatByKey("very_private_data", func(v slog.Value) slog.Value { return slog.StringValue("***********") }) formatter2 := slogformatter.ErrorFormatter("error") formatter3 := slogformatter.FormatByType(func(u User) slog.Value { return slog.StringValue(fmt.Sprintf("%s %s", u.firstname, u.lastname)) }) logger := slog.New( slogformatter.NewFormatterHandler(formatter1, formatter2, formatter3)( slog.NewTextHandler(os.StdErr, nil), ), ) err := fmt.Errorf("an error") logger.Error("a message", slog.Any("very_private_data", "abcd"), slog.Any("user", user), slog.Any("err", err)) // outputs: // time=2023-04-10T14:00:0.000000+00:00 level=ERROR msg="a message" error.message="an error" error.type="*errors.errorString" user="John doe" very_private_data="********" ``` -------------------------------- ### Format slog attributes by group and key in Go Source: https://github.com/samber/slog-formatter/blob/main/README.md Demonstrates how to create a new slog formatter handler that formats attributes under a specific group and matching key. It applies a custom function to the matched value, allowing for dynamic modification based on the attribute's context. ```go slogformatter.NewFormatterHandler( slogformatter.FormatByGroupKey([]{"user", "address"}, "country", func(value slog.Value) slog.Value { return ... }), ) ``` -------------------------------- ### Format slog attributes by key with slogformatter.FormatByKey Source: https://github.com/samber/slog-formatter/blob/main/README.md Demonstrates how to use `slogformatter.FormatByKey` to apply a formatter function to attributes matching a specific key (e.g., 'abcd'). ```go slogformatter.NewFormatterHandler( slogformatter.FormatByKey("abcd", func(value slog.Value) slog.Value { return ... }), ) ``` -------------------------------- ### Apply Multiple Formatters with slog-multi Middleware in Go Source: https://github.com/samber/slog-formatter/blob/main/README.md Demonstrates how to use `slog-formatter.NewFormatterHandler` with `slog-multi` to apply multiple custom formatters (e.g., `FormatByKey`, `ErrorFormatter`, `FormatByType`) to `slog` records. This allows for dynamic modification of log values before they are written to the sink, enabling redaction, transformation, or enrichment of log data. ```Go import ( slogformatter "github.com/samber/slog-formatter" slogmulti "github.com/samber/slog-multi" "log/slog" ) formatter1 := slogformatter.FormatByKey("very_private_data", func(v slog.Value) slog.Value { return slog.StringValue("***********") }) formatter2 := slogformatter.ErrorFormatter("error") formatter3 := slogformatter.FormatByType(func(u User) slog.Value { return slog.StringValue(fmt.Sprintf("%s %s", u.firstname, u.lastname)) }) formattingMiddleware := slogformatter.NewFormatterHandler(formatter1, formatter2, formatter3) sink := slog.NewJSONHandler(os.Stderr, slog.HandlerOptions{}) logger := slog.New( slogmulti. Pipe(formattingMiddleware). Handler(sink), ) err := fmt.Errorf("an error") logger.Error("a message", slog.Any("very_private_data", "abcd"), slog.Any("user", user), slog.Any("err", err)) // outputs: // time=2023-04-10T14:00:0.000000+00:00 level=ERROR msg="a message" error.message="an error" error.type="*errors.errorString" user="John doe" very_private_data="********" ``` -------------------------------- ### Format slog attributes by group, key, and type in Go Source: https://github.com/samber/slog-formatter/blob/main/README.md Illustrates how to create a new slog formatter handler that formats attributes under a specific group and matching key, with an additional type constraint. This allows for type-safe manipulation of the attribute's value using a custom function. ```go slogformatter.NewFormatterHandler( slogformatter.FormatByGroupKeyType[string]([]{"user", "address"}, "country", func(value string) slog.Value { return ... }), ) ``` -------------------------------- ### Format slog attributes by key and generic type with slogformatter.FormatByFieldType Source: https://github.com/samber/slog-formatter/blob/main/README.md Illustrates how to use `slogformatter.FormatByFieldType` to apply a formatter function to attributes that match both a specific key and a generic type. ```go slogformatter.NewFormatterHandler( slogformatter.FormatByFieldType[User]("user", func(u User) slog.Value { return ... }), ) ``` -------------------------------- ### Format slog attributes by Kind with slogformatter.FormatByKind Source: https://github.com/samber/slog-formatter/blob/main/README.md Explains how to use `slogformatter.FormatByKind` to apply a formatter function specifically to attributes matching a certain `slog.Kind` (e.g., `slog.KindDuration`). ```go slogformatter.NewFormatterHandler( slogformatter.FormatByKind(slog.KindDuration, func(value slog.Value) slog.Value { return ... }), ) ``` -------------------------------- ### Apply IPAddressFormatter to mask IP addresses in slog logs Source: https://github.com/samber/slog-formatter/blob/main/README.md Shows how to use `IPAddressFormatter` to transform IP addresses into a masked string (e.g., '********') within `slog` output. ```go import ( slogformatter "github.com/samber/slog-formatter" "log/slog" "os" ) logger := slog.New( slogformatter.NewFormatterHandler( slogformatter.IPAddressFormatter("ip_address"), )( slog.NewTextHandler(os.Stdout, nil), ), ) logger. With("ip_address", "1.2.3.4"). Error("an error") // outputs: // { // "time":"2023-04-10T14:00:0.000000+00:00", // "level": "ERROR", // "msg": "an error", // "ip_address": "*******", // } ``` -------------------------------- ### slog-formatter Handlers API Source: https://github.com/samber/slog-formatter/blob/main/README.md This section outlines the core handler functions provided by the `slog-formatter` library. It includes the primary `NewFormatterHandler`, a middleware compatible with `slog-multi`, and a utility to `RecoverHandlerError` for robust error handling within `slog` handlers. ```APIDOC NewFormatterHandler: main handler NewFormatterMiddleware: compatible with slog-multi middlewares RecoverHandlerError: catch panics and error from handlers ``` -------------------------------- ### Use FlattenFormatterMiddleware to flatten nested log attributes Source: https://github.com/samber/slog-formatter/blob/main/README.md Illustrates the `FlattenFormatterMiddleware` for recursively flattening nested attributes in `slog` output, using a specified separator and prefix. Useful for simplifying complex log structures. ```go import ( slogformatter "github.com/samber/slog-formatter" slogmulti "github.com/samber/slog-multi" "log/slog" "os" ) logger := slog.New( slogmulti. Pipe(slogformatter.FlattenFormatterMiddlewareOptions{Separator: ".", Prefix: "attrs", IgnorePath: false}.NewFlattenFormatterMiddlewareOptions()). Handler(slog.NewJSONHandler(os.Stdout, nil)), ) logger. With("email", "samuel@acme.org"). With("environment", "dev"). WithGroup("group1"). With("hello", "world"). WithGroup("group2"). With("hello", "world"). Error("A message", "foo", "bar") // outputs: // { // "time": "2023-05-20T22:14:55.857065+02:00", // "level": "ERROR", // "msg": "A message", // "attrs.email": "samuel@acme.org", // "attrs.environment": "dev", // "attrs.group1.hello": "world", // "attrs.group1.group2.hello": "world", // "foo": "bar" // } ``` -------------------------------- ### Format slog attributes by group with slogformatter.FormatByGroup Source: https://github.com/samber/slog-formatter/blob/main/README.md Explains how to use `slogformatter.FormatByGroup` to apply a formatter function to all attributes within a specified group path (e.g., 'user', 'address'). ```go slogformatter.NewFormatterHandler( slogformatter.FormatByGroup([]{"user", "address"}, func(attr []slog.Attr) slog.Value { return ... }), ) ``` -------------------------------- ### Format Time Values in Go slog Source: https://github.com/samber/slog-formatter/blob/main/README.md Shows how to use `slogformatter.TimeFormatter` to transform `time.Time` values into a specified readable string format within `slog` logs. This ensures consistent and human-readable time representation across all log entries. ```Go slogformatter.NewFormatterHandler( slogformatter.TimeFormatter(time.DateTime, time.UTC), ) ``` -------------------------------- ### Format HTTP Request and Response in Go slog Source: https://github.com/samber/slog-formatter/blob/main/README.md Illustrates the use of `slogformatter.HTTPRequestFormatter` and `slogformatter.HTTPResponseFormatter` to serialize `http.Request` and `http.Response` objects into structured `slog` entries. This helps in logging detailed HTTP interaction information, including headers and potentially body content, for debugging and auditing purposes. ```Go import ( slogformatter "github.com/samber/slog-formatter" "log/slog" ) logger := slog.New( slogformatter.NewFormatterHandler( slogformatter.HTTPRequestFormatter(false), slogformatter.HTTPResponseFormatter(false), )( slog.NewJSONHandler(os.Stdout, nil), ), ) req, _ := http.NewRequest(http.MethodGet, "https://api.screeb.app", nil) req.Header.Set("Content-Type", "application/json") req.Header.Set("X-TOKEN", "1234567890") res, _ := http.DefaultClient.Do(req) logger.Error("a message", slog.Any("request", req), slog.Any("response", res)) ``` -------------------------------- ### Apply PIIFormatter to redact sensitive information in slog logs Source: https://github.com/samber/slog-formatter/blob/main/README.md Demonstrates how to use `PIIFormatter` to hide private Personal Identifiable Information (PII) in `slog` output. IDs are preserved, while values longer than 5 characters are partially masked with a plain text prefix. ```go import ( slogformatter "github.com/samber/slog-formatter" "log/slog" "os" ) logger := slog.New( slogformatter.NewFormatterHandler( slogformatter.PIIFormatter("user"), )( slog.NewTextHandler(os.Stdout, nil), ), ) logger. With( slog.Group( "user", slog.String("id", "bd57ffbd-8858-4cc4-a93b-426cef16de61"), slog.String("email", "foobar@example.com"), slog.Group( "address", slog.String("street", "1st street"), slog.String("city", "New York"), slog.String("country", "USA"), slog.Int("zip", 12345), ), ), ). Error("an error") // outputs: // { // "time":"2023-04-10T14:00:0.000000+00:00", // "level": "ERROR", // "msg": "an error", // "user": { // "id": "bd57ffbd-8858-4cc4-a93b-426cef16de61", // "email": "foob*******", // "address": { // "street": "1st *******", // "city": "New *******", // "country": "*******", // "zip": "*******" // } // } // } ``` -------------------------------- ### Recover from Handler Errors in Go slog with slog-formatter Source: https://github.com/samber/slog-formatter/blob/main/README.md Illustrates how to use `slogformatter.RecoverHandlerError` to create a `slog.Handler` that catches panics or errors occurring in subsequent handlers within the logging chain. It provides a configurable callback function to handle the error gracefully, preventing application crashes due to logging issues and ensuring robust error reporting. ```Go import ( slogformatter "github.com/samber/slog-formatter" slogmulti "github.com/samber/slog-multi" "log/slog" ) recovery := slogformatter.RecoverHandlerError( func(ctx context.Context, record slog.Record, err error) { // will be called only if subsequent handlers fail or return an error log.Println(err.Error()) }, ) sink := NewSinkHandler(...) logger := slog.New( slogmulti. Pipe(recovery). Handler(sink), ) err := fmt.Errorf("an error") logger.Error("a message", slog.Any("very_private_data", "abcd"), slog.Any("user", user), slog.Any("err", err)) // outputs: // time=2023-04-10T14:00:0.000000+00:00 level=ERROR msg="a message" error.message="an error" error.type="*errors.errorString" user="John doe" very_private_data="********" ``` -------------------------------- ### slog-formatter Common Attribute Formatters API Source: https://github.com/samber/slog-formatter/blob/main/README.md This section details the pre-built, common attribute formatters available in `slog-formatter`. These utilities transform various data types like `time.Time`, `error`, `http.Request`, and `http.Response` into more readable log entries. They also provide functionality for masking sensitive information such as PII and IP addresses. ```APIDOC TimeFormatter: transforms a time.Time into a readable string UnixTimestampFormatter: transforms a time.Time into a unix timestamp. TimezoneConverter: set a time.Time to a different timezone ErrorFormatter: transforms a go error into a readable error HTTPRequestFormatter: transforms a *http.Request into a readable object HTTPResponseFormatter: transforms a *http.Response into a readable object PIIFormatter: hide private Personal Identifiable Information (PII) IPAddressFormatter: hide ip address from logs FlattenFormatterMiddleware: returns a formatter middleware that flatten attributes recursively ``` -------------------------------- ### Format Time as Unix Timestamp in Go slog Source: https://github.com/samber/slog-formatter/blob/main/README.md Demonstrates using `slogformatter.UnixTimestampFormatter` to convert `time.Time` values into a Unix timestamp format (e.g., milliseconds) for `slog` output. This is particularly useful for machine-readable timestamps and integration with systems that prefer numerical time representations. ```Go slogformatter.NewFormatterHandler( slogformatter.UnixTimestampFormatter(time.Millisecond), ) ``` -------------------------------- ### Format slog attributes by generic type with slogformatter.FormatByType Source: https://github.com/samber/slog-formatter/blob/main/README.md Shows how to use `slogformatter.FormatByType` to apply a formatter function to attributes matching a specific generic type, including custom error types. It also provides a note on implementing `slog.LogValuer` for custom types to control their log representation. ```go slogformatter.NewFormatterHandler( // format a custom error type slogformatter.FormatByType[*customError](func(err *customError) slog.Value { return slog.GroupValue( slog.Int("code", err.code), slog.String("message", err.msg), ) }), // format other errors slogformatter.FormatByType[error](func(err error) slog.Value { return slog.GroupValue( slog.Int("code", err.Error()), slog.String("type", reflect.TypeOf(err).String()), ) }), ) ``` ```go type customError struct { ... } func (customError) Error() string { ... } // implements slog.LogValuer func (customError) LogValue() slog.Value { return slog.StringValue(...) } ``` -------------------------------- ### slog-formatter Custom Attribute Formatting API Source: https://github.com/samber/slog-formatter/blob/main/README.md This section describes the API for creating highly customized attribute formatters within `slog-formatter`. These functions allow developers to apply formatting logic to attributes based on various criteria, including their kind, generic type, specific key, or their position within a log group, offering fine-grained control over log output. ```APIDOC Format: pass any attribute into a formatter FormatByKind: pass attributes matching slog.Kind into a formatter FormatByType: pass attributes matching generic type into a formatter FormatByKey: pass attributes matching key into a formatter FormatByFieldType: pass attributes matching both key and generic type into a formatter FormatByGroup: pass attributes under a group into a formatter FormatByGroupKey: pass attributes under a group and matching key, into a formatter FormatByGroupKeyType: pass attributes under a group, matching key and matching a generic type, into a formatter ``` -------------------------------- ### Convert Timezone for slog Logs in Go Source: https://github.com/samber/slog-formatter/blob/main/README.md Explains how to use `slogformatter.TimezoneConverter` to adjust the timezone of `time.Time` values within `slog` records. This ensures logs reflect the correct time based on a desired timezone, which is crucial for distributed systems or logs analyzed across different geographical regions. ```Go slogformatter.NewFormatterHandler( slogformatter.TimezoneConverter(time.UTC), ) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.