package server import ( "context" "errors" "fmt" "log/slog" "time" "connectrpc.com/connect" "github.com/tigorlazuardi/bluemage/go/pkg/errs" "github.com/tigorlazuardi/bluemage/go/pkg/telemetry" "go.opentelemetry.io/otel/trace" ) func LogInterceptor() connect.UnaryInterceptorFunc { interceptor := func(next connect.UnaryFunc) connect.UnaryFunc { return func(ctx context.Context, ar connect.AnyRequest) (resp connect.AnyResponse, err error) { span := trace.SpanFromContext(ctx) defer func() { telemetry.EndWithStatus(span, err) }() start := time.Now() resp, err = next(ctx, ar) dur := time.Since(start) if err != nil { slog.ErrorContext(ctx, "RPC Error", "procedure", ar.Spec().Procedure, "method", ar.HTTPMethod(), "duration", fmt.Sprintf("%.3fs", dur.Seconds()), "error", errs.DrillToError(err), "span.id", span.SpanContext().SpanID().String(), "trace.id", span.SpanContext().TraceID().String(), ) } else { slog.InfoContext(ctx, "RPC Call", "procedure", ar.Spec().Procedure, "method", ar.HTTPMethod(), "duration", fmt.Sprintf("%.3fs", dur.Seconds()), "span.id", span.SpanContext().SpanID().String(), "trace.id", span.SpanContext().TraceID().String(), ) } return resp, err } } return connect.UnaryInterceptorFunc(interceptor) } func ErrorMessageInterceptor() connect.UnaryInterceptorFunc { return func(uf connect.UnaryFunc) connect.UnaryFunc { return func(ctx context.Context, ar connect.AnyRequest) (connect.AnyResponse, error) { resp, err := uf(ctx, ar) if err == nil { return resp, err } span := trace.SpanFromContext(ctx) if !span.SpanContext().IsValid() { return resp, err } if cerr := new(connect.Error); errors.As(err, &cerr) { if e := errs.FindError(cerr); e != nil { msg := e.GetMessage() spanContext := span.SpanContext() traceId := spanContext.TraceID().String() e.Message("%s|%s", traceId, msg) } } return resp, err } } }