mirror of
https://github.com/slackhq/nebula.git
synced 2026-05-11 14:42:02 -07:00
69 lines
1.8 KiB
Go
69 lines
1.8 KiB
Go
package util
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"log/slog"
|
|
)
|
|
|
|
type ContextualError struct {
|
|
RealError error
|
|
Fields map[string]any
|
|
Context string
|
|
}
|
|
|
|
func NewContextualError(msg string, fields map[string]any, realError error) *ContextualError {
|
|
return &ContextualError{Context: msg, Fields: fields, RealError: realError}
|
|
}
|
|
|
|
// ContextualizeIfNeeded is a helper function to turn an error into a ContextualError if it is not already one
|
|
func ContextualizeIfNeeded(msg string, err error) error {
|
|
switch err.(type) {
|
|
case *ContextualError:
|
|
return err
|
|
default:
|
|
return NewContextualError(msg, nil, err)
|
|
}
|
|
}
|
|
|
|
// LogWithContextIfNeeded is a helper function to log an error line for an error or ContextualError
|
|
func LogWithContextIfNeeded(msg string, err error, l *slog.Logger) {
|
|
switch v := err.(type) {
|
|
case *ContextualError:
|
|
v.Log(l)
|
|
default:
|
|
l.Error(msg, "error", err)
|
|
}
|
|
}
|
|
|
|
func (ce *ContextualError) Error() string {
|
|
if ce.RealError == nil {
|
|
return ce.Context
|
|
}
|
|
return fmt.Errorf("%s (%v): %w", ce.Context, ce.Fields, ce.RealError).Error()
|
|
}
|
|
|
|
func (ce *ContextualError) Unwrap() error {
|
|
if ce.RealError == nil {
|
|
return errors.New(ce.Context)
|
|
}
|
|
return ce.RealError
|
|
}
|
|
|
|
// Log emits ce as a single error-level log line with Fields and RealError
|
|
// promoted to top-level attributes, producing a flat shape callers can grep
|
|
// or parse without walking into a nested object.
|
|
func (ce *ContextualError) Log(l *slog.Logger) {
|
|
attrs := make([]slog.Attr, 0, len(ce.Fields)+1)
|
|
for k, v := range ce.Fields {
|
|
attrs = append(attrs, slog.Any(k, v))
|
|
}
|
|
if ce.RealError != nil {
|
|
attrs = append(attrs, slog.Any("error", ce.RealError))
|
|
}
|
|
// LogAttrs is intentional: attrs is built from a map[string]any so it has
|
|
// no pair-form equivalent.
|
|
//nolint:sloglint
|
|
l.LogAttrs(context.Background(), slog.LevelError, ce.Context, attrs...)
|
|
}
|