File size: 2,128 Bytes
fea99b3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | package log
import (
"fmt"
"log/slog"
"os"
"runtime/debug"
)
// OTelCodeStackTrace a stacktrace as a string in the natural representation for the language runtime.
// The representation is to be determined and documented by each language SIG.
// See: https://github.com/open-telemetry/semantic-conventions/blob/v1.29.0/docs/attributes-registry/code.md
const OTelCodeStackTrace = "code.stacktrace"
type propagationStrategy int8
const (
// propagationStrategyPanic will propagate the panic after logging it
propagationStrategyRePanic propagationStrategy = iota
// propagationStrategyExit will exit the program after logging the panic
propagationStrategyExit
// propagationStrategyContinue will continue the program after logging the panic
propagationStrategyContinue
)
type panicLoggerOptions struct {
propagationStrategy propagationStrategy
}
// WithRePanic is an option to set the propagation strategy to propagate the panic after logging it
func WithRePanic(o *panicLoggerOptions) {
o.propagationStrategy = propagationStrategyRePanic
}
// WithExit is an option to set the propagation strategy to exit the program after logging the panic
func WithExit(o *panicLoggerOptions) {
o.propagationStrategy = propagationStrategyExit
}
// WithContinue is an option to set the propagation strategy to continue the program after logging the panic
func WithContinue(o *panicLoggerOptions) {
o.propagationStrategy = propagationStrategyContinue
}
// PanicLogger is a function that logs panics and then propagates the failure based on the propagationStrategy setting
// Usage (in main):
//
// defer log.PanicLogger(log.WithExit)
func PanicLogger(options ...func(*panicLoggerOptions)) {
opts := &panicLoggerOptions{}
for _, o := range options {
o(opts)
}
if r := recover(); r != nil {
description := fmt.Sprintf("panic: %s", r)
slog.Error(description, OTelCodeStackTrace, string(debug.Stack()))
switch opts.propagationStrategy {
case propagationStrategyExit:
os.Exit(1)
case propagationStrategyContinue:
return
case propagationStrategyRePanic:
fallthrough
default:
panic(r)
}
}
}
|