77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
package restapi
|
|
|
|
import (
|
|
"time"
|
|
|
|
"galaxy/gateway/internal/logging"
|
|
"galaxy/gateway/internal/telemetry"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func withPublicObservability(logger *zap.Logger, metrics *telemetry.Runtime) gin.HandlerFunc {
|
|
if logger == nil {
|
|
logger = zap.NewNop()
|
|
}
|
|
|
|
return func(c *gin.Context) {
|
|
start := time.Now()
|
|
c.Next()
|
|
|
|
statusCode := c.Writer.Status()
|
|
route := c.FullPath()
|
|
if route == "" {
|
|
route = c.Request.URL.Path
|
|
}
|
|
|
|
class, ok := PublicRouteClassFromContext(c.Request.Context())
|
|
if !ok {
|
|
class = PublicRouteClassPublicMisc
|
|
}
|
|
|
|
errorCode, _ := c.Get(publicErrorCodeContextKey)
|
|
errorCodeValue, _ := errorCode.(string)
|
|
|
|
outcome := telemetry.OutcomeFromPublicErrorCode(statusCode, errorCodeValue)
|
|
rejectReason := telemetry.RejectReason(outcome)
|
|
duration := time.Since(start)
|
|
|
|
attrs := []attribute.KeyValue{
|
|
attribute.String("route_class", string(class)),
|
|
attribute.String("route", route),
|
|
attribute.String("method", c.Request.Method),
|
|
attribute.String("edge_outcome", string(outcome)),
|
|
}
|
|
if rejectReason != "" {
|
|
attrs = append(attrs, attribute.String("reject_reason", rejectReason))
|
|
}
|
|
metrics.RecordPublicRequest(c.Request.Context(), attrs, duration)
|
|
|
|
fields := []zap.Field{
|
|
zap.String("component", "public_http"),
|
|
zap.String("transport", "http"),
|
|
zap.String("route", route),
|
|
zap.String("route_class", string(class)),
|
|
zap.String("method", c.Request.Method),
|
|
zap.Int("status_code", statusCode),
|
|
zap.Float64("duration_ms", float64(duration.Microseconds())/1000),
|
|
zap.String("edge_outcome", string(outcome)),
|
|
}
|
|
if rejectReason != "" {
|
|
fields = append(fields, zap.String("reject_reason", rejectReason))
|
|
}
|
|
fields = append(fields, logging.TraceFieldsFromContext(c.Request.Context())...)
|
|
|
|
switch outcome {
|
|
case telemetry.EdgeOutcomeSuccess:
|
|
logger.Info("public request completed", fields...)
|
|
case telemetry.EdgeOutcomeBackendUnavailable, telemetry.EdgeOutcomeInternalError:
|
|
logger.Error("public request failed", fields...)
|
|
default:
|
|
logger.Warn("public request rejected", fields...)
|
|
}
|
|
}
|
|
}
|