mirror of
https://github.com/foomo/keel.git
synced 2025-10-16 12:35:34 +00:00
88 lines
2.2 KiB
Go
88 lines
2.2 KiB
Go
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/foomo/keel/log"
|
|
httplog "github.com/foomo/keel/net/http/log"
|
|
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
|
"go.opentelemetry.io/otel"
|
|
"go.opentelemetry.io/otel/propagation"
|
|
"go.opentelemetry.io/otel/trace"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type (
|
|
TelemetryOptions struct {
|
|
Name string
|
|
OtelOpts []otelhttp.Option
|
|
InjectPropagationHeader bool
|
|
}
|
|
TelemetryOption func(*TelemetryOptions)
|
|
)
|
|
|
|
// GetDefaultTelemetryOptions returns the default options
|
|
func GetDefaultTelemetryOptions() TelemetryOptions {
|
|
return TelemetryOptions{
|
|
OtelOpts: []otelhttp.Option{},
|
|
InjectPropagationHeader: true,
|
|
}
|
|
}
|
|
|
|
// Telemetry middleware
|
|
func Telemetry(opts ...TelemetryOption) Middleware {
|
|
options := GetDefaultTelemetryOptions()
|
|
for _, opt := range opts {
|
|
if opt != nil {
|
|
opt(&options)
|
|
}
|
|
}
|
|
return TelemetryWithOptions(options)
|
|
}
|
|
|
|
func TelemetryWithName(v string) TelemetryOption {
|
|
return func(o *TelemetryOptions) {
|
|
o.Name = v
|
|
}
|
|
}
|
|
|
|
func TelemetryWithInjectPropagationHeader(v bool) TelemetryOption {
|
|
return func(o *TelemetryOptions) {
|
|
o.InjectPropagationHeader = v
|
|
}
|
|
}
|
|
|
|
// TelemetryWithOtelOpts middleware options
|
|
func TelemetryWithOtelOpts(v ...otelhttp.Option) TelemetryOption {
|
|
return func(o *TelemetryOptions) {
|
|
o.OtelOpts = v
|
|
}
|
|
}
|
|
|
|
// TelemetryWithOptions middleware
|
|
func TelemetryWithOptions(opts TelemetryOptions) Middleware {
|
|
return func(l *zap.Logger, name string, next http.Handler) http.Handler {
|
|
if opts.Name != "" {
|
|
name = opts.Name
|
|
}
|
|
|
|
return otelhttp.NewHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if opts.InjectPropagationHeader {
|
|
otel.GetTextMapPropagator().Inject(r.Context(), propagation.HeaderCarrier(w.Header()))
|
|
}
|
|
|
|
if labeler, ok := httplog.LabelerFromRequest(r); ok {
|
|
if spanCtx := trace.SpanContextFromContext(r.Context()); spanCtx.IsValid() && spanCtx.IsSampled() {
|
|
labeler.Add(log.FTraceID(spanCtx.TraceID().String()))
|
|
labeler.Add(log.FSpanID(spanCtx.SpanID().String()))
|
|
}
|
|
}
|
|
|
|
// wrap response write to get access to status & size
|
|
wr := WrapResponseWriter(w)
|
|
|
|
next.ServeHTTP(wr, r)
|
|
}), name, opts.OtelOpts...)
|
|
}
|
|
}
|