Files
holos/internal/server/interceptor/logger.go
Jeff McCune 8abd03e165 (#175) Log x-request-id and x-b3-trace headers
This patch logs the x-request-id header which makes it straight forward
to correlate the logs with the service mesh logs.

For example, select the request id from the gateway logs by copying the
log from the holos server logs.

```sh
kubectl -n istio-ingress logs -l app=istio-ingressgateway -f \
  | grep --line-buffered '^{' \
  | jq 'select(.request_id=="'d0867115-5795-4096-942e-5ac188cdf618'")'
```

```json
{
  "upstream_local_address": "10.244.1.51:44248",
  "x_forwarded_for": "192.168.2.21",
  "authority": "jeff.app.dev.k2.holos.run:443",
  "upstream_transport_failure_reason": null,
  "connection_termination_details": null,
  "response_code": 200,
  "duration": 6,
  "response_flags": "-",
  "upstream_service_time": "5",
  "upstream_cluster": "outbound|3000||holos.jeff-holos.svc.cluster.local",
  "upstream_host": "10.244.1.249:3000",
  "user_agent": "connect-go/1.16.0 (go1.22.2)",
  "requested_server_name": "jeff.app.dev.k2.holos.run",
  "request_id": "d0867115-5795-4096-942e-5ac188cdf618",
  "start_time": "2024-05-17T03:16:37.900Z",
  "method": "POST",
  "protocol": "HTTP/2",
  "downstream_local_address": "65.102.23.41:443",
  "path": "/holos.user.v1alpha1.UserService/GetUser",
  "bytes_sent": 159,
  "downstream_remote_address": "192.168.2.21:59564",
  "response_code_details": "via_upstream",
  "bytes_received": 0,
  "route_name": "holos-api"
}
```
2024-05-16 20:14:34 -07:00

42 lines
1.2 KiB
Go

package interceptor
import (
"context"
"time"
"connectrpc.com/connect"
"github.com/holos-run/holos/internal/server/middleware/logger"
)
func NewLogger() connect.UnaryInterceptorFunc {
interceptor := func(next connect.UnaryFunc) connect.UnaryFunc {
return connect.UnaryFunc(func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
start := time.Now()
rpcLogger := logger.FromContext(ctx).With(
"procedure", req.Spec().Procedure,
"request_id", req.Header().Get("x-request-id"),
"traceid", req.Header().Get("x-b3-traceid"),
"spanid", req.Header().Get("x-b3-spanid"),
"parentspanid", req.Header().Get("x-b3-parentspanid"),
"sampled", req.Header().Get("x-b3-sampled"),
"host", req.Header().Get("host"),
)
ctx = logger.NewContext(ctx, rpcLogger)
resp, err := next(ctx, req)
go emitLog(ctx, start, err)
return resp, err
})
}
return connect.UnaryInterceptorFunc(interceptor)
}
func emitLog(ctx context.Context, start time.Time, err error) {
log := logger.FromContext(ctx)
if err == nil {
log = log.With("ok", true)
} else {
log = log.With("ok", false, "code", connect.CodeOf(err), "err", err)
}
log.InfoContext(ctx, "response", "duration", time.Since(start))
}