2024-05-21 05:54:22 +00:00
|
|
|
package fiber_tracing
|
|
|
|
|
|
|
|
// This was copied from "github.com/psmarcin/fiber-opentelemetry/pkg/fiber-otel"
|
|
|
|
// and slighltly modified but this piece of code is yet to be fully integrated
|
|
|
|
// into the package.
|
|
|
|
|
|
|
|
import (
|
2024-05-27 05:37:54 +00:00
|
|
|
"git.ma-al.com/maal-libraries/observer/pkg/attr"
|
2024-05-21 05:54:22 +00:00
|
|
|
"github.com/gofiber/fiber/v2"
|
|
|
|
"go.opentelemetry.io/otel"
|
2024-07-24 13:19:51 +00:00
|
|
|
"go.opentelemetry.io/otel/propagation"
|
2024-05-21 05:54:22 +00:00
|
|
|
semconv "go.opentelemetry.io/otel/semconv/v1.25.0"
|
|
|
|
"go.opentelemetry.io/otel/trace"
|
|
|
|
)
|
|
|
|
|
|
|
|
var Tracer = otel.Tracer("fiber_tracing_middleware")
|
|
|
|
|
|
|
|
// Config defines the config for middleware.
|
|
|
|
type middlewareConfig struct {
|
|
|
|
Tracer trace.Tracer
|
|
|
|
TracerStartAttributes []trace.SpanStartOption
|
|
|
|
}
|
|
|
|
|
|
|
|
// ConfigDefault is the default config
|
|
|
|
var configDefault = middlewareConfig{
|
|
|
|
Tracer: Tracer,
|
|
|
|
TracerStartAttributes: []trace.SpanStartOption{
|
|
|
|
trace.WithNewRoot(),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
// Helper function to set default values
|
|
|
|
func configDefaults(config ...middlewareConfig) middlewareConfig {
|
|
|
|
// Return default config if nothing provided
|
|
|
|
if len(config) < 1 {
|
|
|
|
return configDefault
|
|
|
|
}
|
|
|
|
|
|
|
|
// Override default config
|
|
|
|
cfg := config[0]
|
|
|
|
|
|
|
|
if len(cfg.TracerStartAttributes) == 0 {
|
|
|
|
cfg.TracerStartAttributes = configDefault.TracerStartAttributes
|
|
|
|
}
|
|
|
|
|
|
|
|
return cfg
|
|
|
|
}
|
|
|
|
|
2024-07-24 13:19:51 +00:00
|
|
|
// A helper implementing `propagation.TextMapCarrier`
|
|
|
|
type headersCarrier struct {
|
|
|
|
*fiber.Ctx
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h headersCarrier) Get(key string) string {
|
|
|
|
c := h.Ctx
|
|
|
|
headers := c.GetReqHeaders()
|
|
|
|
if val, ok := headers[key]; ok {
|
|
|
|
if len(val) > 0 {
|
|
|
|
return val[len(val)-1]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h headersCarrier) Set(key string, value string) {
|
|
|
|
c := h.Ctx
|
|
|
|
c.Set(key, value)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h headersCarrier) Keys() []string {
|
|
|
|
c := h.Ctx
|
|
|
|
headers := c.GetRespHeaders()
|
|
|
|
keys := make([]string, 0)
|
|
|
|
for k, _ := range headers {
|
|
|
|
keys = append(keys, k)
|
|
|
|
}
|
|
|
|
return keys
|
|
|
|
}
|
|
|
|
|
2024-05-21 05:54:22 +00:00
|
|
|
func new(config ...middlewareConfig) fiber.Handler {
|
|
|
|
// Set default config
|
|
|
|
cfg := configDefaults(config...)
|
|
|
|
|
|
|
|
// Return new handler
|
|
|
|
return func(c *fiber.Ctx) error {
|
2024-05-27 05:37:54 +00:00
|
|
|
spanStartAttributes := []attr.KeyValue{
|
2024-05-21 05:54:22 +00:00
|
|
|
semconv.HTTPMethod(c.Method()),
|
|
|
|
semconv.HTTPTarget(string(c.Request().RequestURI())),
|
|
|
|
semconv.HTTPURL(c.OriginalURL()),
|
|
|
|
semconv.HTTPUserAgent(string(c.Request().Header.UserAgent())),
|
|
|
|
semconv.HTTPRequestContentLength(c.Request().Header.ContentLength()),
|
|
|
|
semconv.HTTPScheme(c.Protocol()),
|
|
|
|
semconv.NetTransportTCP,
|
2024-05-27 05:37:54 +00:00
|
|
|
}
|
|
|
|
spanStartAttributes = append(spanStartAttributes, attr.ProcessStart()...)
|
2024-05-21 05:54:22 +00:00
|
|
|
|
|
|
|
opts := []trace.SpanStartOption{
|
2024-05-27 05:37:54 +00:00
|
|
|
trace.WithAttributes(spanStartAttributes...),
|
|
|
|
trace.WithSpanKind(trace.SpanKindServer),
|
2024-05-21 05:54:22 +00:00
|
|
|
}
|
|
|
|
opts = append(opts, cfg.TracerStartAttributes...)
|
|
|
|
|
2024-07-24 13:19:51 +00:00
|
|
|
// Init context using values from request headers if possible:
|
|
|
|
headersCarrier := headersCarrier{c}
|
|
|
|
ctx := c.UserContext()
|
|
|
|
tctx := propagation.TraceContext{}
|
|
|
|
ctx = tctx.Extract(ctx, headersCarrier)
|
|
|
|
|
2024-05-21 05:54:22 +00:00
|
|
|
otelCtx, span := Tracer.Start(
|
2024-07-24 13:19:51 +00:00
|
|
|
ctx,
|
2024-05-27 05:37:54 +00:00
|
|
|
c.Method()+" "+c.OriginalURL(),
|
2024-05-21 05:54:22 +00:00
|
|
|
opts...,
|
|
|
|
)
|
|
|
|
|
|
|
|
c.SetUserContext(otelCtx)
|
2024-07-24 13:19:51 +00:00
|
|
|
|
2024-05-21 05:54:22 +00:00
|
|
|
defer span.End()
|
|
|
|
|
|
|
|
err := c.Next()
|
|
|
|
|
|
|
|
statusCode := c.Response().StatusCode()
|
|
|
|
attrs := semconv.HTTPResponseStatusCode(statusCode)
|
|
|
|
span.SetAttributes(attrs)
|
|
|
|
|
2024-07-24 13:19:51 +00:00
|
|
|
// Return with trace context added to headers
|
|
|
|
ctx = c.UserContext()
|
|
|
|
tctx.Inject(ctx, headersCarrier)
|
|
|
|
|
2024-05-21 05:54:22 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|