Files
krakend-otel/http/server/traces.go
T

83 lines
2.1 KiB
Go

package server
import (
"net/http"
"strings"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/semconv/v1.21.0"
"go.opentelemetry.io/otel/trace"
otelhttp "github.com/krakend/krakend-otel/http"
)
type tracesHTTP struct {
tracer trace.Tracer
fixedAttrs []attribute.KeyValue
reportHeaders bool
}
func newTracesHTTP(tracer trace.Tracer, attrs []attribute.KeyValue, reportHeaders bool) *tracesHTTP {
var fa []attribute.KeyValue
if len(attrs) > 0 {
fa = make([]attribute.KeyValue, len(attrs))
copy(fa, attrs)
}
return &tracesHTTP{
tracer: tracer,
fixedAttrs: fa,
reportHeaders: reportHeaders,
}
}
// start starts a trace from using the handlerTracking information provided.
//
// When traces are disabled, the tracer will be nil.
func (t *tracesHTTP) start(r *http.Request, tr *tracking) *http.Request {
if t == nil || t.tracer == nil || r.URL == nil {
return r
}
tr.ctx, tr.span = t.tracer.Start(r.Context(), r.URL.Path)
r = r.WithContext(tr.ctx)
attrs := otelhttp.TraceRequestAttrs(r)
tr.span.SetAttributes(attrs...)
if len(t.fixedAttrs) > 0 {
tr.span.SetAttributes(t.fixedAttrs...)
}
if t.reportHeaders {
// report all incoming headers
for hk, hv := range r.Header {
tr.span.SetAttributes(attribute.StringSlice("http.request.header."+strings.ToLower(hk), hv))
}
}
return r
}
// end finishes the span started and tracked using the [handlerTracking] info.
func (t *tracesHTTP) end(tr *tracking) {
if t == nil || tr.span == nil || !tr.span.IsRecording() {
return
}
tr.span.SetAttributes(
semconv.HTTPRoute(tr.EndpointPattern()),
semconv.HTTPResponseStatusCode(tr.responseStatus),
semconv.HTTPResponseBodySize(tr.responseSize))
if tr.responseHeaders != nil {
// report all incoming headers
for hk, hv := range tr.responseHeaders {
tr.span.SetAttributes(attribute.StringSlice("http.response.header."+strings.ToLower(hk), hv))
}
}
if len(tr.writeErrs) > 0 {
e := tr.writeErrs[0]
tr.span.RecordError(e)
tr.span.SetStatus(codes.Error, e.Error())
} else {
tr.span.SetStatus(codes.Ok, "")
}
tr.span.End()
}