package unitel import ( "time" "github.com/getsentry/sentry-go" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog" "go.opentelemetry.io/otel/trace" ) const requestBufferSize = 1000 func RequestLogger(l zerolog.Logger) fiber.Handler { type request struct { Method string Path string Status int Duration time.Duration OtelSpanID *trace.SpanID SentrySpanID *sentry.SpanID } reqs := make(chan request, requestBufferSize) go func() { for { r := <-reqs l2 := l.Trace(). Str("method", r.Method). Str("path", r.Path). Int("status", r.Status). Dur("duration", r.Duration) if r.OtelSpanID != nil { l2 = l2.Str("otel_span_id", r.OtelSpanID.String()) } if r.SentrySpanID != nil { l2 = l2.Str("sentry_span_id", r.SentrySpanID.String()) } l2.Msg("request") } }() return func(c *fiber.Ctx) error { var otelSpanId *trace.SpanID = nil if spanId := trace.SpanContextFromContext(c.UserContext()).SpanID(); spanId.IsValid() { otelSpanId = &spanId } var sentrySpanId *sentry.SpanID = nil if span := sentry.SpanFromContext(c.UserContext()); span != nil { sentrySpanId = &span.SpanID } start := time.Now() err := c.Next() duration := time.Since(start) status := c.Response().StatusCode() if err != nil { if e, ok := err.(*fiber.Error); ok { status = e.Code } else { status = fiber.StatusInternalServerError } } // pushing the request to the logger, so we don't block the requests reqs <- request{ Method: c.Method(), Path: c.Path(), Status: status, Duration: duration, OtelSpanID: otelSpanId, SentrySpanID: sentrySpanId, } return err } }