Skip to content

Commit e724ddb

Browse files
committed
update attributes for pipe and backend stage
1 parent b379954 commit e724ddb

File tree

2 files changed

+85
-10
lines changed

2 files changed

+85
-10
lines changed

README.md

+59
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,20 @@ At the router level we have 3 main options:
121121
}
122122
```
123123

124+
##### Metrics
125+
126+
- `router-response-latency`: histogram of the time it takes to produce the response.
127+
Attributes:
128+
- `http.response.status_code`: status code of the produced response
129+
- `url.path`: the matched endpoint path
130+
- `krakend.stage`: always with value `router`
131+
- `router-response-size`: histogram of the size of the body produced for the response.
132+
Attributes:
133+
- `http.response.status_code`: status code of the produced response
134+
- `url.path`: the matched endpoint path
135+
- `kakend.stage`: always with value `router`
136+
137+
124138
#### pipe
125139

126140
At the pipe level we only have 2 options:
@@ -135,6 +149,26 @@ At the pipe level we only have 2 options:
135149
}
136150
```
137151

152+
##### Metrics
153+
154+
- `stage-duration`: histogram of the time it takes to produce the response.
155+
Attributes:
156+
- `url.path`: the matched endpoint path that **krakend is serving** (is different
157+
than in `backend`, krakend stage, when this property is the path
158+
for the backend we are targetting).
159+
- `krakend.stage`: always with value `pipe`
160+
161+
##### Traces
162+
163+
Attributes:
164+
165+
- `krakend.stage`: always with value `pipe`
166+
- `complete`: a `true` / `false` value to know when a response is complete (all
167+
backends returned a successful response).
168+
- `canceled`: if appears, will always be `true`, and indicates a request
169+
that has been canceled (usually when parallel requests are used).
170+
- `error`: in case an error happened, the description of the error.
171+
138172
#### backend
139173

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

223+
##### Metrics
224+
225+
- `stage-duration`: histogram of the time it takes to produce the response. Controlled
226+
by the `disable_stage` flag (if set to `true` this metric will not appear).
227+
Attributes:
228+
- `url.path`: the matched endpoint path that **krakend is serving** (is different
229+
than in `backend`, krakend stage, when this property is the path
230+
for the backend we are targetting).
231+
- `krakend.stage`: always with value `backend`
232+
- `krakend.endpoint`: this attribute is set to the krakend exposed endpoint that
233+
is the "parent" of the backend request.
234+
- `server.address`: the target host (in case more than one are provided, those
235+
are joined with `_`).
236+
237+
##### Traces
238+
239+
**Stage Span** attributes (controlled by the `disable_stage` flag: will not appear if set to `true`):
240+
241+
- `krakend.stage`: always with value `pipe`
242+
- `complete`: a `true` / `false` value to know when a response is complete (all
243+
backends returned a successful response).
244+
- `canceled`: if appears, will always be `true`, and indicates a request
245+
that has been canceled (usually when parallel requests are used).
246+
- `error`: in case an error happened, the description of the error.
247+
189248
### Instance
190249

191250
Given that any Exporter could implement both traces and metrics, we might want

lura/proxy.go

+26-10
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ package lura
33
import (
44
"context"
55
"errors"
6+
"strings"
67
"time"
78

89
"go.opentelemetry.io/otel/attribute"
910
"go.opentelemetry.io/otel/metric"
11+
"go.opentelemetry.io/otel/semconv/v1.21.0"
1012
"go.opentelemetry.io/otel/trace"
1113

1214
"github.com/luraproject/lura/v2/config"
@@ -34,9 +36,11 @@ var (
3436
)
3537
)
3638

37-
// Middleare creates a proxy that instruments the proxy it wraps by creating an span if enabled,
39+
// Middleware creates a proxy that instruments the proxy it wraps by creating an span if enabled,
3840
// and report the duration of this stage in metrics if enabled.
39-
func Middleware(name string, stage string, gsf state.GetterFn, metricsEnabled bool, tracesEnabled bool) proxy.Middleware {
41+
func Middleware(staticAttrs []attribute.KeyValue, gsf state.GetterFn, metricsEnabled bool, tracesEnabled bool,
42+
spanName string) proxy.Middleware {
43+
4044
if gsf == nil {
4145
gsf = state.GlobalState
4246
}
@@ -62,10 +66,7 @@ func Middleware(name string, stage string, gsf state.GetterFn, metricsEnabled bo
6266
if err != nil {
6367
reportMetrics = false
6468
}
65-
metricAttrs := metric.WithAttributes(
66-
attribute.String("krakend.name", name),
67-
attribute.String("krakend.stage", stage),
68-
)
69+
metricAttrs := metric.WithAttributes(staticAttrs...)
6970

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

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

@@ -177,6 +182,17 @@ func BackendFactory(bf proxy.BackendFactory, gsfn state.GetterFn, opts *kotelcon
177182
}
178183
}
179184
urlPattern := kotelconfig.NormalizeURLPattern(cfg.URLPattern)
180-
return Middleware(urlPattern, "backend", gsfn, metricsEnabled, tracesEnabled)(next)
185+
parentEndpoint := kotelconfig.NormalizeURLPattern(cfg.ParentEndpoint)
186+
hosts := strings.Join(cfg.Host, "_")
187+
// TODO: check if we want to have the hosts as static attribute
188+
staticAttrs := []attribute.KeyValue{
189+
semconv.URLPath(urlPattern),
190+
attribute.String("krakend.stage", "backend"),
191+
attribute.String("krakend.endpoint", parentEndpoint),
192+
semconv.ServerAddress(hosts),
193+
}
194+
// TODO: check if we want to have the hosts, to paths that are the same, but for different hosts
195+
spanName := strings.Join(cfg.Host, "_") + urlPattern
196+
return Middleware(staticAttrs, gsfn, metricsEnabled, tracesEnabled, spanName)(next)
181197
}
182198
}

0 commit comments

Comments
 (0)