Skip to content

Instantly share code, notes, and snippets.

@JonCanning
Last active June 20, 2024 15:04
Show Gist options
  • Save JonCanning/ee2737170b974d10bcba5a280d02c0d7 to your computer and use it in GitHub Desktop.
Save JonCanning/ee2737170b974d10bcba5a280d02c0d7 to your computer and use it in GitHub Desktop.
Go Logger
package log
import (
"context"
"log/slog"
"os"
"github.com/covalenthq/lumberjack"
slogmulti "github.com/samber/slog-multi"
"go.opentelemetry.io/otel/trace"
)
type logWithContext func(ctx context.Context, message string, attributes ...attribute)
var (
Debug logWithContext
Info logWithContext
Warn logWithContext
Error func(ctx context.Context, err error, attributes ...attribute)
)
type attribute struct {
Key string
Value any
}
func NewAttribute(key string, value any) attribute {
return attribute{Key: key, Value: value}
}
func InitLogger(serviceName string, version string, environment string, logLevel string) {
logFile := &lumberjack.Logger{
Filename: "logs/log.log",
MaxAge: 7,
}
var slogLevel slog.Level
err := slogLevel.UnmarshalText([]byte(logLevel))
if err != nil {
panic(err)
}
var consoleHandler slog.Handler
if environment == "test" {
consoleHandler = slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slogLevel})
} else {
consoleHandler = slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError})
}
hostname, err := os.Hostname()
if err != nil {
panic(err)
}
fanoutHandler := slogmulti.Fanout(
slog.NewJSONHandler(logFile, &slog.HandlerOptions{Level: slogLevel}),
consoleHandler,
)
slogger := *slog.New(
fanoutHandler,
).With("service.name", serviceName).With("service.version", version).With("environment", environment).With("host.name", hostname)
writeLog := func(ctx context.Context, logF func(ctx context.Context, msg string, args ...any), message string, attributes ...attribute) {
slogAttrs := make([]any, 0)
for _, attribute := range attributes {
slogAttrs = append(slogAttrs, slog.Any(attribute.Key, attribute.Value))
}
spanContext := trace.SpanFromContext(ctx).SpanContext()
if spanContext.IsValid() {
attr := slog.String("trace_id", spanContext.TraceID().String())
slogAttrs = append(slogAttrs, attr)
}
logF(ctx, message, slogAttrs...)
}
Debug = func(ctx context.Context, message string, attributes ...attribute) {
writeLog(ctx, slogger.DebugContext, message, attributes...)
}
Info = func(ctx context.Context, message string, attributes ...attribute) {
writeLog(ctx, slogger.InfoContext, message, attributes...)
}
Warn = func(ctx context.Context, message string, attributes ...attribute) {
writeLog(ctx, slogger.WarnContext, message, attributes...)
}
Error = func(ctx context.Context, err error, attributes ...attribute) {
writeLog(ctx, slogger.ErrorContext, err.Error(), attributes...)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment