mirror of
https://github.com/foomo/gofuncy.git
synced 2025-10-16 12:25:41 +00:00
refactor: use zap
This commit is contained in:
parent
a7193f6c54
commit
94afcde6ab
@ -74,7 +74,7 @@ func ChannelWithCounterName[T any](name string) ChannelOption[T] {
|
||||
|
||||
func ChannelWithHistogramName(name string) Option {
|
||||
return func(o *Options) {
|
||||
o.histogramName = name
|
||||
o.durationHistogramName = name
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
type contextKey string
|
||||
|
||||
const (
|
||||
NoNameRoutine string = "noname"
|
||||
contextKeyRoutine contextKey = "routine"
|
||||
contextKeyParentRoutine contextKey = "parentRoutine"
|
||||
contextKeySender contextKey = "sender"
|
||||
@ -24,7 +25,7 @@ func RoutineFromContext(ctx context.Context) string {
|
||||
if value, ok := ctx.Value(contextKeyRoutine).(string); ok {
|
||||
return value
|
||||
}
|
||||
return "noname"
|
||||
return NoNameRoutine
|
||||
}
|
||||
|
||||
func injectSenderIntoContext(ctx context.Context, name string) context.Context {
|
||||
|
||||
134
go.go
134
go.go
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
@ -15,23 +14,27 @@ import (
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.30.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
type (
|
||||
Options struct {
|
||||
l *slog.Logger
|
||||
l *zap.Logger
|
||||
ctx context.Context //nolint:containedctx // required
|
||||
level slog.Level
|
||||
level zapcore.Level
|
||||
name string
|
||||
// telemetry
|
||||
meter metric.Meter
|
||||
tracer trace.Tracer
|
||||
counter metric.Int64UpDownCounter
|
||||
counterName string
|
||||
histogram metric.Int64Histogram
|
||||
histogramName string
|
||||
histogramEnabled bool
|
||||
telemetryEnabled bool
|
||||
meter metric.Meter
|
||||
tracer trace.Tracer
|
||||
totalCounter metric.Int64Counter
|
||||
totalCounterName string
|
||||
runningCounter metric.Int64UpDownCounter
|
||||
runningCounterName string
|
||||
durationHistogram metric.Int64Histogram
|
||||
durationHistogramName string
|
||||
durationHistogramEnabled bool
|
||||
telemetryEnabled bool
|
||||
}
|
||||
Option func(*Options)
|
||||
)
|
||||
@ -48,13 +51,13 @@ func WithContext(ctx context.Context) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func WithLogger(l *slog.Logger) Option {
|
||||
func WithLogger(l *zap.Logger) Option {
|
||||
return func(o *Options) {
|
||||
o.l = l
|
||||
}
|
||||
}
|
||||
|
||||
func WithLogLevel(level slog.Level) Option {
|
||||
func WithLogLevel(level zapcore.Level) Option {
|
||||
return func(o *Options) {
|
||||
o.level = level
|
||||
}
|
||||
@ -72,31 +75,38 @@ func WithTracer(v trace.Tracer) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func WithCounterName(name string) Option {
|
||||
func WithTotalCounterName(name string) Option {
|
||||
return func(o *Options) {
|
||||
o.counterName = name
|
||||
o.totalCounterName = name
|
||||
}
|
||||
}
|
||||
|
||||
func WithHistogramEnabled(v bool) Option {
|
||||
func WithRunningCounterName(name string) Option {
|
||||
return func(o *Options) {
|
||||
o.histogramEnabled = v
|
||||
o.runningCounterName = name
|
||||
}
|
||||
}
|
||||
|
||||
func WithDurationHistogramEnabled(v bool) Option {
|
||||
return func(o *Options) {
|
||||
o.durationHistogramEnabled = v
|
||||
}
|
||||
}
|
||||
|
||||
func WithHistogramName(name string) Option {
|
||||
return func(o *Options) {
|
||||
o.histogramName = name
|
||||
o.durationHistogramName = name
|
||||
}
|
||||
}
|
||||
|
||||
func Go(fn Func, opts ...Option) <-chan error {
|
||||
o := &Options{
|
||||
l: slog.Default(),
|
||||
level: slog.LevelDebug,
|
||||
counterName: "gofuncy.routine.count",
|
||||
histogramName: "gofuncy.routine.duration",
|
||||
telemetryEnabled: os.Getenv("OTEL_ENABLED") == "true",
|
||||
l: zap.NewNop(),
|
||||
level: zapcore.DebugLevel,
|
||||
totalCounterName: "gofuncy.routine.total.count",
|
||||
runningCounterName: "gofuncy.routine.running.count",
|
||||
durationHistogramName: "gofuncy.routine.duration",
|
||||
telemetryEnabled: os.Getenv("OTEL_ENABLED") == "true",
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
@ -125,74 +135,86 @@ func Go(fn Func, opts ...Option) <-chan error {
|
||||
}
|
||||
}
|
||||
if o.meter != nil {
|
||||
if value, err := o.meter.Int64UpDownCounter(
|
||||
o.counterName,
|
||||
metric.WithDescription("Gofuncy routine counter"),
|
||||
if value, err := o.meter.Int64Counter(
|
||||
o.totalCounterName,
|
||||
metric.WithDescription("Gofuncy total go routine count"),
|
||||
); err != nil {
|
||||
o.l.Error("failed to initialize counter", "error", err)
|
||||
o.l.Error("failed to initialize counter", zap.Error(err))
|
||||
} else {
|
||||
o.counter = value
|
||||
o.totalCounter = value
|
||||
}
|
||||
if value, err := o.meter.Int64UpDownCounter(
|
||||
o.runningCounterName,
|
||||
metric.WithDescription("Gofuncy running go routine count"),
|
||||
); err != nil {
|
||||
o.l.Error("failed to initialize counter", zap.Error(err))
|
||||
} else {
|
||||
o.runningCounter = value
|
||||
}
|
||||
}
|
||||
if o.meter != nil && o.histogramEnabled {
|
||||
if o.meter != nil && o.durationHistogramEnabled {
|
||||
if value, err := o.meter.Int64Histogram(
|
||||
o.histogramName,
|
||||
metric.WithDescription("Gofuncy routine duration histogram"),
|
||||
o.durationHistogramName,
|
||||
metric.WithDescription("Gofuncy go routine duration histogram"),
|
||||
); err != nil {
|
||||
o.l.Error("failed to initialize histogram", "error", err)
|
||||
o.l.Error("failed to initialize histogram", zap.Error(err))
|
||||
} else {
|
||||
o.histogram = value
|
||||
o.durationHistogram = value
|
||||
}
|
||||
}
|
||||
|
||||
delay := time.Now()
|
||||
errChan := make(chan error, 1)
|
||||
go func(o *Options, errChan chan<- error) {
|
||||
var err error
|
||||
defer func() {
|
||||
o.l.Info("gofuncy --> closing chan")
|
||||
close(errChan)
|
||||
o.l.Info("gofuncy --> closing chan")
|
||||
}()
|
||||
ctx := o.ctx
|
||||
start := time.Now()
|
||||
l := o.l.With("name", o.name)
|
||||
if value := RoutineFromContext(ctx); value != "" {
|
||||
l = l.With("parent", value)
|
||||
defer close(errChan)
|
||||
l := o.l.With(zap.String("name", o.name))
|
||||
if value := RoutineFromContext(ctx); value != NoNameRoutine {
|
||||
l = l.With(zap.String("parent", value))
|
||||
}
|
||||
var span trace.Span
|
||||
if o.tracer != nil {
|
||||
ctx, span = o.tracer.Start(o.ctx, o.name)
|
||||
if span.IsRecording() {
|
||||
l = l.With("trace_id", span.SpanContext().TraceID().String())
|
||||
l = l.With(zap.String("trace_id", span.SpanContext().TraceID().String()))
|
||||
}
|
||||
defer span.End()
|
||||
}
|
||||
l.Log(ctx, o.level, "starting gofuncy routine")
|
||||
l.Log(o.level, "starting gofuncy routine",
|
||||
zap.Duration("delay", time.Since(delay).Round(time.Millisecond)),
|
||||
)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
l = l.With("error", err.Error())
|
||||
}
|
||||
l.Log(ctx, o.level, "exiting gofuncy routine", "duration", time.Since(start).Round(time.Millisecond).String())
|
||||
l.Log(o.level, "exiting gofuncy routine",
|
||||
zap.Duration("duration", time.Since(start).Round(time.Millisecond)),
|
||||
zap.Error(err),
|
||||
)
|
||||
}()
|
||||
// create telemetry if enabled
|
||||
if o.counter != nil {
|
||||
attrs := metric.WithAttributes(semconv.ProcessRuntimeName(o.name))
|
||||
o.counter.Add(ctx, 1, attrs)
|
||||
defer o.counter.Add(ctx, -1, attrs)
|
||||
attrs := metric.WithAttributes(semconv.ProcessRuntimeName(o.name))
|
||||
if o.runningCounter != nil {
|
||||
o.runningCounter.Add(ctx, 1, attrs)
|
||||
defer o.runningCounter.Add(ctx, -1, attrs)
|
||||
}
|
||||
if o.histogram != nil {
|
||||
start := time.Now()
|
||||
defer o.histogram.Record(ctx, time.Since(start).Milliseconds(), metric.WithAttributes(
|
||||
semconv.ProcessRuntimeName(o.name),
|
||||
if o.totalCounter != nil {
|
||||
o.totalCounter.Add(ctx, 1, attrs)
|
||||
defer o.runningCounter.Add(ctx, -1, attrs, metric.WithAttributes(
|
||||
attribute.Bool("error", err != nil),
|
||||
))
|
||||
}
|
||||
if o.durationHistogram != nil {
|
||||
defer func() {
|
||||
o.durationHistogram.Record(ctx, time.Since(start).Milliseconds(), attrs, metric.WithAttributes(
|
||||
attribute.Bool("error", err != nil),
|
||||
))
|
||||
}()
|
||||
}
|
||||
ctx = injectParentRoutineIntoContext(ctx, RoutineFromContext(ctx))
|
||||
ctx = injectRoutineIntoContext(ctx, o.name)
|
||||
err = fn(ctx)
|
||||
errChan <- err
|
||||
}(o, errChan)
|
||||
|
||||
o.l.Info("gofuncy --> returning")
|
||||
return errChan
|
||||
}
|
||||
|
||||
2
go.mod
2
go.mod
@ -8,6 +8,7 @@ require (
|
||||
go.opentelemetry.io/otel v1.35.0
|
||||
go.opentelemetry.io/otel/metric v1.35.0
|
||||
go.opentelemetry.io/otel/trace v1.35.0
|
||||
go.uber.org/zap v1.27.0
|
||||
)
|
||||
|
||||
require (
|
||||
@ -17,5 +18,6 @@ require (
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
27
go.sum
27
go.sum
@ -7,31 +7,36 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
|
||||
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
|
||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
|
||||
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
|
||||
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
Loading…
Reference in New Issue
Block a user