refactor(reqlog): print for request and response individually

This commit is contained in:
DevMiner 2024-07-31 17:06:27 +02:00
parent 7aa4621e13
commit aff39e4343

View file

@ -11,69 +11,95 @@ import (
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
) )
const requestBufferSize = 1000 const reqLoggerBufSize = 1000
func RequestLogger(l zerolog.Logger, requestHeaders, responseHeaders bool) fiber.Handler { func RequestLogger(l zerolog.Logger, requestHeaders, responseHeaders bool) fiber.Handler {
type request struct { type request struct {
Method string Method string
Path string Path string
Start time.Time
RequestHeaders map[string][]string
OtelSpanID *trace.SpanID
SentrySpanID *sentry.SpanID
}
type response struct {
Status int Status int
End time.Time
Duration time.Duration Duration time.Duration
RequestHeaders map[string][]string
ResponseHeaders map[string][]string ResponseHeaders map[string][]string
OtelSpanID *trace.SpanID OtelSpanID *trace.SpanID
SentrySpanID *sentry.SpanID SentrySpanID *sentry.SpanID
} }
reqs := make(chan request, requestBufferSize) reqCh := make(chan request, reqLoggerBufSize)
resCh := make(chan response, reqLoggerBufSize)
formatHeaderAttribute := func(t, k string, v []string, i int) string {
attr := fmt.Sprintf("%s.headers.%s", t, k)
if len(v) != 1 {
attr = fmt.Sprintf("%s.%d", attr, i)
}
return attr
}
go func() { go func() {
for { for {
r := <-reqs select {
case r := <-reqCh:
l2 := l.Trace().
Str("method", r.Method).
Str("path", r.Path).
Time("start", r.Start)
l2 := l.Trace(). if r.OtelSpanID != nil {
Str("method", r.Method). l2 = l2.Str("otel_span_id", r.OtelSpanID.String())
Str("path", r.Path). }
Int("status", r.Status).
Dur("duration", r.Duration)
if r.OtelSpanID != nil { if r.SentrySpanID != nil {
l2 = l2.Str("otel_span_id", r.OtelSpanID.String()) l2 = l2.Str("sentry_span_id", r.SentrySpanID.String())
} }
if r.SentrySpanID != nil { if requestHeaders {
l2 = l2.Str("sentry_span_id", r.SentrySpanID.String()) for k, v := range r.RequestHeaders {
} for i, vv := range v {
attr := formatHeaderAttribute("request", k, v, i)
if requestHeaders { l2 = l2.Str(attr, vv)
for k, v := range r.RequestHeaders {
for i, vv := range v {
attr := fmt.Sprintf("request.headers.%s", k)
if len(v) != 1 {
attr = fmt.Sprintf("%s.%d", attr, i)
} }
l2 = l2.Str(attr, vv)
} }
} }
}
if responseHeaders { l2.Msg("request")
for k, v := range r.ResponseHeaders {
for i, vv := range v {
attr := fmt.Sprintf("response.headers.%s", k)
if len(v) != 1 { case r := <-resCh:
attr = fmt.Sprintf("%s.%d", attr, i) l2 := l.Trace().
Int("status", r.Status).
Time("end", r.End).
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())
}
if responseHeaders {
for k, v := range r.ResponseHeaders {
for i, vv := range v {
attr := formatHeaderAttribute("response", k, v, i)
l2 = l2.Str(attr, vv)
} }
l2 = l2.Str(attr, vv)
} }
} }
}
l2.Msg("request") l2.Msg("response")
}
} }
}() }()
@ -88,26 +114,11 @@ func RequestLogger(l zerolog.Logger, requestHeaders, responseHeaders bool) fiber
sentrySpanId = &span.SpanID sentrySpanId = &span.SpanID
} }
start := time.Now() // pushing the request to the logger, so we don't block the handling
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
req := request{ req := request{
Method: c.Method(), Method: c.Method(),
Path: c.Path(), Path: c.Path(),
Status: status, Start: time.Now(),
Duration: duration,
OtelSpanID: otelSpanId, OtelSpanID: otelSpanId,
SentrySpanID: sentrySpanId, SentrySpanID: sentrySpanId,
} }
@ -120,17 +131,41 @@ func RequestLogger(l zerolog.Logger, requestHeaders, responseHeaders bool) fiber
} }
} }
} }
reqCh <- req
start := time.Now()
err := c.Next()
end := time.Now()
status := c.Response().StatusCode()
if err != nil {
if e, ok := err.(*fiber.Error); ok {
status = e.Code
} else {
status = fiber.StatusInternalServerError
}
}
// pushing the response to the logger, so we don't block the handling
res := response{
Status: status,
End: end,
Duration: end.Sub(start),
OtelSpanID: otelSpanId,
SentrySpanID: sentrySpanId,
}
if responseHeaders { if responseHeaders {
req.ResponseHeaders = make(map[string][]string) res.ResponseHeaders = make(map[string][]string)
for k, v := range c.GetRespHeaders() { for k, v := range c.GetRespHeaders() {
for _, vv := range v { for _, vv := range v {
req.ResponseHeaders[k] = append(req.ResponseHeaders[k], utils.CopyString(vv)) res.ResponseHeaders[k] = append(res.ResponseHeaders[k], utils.CopyString(vv))
} }
} }
} }
reqs <- req resCh <- res
return err return err
} }