Skip to content

Commit

Permalink
update attributes for pipe and backend stage
Browse files Browse the repository at this point in the history
  • Loading branch information
dhontecillas committed Jan 21, 2024
1 parent b379954 commit e724ddb
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 10 deletions.
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,20 @@ At the router level we have 3 main options:
}
```

##### Metrics

- `router-response-latency`: histogram of the time it takes to produce the response.
Attributes:
- `http.response.status_code`: status code of the produced response
- `url.path`: the matched endpoint path
- `krakend.stage`: always with value `router`
- `router-response-size`: histogram of the size of the body produced for the response.
Attributes:
- `http.response.status_code`: status code of the produced response
- `url.path`: the matched endpoint path
- `kakend.stage`: always with value `router`


#### pipe

At the pipe level we only have 2 options:
Expand All @@ -135,6 +149,26 @@ At the pipe level we only have 2 options:
}
```

##### Metrics

- `stage-duration`: histogram of the time it takes to produce the response.
Attributes:
- `url.path`: the matched endpoint path that **krakend is serving** (is different
than in `backend`, krakend stage, when this property is the path
for the backend we are targetting).
- `krakend.stage`: always with value `pipe`

##### Traces

Attributes:

- `krakend.stage`: always with value `pipe`
- `complete`: a `true` / `false` value to know when a response is complete (all
backends returned a successful response).
- `canceled`: if appears, will always be `true`, and indicates a request
that has been canceled (usually when parallel requests are used).
- `error`: in case an error happened, the description of the error.

#### backend

At the backend level is where we have more granularity selecting the information
Expand Down Expand Up @@ -186,6 +220,31 @@ For both, the `metrics` and `traces` part, we can select the same options:
}
```

##### Metrics

- `stage-duration`: histogram of the time it takes to produce the response. Controlled
by the `disable_stage` flag (if set to `true` this metric will not appear).
Attributes:
- `url.path`: the matched endpoint path that **krakend is serving** (is different
than in `backend`, krakend stage, when this property is the path
for the backend we are targetting).
- `krakend.stage`: always with value `backend`
- `krakend.endpoint`: this attribute is set to the krakend exposed endpoint that
is the "parent" of the backend request.
- `server.address`: the target host (in case more than one are provided, those
are joined with `_`).

##### Traces

**Stage Span** attributes (controlled by the `disable_stage` flag: will not appear if set to `true`):

- `krakend.stage`: always with value `pipe`
- `complete`: a `true` / `false` value to know when a response is complete (all
backends returned a successful response).
- `canceled`: if appears, will always be `true`, and indicates a request
that has been canceled (usually when parallel requests are used).
- `error`: in case an error happened, the description of the error.

### Instance

Given that any Exporter could implement both traces and metrics, we might want
Expand Down
36 changes: 26 additions & 10 deletions lura/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package lura
import (
"context"
"errors"
"strings"
"time"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/semconv/v1.21.0"
"go.opentelemetry.io/otel/trace"

"github.com/luraproject/lura/v2/config"
Expand Down Expand Up @@ -34,9 +36,11 @@ var (
)
)

// Middleare creates a proxy that instruments the proxy it wraps by creating an span if enabled,
// Middleware creates a proxy that instruments the proxy it wraps by creating an span if enabled,
// and report the duration of this stage in metrics if enabled.
func Middleware(name string, stage string, gsf state.GetterFn, metricsEnabled bool, tracesEnabled bool) proxy.Middleware {
func Middleware(staticAttrs []attribute.KeyValue, gsf state.GetterFn, metricsEnabled bool, tracesEnabled bool,
spanName string) proxy.Middleware {

if gsf == nil {
gsf = state.GlobalState
}
Expand All @@ -62,10 +66,7 @@ func Middleware(name string, stage string, gsf state.GetterFn, metricsEnabled bo
if err != nil {
reportMetrics = false
}
metricAttrs := metric.WithAttributes(
attribute.String("krakend.name", name),
attribute.String("krakend.stage", stage),
)
metricAttrs := metric.WithAttributes(staticAttrs...)

reportTrace := tracesEnabled
tracer := gs.Tracer()
Expand All @@ -83,15 +84,15 @@ func Middleware(name string, stage string, gsf state.GetterFn, metricsEnabled bo
ctx = trace.ContextWithSpan(ctx, ginSpan)
}
// start the new Context, for the stage:
ctx, span = tracer.Start(ctx, name)
ctx, span = tracer.Start(ctx, spanName)
if ginSpan != nil {
// we need to update the key with the new span, otherwise, deeper middlewares
// (like when from pipe -> proxy), would get the span from the parent, instead
// of the one in the context
ctx = context.WithValue(ctx, state.KrakenDContextOTELStrKey, span)
}
// TODO: CHECK that we have this attribute set !!
span.SetAttributes(attribute.String("krakend.stage", stage))
span.SetAttributes(staticAttrs...)
}

startedAt := time.Now()
Expand Down Expand Up @@ -154,7 +155,11 @@ func ProxyFactory(pf proxy.Factory, gsfn state.GetterFn, opts *kotelconfig.PipeO
// in original opencensus, we prefixed the endpoint with a `pipe` prefix
// return Middleware("pipe-" + cfg.Endpoint)(next), nil
urlPattern := kotelconfig.NormalizeURLPattern(cfg.Endpoint)
return Middleware(urlPattern, "pipe", gsfn, metricsEnabled, tracesEnabled)(next), nil
staticAttrs := []attribute.KeyValue{
semconv.URLPath(urlPattern),
attribute.String("krakend.stage", "pipe"),
}
return Middleware(staticAttrs, gsfn, metricsEnabled, tracesEnabled, urlPattern)(next), nil
}
}

Expand All @@ -177,6 +182,17 @@ func BackendFactory(bf proxy.BackendFactory, gsfn state.GetterFn, opts *kotelcon
}
}
urlPattern := kotelconfig.NormalizeURLPattern(cfg.URLPattern)
return Middleware(urlPattern, "backend", gsfn, metricsEnabled, tracesEnabled)(next)
parentEndpoint := kotelconfig.NormalizeURLPattern(cfg.ParentEndpoint)
hosts := strings.Join(cfg.Host, "_")
// TODO: check if we want to have the hosts as static attribute
staticAttrs := []attribute.KeyValue{
semconv.URLPath(urlPattern),
attribute.String("krakend.stage", "backend"),
attribute.String("krakend.endpoint", parentEndpoint),
semconv.ServerAddress(hosts),
}
// TODO: check if we want to have the hosts, to paths that are the same, but for different hosts
spanName := strings.Join(cfg.Host, "_") + urlPattern
return Middleware(staticAttrs, gsfn, metricsEnabled, tracesEnabled, spanName)(next)
}
}

0 comments on commit e724ddb

Please sign in to comment.