mirror of
https://github.com/hanzoai/krakend-otel.git
synced 2026-11-03 01:12:56 +00:00
78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
package lura
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/metric"
|
|
|
|
"github.com/luraproject/lura/v2/proxy"
|
|
|
|
kotelconfig "github.com/krakend/krakend-otel/config"
|
|
"github.com/krakend/krakend-otel/state"
|
|
)
|
|
|
|
type middlewareMeter struct {
|
|
duration metric.Float64Histogram
|
|
attrs metric.MeasurementOption
|
|
}
|
|
|
|
func newMiddlewareMeter(s state.OTEL, stageName string, attrs []attribute.KeyValue) (*middlewareMeter, error) {
|
|
if s == nil {
|
|
return nil, errors.New("no OTEL state provided")
|
|
}
|
|
mAttrs := make([]attribute.KeyValue, 0, len(attrs))
|
|
mAttrs = append(mAttrs, attrs...)
|
|
|
|
meter := s.Meter()
|
|
if meter == nil {
|
|
return nil, errors.New("OTEL state returned nil meter")
|
|
}
|
|
var err error
|
|
durationName := "krakend." + stageName + ".duration"
|
|
duration, err := meter.Float64Histogram(durationName, kotelconfig.TimeBucketsOpt)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &middlewareMeter{
|
|
duration: duration,
|
|
attrs: metric.WithAttributes(mAttrs...),
|
|
}, nil
|
|
}
|
|
|
|
// multiError is an interface that is implemented by lura at the
|
|
// proxy level to gather errors for each of the backends
|
|
type multiError interface {
|
|
error
|
|
Errors() []error
|
|
}
|
|
|
|
func (m *middlewareMeter) report(ctx context.Context, secs float64, resp *proxy.Response, err error) {
|
|
isErr := false
|
|
isCanceled := false
|
|
if err != nil {
|
|
if errors.Is(err, context.Canceled) || errors.Is(ctx.Err(), context.Canceled) {
|
|
isCanceled = true
|
|
}
|
|
if mErr, ok := err.(multiError); ok {
|
|
errs := mErr.Errors()
|
|
for _, e := range errs {
|
|
if errors.Is(e, context.Canceled) {
|
|
isCanceled = true
|
|
} else {
|
|
isErr = true
|
|
}
|
|
}
|
|
}
|
|
if !isCanceled {
|
|
isErr = true
|
|
}
|
|
}
|
|
metricDynAttrs := metric.WithAttributes(
|
|
attribute.Bool("error", isErr),
|
|
attribute.Bool("canceled", isCanceled),
|
|
attribute.Bool("complete", resp != nil && resp.IsComplete))
|
|
m.duration.Record(ctx, secs, m.attrs, metricDynAttrs)
|
|
}
|