Skip to content

Commit 2f3fb7b

Browse files
committed
implement skip paths for the exposed endpoints
1 parent dd1287d commit 2f3fb7b

File tree

9 files changed

+79
-64
lines changed

9 files changed

+79
-64
lines changed

config/config.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ type Config struct {
99
Layers *LayersOpts `json:"layers"`
1010
Exporters map[string]Exporter `json:"exporters"`
1111
Instance *Instance `json:"instance"`
12+
SkipPaths []string `json:"skip_paths"`
1213
Extra map[string]interface{} `json:"extra"`
1314
}
1415

@@ -47,10 +48,9 @@ type LayersOpts struct {
4748
// We can select if we want to disable the metrics,
4849
// the traces, and / or the trace propagation.
4950
type RouterOpts struct {
50-
DisableMetrics bool `json:"disable_metrics"`
51-
DisableTraces bool `json:"disable_traces"`
52-
DisablePropagation bool `json:"disable_propagation"`
53-
SkipPaths []string `json:"skip_paths"`
51+
DisableMetrics bool `json:"disable_metrics"`
52+
DisableTraces bool `json:"disable_traces"`
53+
DisablePropagation bool `json:"disable_propagation"`
5454
}
5555

5656
// PipeOpts has the options for the KrakenD pipe stage

config/lura.go

+14
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ func FromLura(srvCfg config.ServiceConfig) (*Config, error) {
3535
return nil, err
3636
}
3737

38+
// TODO: we might want to move these defaults to the config.go
39+
// file, as is not specific to reading the config from the Lura
40+
// config.
3841
if cfg.Layers == nil {
3942
cfg.Layers = &LayersOpts{}
4043
}
@@ -76,6 +79,17 @@ func FromLura(srvCfg config.ServiceConfig) (*Config, error) {
7679
}
7780
}
7881

82+
if len(cfg.SkipPaths) == 0 {
83+
// if there are no defined skip paths, we use the default ones:
84+
// to avoid using defaultSkipPaths, provide a list with an empty string
85+
cfg.SkipPaths = []string{
86+
"/healthz",
87+
"/_ah/health",
88+
"/__debug",
89+
"/__echo",
90+
}
91+
}
92+
7993
if cfg.ServiceName == "" {
8094
if srvCfg.Name != "" {
8195
cfg.ServiceName = srvCfg.Name

example/make_requests.sh

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#!/bin/bash
22

33
# for i in {1..10}
4-
for i in {1..2}
4+
for i in {1..1}
55
do
6-
# curl localhost:54444/fake/fsf
7-
# curl localhost:54444/combination/2
6+
curl localhost:54444/fake/fsf
7+
curl localhost:54444/combination/2
88
curl localhost:54444/combination/1
99
done
1010

example/server/main.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -91,20 +91,23 @@ func main() {
9191

9292
bf := func(backendConfig *config.Backend) proxy.Proxy {
9393
reqExec := lura.HTTPRequestExecutorFromConfig(client.NewHTTPClient,
94-
backendConfig, obsConfig.Layers.Backend)
94+
backendConfig, obsConfig.Layers.Backend, obsConfig.SkipPaths)
9595
return proxy.NewHTTPProxyWithHTTPExecutor(backendConfig, reqExec, backendConfig.Decoder)
9696
}
97+
bf = lura.BackendFactory(bf, state.GlobalState, obsConfig.Layers.Backend, obsConfig.SkipPaths)
9798

98-
defaultPF := proxy.NewDefaultFactory(lura.BackendFactory(bf, state.GlobalState, obsConfig.Layers.Backend), logger)
99-
pf := lura.ProxyFactory(defaultPF, state.GlobalState, obsConfig.Layers.Pipe)
99+
defaultPF := proxy.NewDefaultFactory(bf, logger)
100+
pf := lura.ProxyFactory(defaultPF, state.GlobalState, obsConfig.Layers.Pipe, obsConfig.SkipPaths)
100101

102+
handlerF := otelgin.New(krakendgin.EndpointHandler, state.GlobalState,
103+
obsConfig.Layers.Router, obsConfig.SkipPaths)
101104
// setup the krakend router
102105
routerFactory := krakendgin.NewFactory(krakendgin.Config{
103106
Engine: gin.Default(),
104107
ProxyFactory: pf,
105108
Middlewares: []gin.HandlerFunc{},
106109
Logger: logger,
107-
HandlerFactory: otelgin.New(krakendgin.EndpointHandler, state.GlobalState, obsConfig.Layers.Router),
110+
HandlerFactory: handlerF,
108111
RunServer: server.RunServer,
109112
})
110113

go.mod

+9-13
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ go 1.20
44

55
require (
66
github.com/gin-gonic/gin v1.9.1
7-
github.com/luraproject/lura/v2 v2.4.0
7+
github.com/luraproject/lura/v2 v2.4.3-0.20240111145738-b6784e5701d8
8+
github.com/prometheus/client_golang v1.17.0
89
go.opentelemetry.io/otel v1.21.0
9-
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0
10+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0
11+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0
12+
go.opentelemetry.io/otel/exporters/prometheus v0.44.0
1013
go.opentelemetry.io/otel/metric v1.21.0
14+
go.opentelemetry.io/otel/sdk v1.21.0
1115
go.opentelemetry.io/otel/sdk/metric v1.21.0
1216
go.opentelemetry.io/otel/trace v1.21.0
13-
google.golang.org/grpc v1.59.0
1417
)
1518

1619
require (
@@ -31,36 +34,29 @@ require (
3134
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
3235
github.com/json-iterator/go v1.1.12 // indirect
3336
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
34-
github.com/kr/pretty v0.3.1 // indirect
3537
github.com/krakendio/flatmap v1.1.1 // indirect
3638
github.com/leodido/go-urn v1.2.4 // indirect
3739
github.com/mattn/go-isatty v0.0.19 // indirect
3840
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
3941
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
4042
github.com/modern-go/reflect2 v1.0.2 // indirect
4143
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
42-
github.com/prometheus/client_golang v1.17.0 // indirect
4344
github.com/prometheus/client_model v0.5.0 // indirect
4445
github.com/prometheus/common v0.44.0 // indirect
4546
github.com/prometheus/procfs v0.11.1 // indirect
46-
github.com/rogpeppe/go-internal v1.10.0 // indirect
4747
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
4848
github.com/ugorji/go/codec v1.2.11 // indirect
4949
github.com/valyala/fastrand v1.1.0 // indirect
5050
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect
51-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect
52-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 // indirect
53-
go.opentelemetry.io/otel/exporters/prometheus v0.44.0 // indirect
54-
go.opentelemetry.io/otel/sdk v1.21.0 // indirect
5551
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
5652
golang.org/x/arch v0.3.0 // indirect
57-
golang.org/x/crypto v0.14.0 // indirect
53+
golang.org/x/crypto v0.17.0 // indirect
5854
golang.org/x/net v0.17.0 // indirect
5955
golang.org/x/sys v0.15.0 // indirect
60-
golang.org/x/text v0.13.0 // indirect
56+
golang.org/x/text v0.14.0 // indirect
6157
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
6258
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
59+
google.golang.org/grpc v1.59.0 // indirect
6360
google.golang.org/protobuf v1.31.0 // indirect
64-
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
6561
gopkg.in/yaml.v3 v3.0.1 // indirect
6662
)

lura/backend.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,17 @@ var defaultOpts = otelconfig.BackendOpts{
3434
// HTTPRequestExecutorFromConfig creates an HTTPRequestExecutor to be used
3535
// for the backend requests.
3636
func HTTPRequestExecutorFromConfig(clientFactory transport.HTTPClientFactory,
37-
cfg *config.Backend, opts *otelconfig.BackendOpts,
37+
cfg *config.Backend, opts *otelconfig.BackendOpts, skipPaths []string,
3838
) transport.HTTPRequestExecutor {
39+
40+
for _, sp := range skipPaths {
41+
if cfg.ParentEndpoint == sp {
42+
// TODO: check if there might be some othe executor that is
43+
// not the default one ?
44+
return transport.DefaultHTTPRequestExecutor(clientFactory)
45+
}
46+
}
47+
3948
if !opts.Enabled() {
4049
// no configuration for the backend, then .. no metrics nor tracing:
4150
return transport.DefaultHTTPRequestExecutor(clientFactory)

lura/proxy.go

+17-3
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@ func Middleware(name string, stage string, gsf state.GetterFn, metricsEnabled bo
121121

122122
// ProxyFactory returns a pipe stage factory that wraps the provided proxy factory with the
123123
// instrumentation [Middleware] based on the configuration options.
124-
func ProxyFactory(pf proxy.Factory, gsfn state.GetterFn, opts *kotelconfig.PipeOpts) proxy.FactoryFunc {
124+
func ProxyFactory(pf proxy.Factory, gsfn state.GetterFn, opts *kotelconfig.PipeOpts,
125+
skipPaths []string) proxy.FactoryFunc {
126+
125127
if opts == nil {
126128
return pf.New
127129
}
@@ -141,8 +143,13 @@ func ProxyFactory(pf proxy.Factory, gsfn state.GetterFn, opts *kotelconfig.PipeO
141143
if err != nil {
142144
return next, err
143145
}
146+
for _, sp := range skipPaths {
147+
if cfg.Endpoint == sp {
148+
return next, nil
149+
}
150+
}
144151

145-
// TODO: check the followint warning:
152+
// TODO: check the following warning:
146153
// WARNING: this changes how it was working before:
147154
// in original opencensus, we prefixed the endpoint with a `pipe` prefix
148155
// return Middleware("pipe-" + cfg.Endpoint)(next), nil
@@ -153,7 +160,9 @@ func ProxyFactory(pf proxy.Factory, gsfn state.GetterFn, opts *kotelconfig.PipeO
153160

154161
// BackendFactory returns a backend factory that wraps the provided backend factory with the
155162
// instrumentation [Middleware] based on the configuration options.
156-
func BackendFactory(bf proxy.BackendFactory, gsfn state.GetterFn, opts *kotelconfig.BackendOpts) proxy.BackendFactory {
163+
func BackendFactory(bf proxy.BackendFactory, gsfn state.GetterFn, opts *kotelconfig.BackendOpts,
164+
skipPaths []string) proxy.BackendFactory {
165+
157166
if opts == nil || (opts.Metrics.DisableStage && opts.Traces.DisableStage) {
158167
return bf
159168
}
@@ -162,6 +171,11 @@ func BackendFactory(bf proxy.BackendFactory, gsfn state.GetterFn, opts *kotelcon
162171

163172
return func(cfg *config.Backend) proxy.Proxy {
164173
next := bf(cfg)
174+
for _, sp := range skipPaths {
175+
if cfg.ParentEndpoint == sp {
176+
return next
177+
}
178+
}
165179
urlPattern := kotelconfig.NormalizeURLPattern(cfg.URLPattern)
166180
return Middleware(urlPattern, "backend", gsfn, metricsEnabled, tracesEnabled)(next)
167181
}

router/gin/endpoint.go

+15-34
Original file line numberDiff line numberDiff line change
@@ -17,57 +17,38 @@ import (
1717
"github.com/krakend/krakend-otel/state"
1818
)
1919

20-
var defaultSkipPaths = []string{
21-
"/healthz",
22-
"/_ah/health",
23-
"/__debug",
24-
"/__echo",
25-
}
26-
27-
// defaultRouterOpts return the default options when no options
28-
// are provided
29-
func defaultRouterOpts() *kconfig.RouterOpts {
30-
return &kconfig.RouterOpts{
31-
DisableMetrics: false,
32-
DisableTraces: false,
33-
DisablePropagation: false,
34-
}
35-
}
36-
3720
// New wraps a handler factory adding some simple instrumentation to the generated handlers
38-
func New(hf krakendgin.HandlerFactory, gsfn state.GetterFn, opts *kconfig.RouterOpts) krakendgin.HandlerFactory {
39-
if opts == nil {
40-
opts = defaultRouterOpts()
41-
}
21+
func New(hf krakendgin.HandlerFactory, gsfn state.GetterFn,
22+
opts *kconfig.RouterOpts, skipPaths []string) krakendgin.HandlerFactory {
23+
4224
if gsfn == nil {
4325
gsfn = state.GlobalState
4426
}
4527
return func(cfg *config.EndpointConfig, p proxy.Proxy) gin.HandlerFunc {
46-
return HandlerFunc(cfg, opts, gsfn, hf(cfg, p))
28+
return HandlerFunc(cfg, opts, gsfn, skipPaths, hf(cfg, p))
4729
}
4830
}
4931

5032
// HandlerFunc creates and instrumented gin.Handler wrapper with traces and / or metrics enabled
5133
// according to the [config.RouterOpts].
52-
func HandlerFunc(cfg *config.EndpointConfig, opts *kconfig.RouterOpts, gsfn state.GetterFn, next gin.HandlerFunc) gin.HandlerFunc {
53-
s := gsfn()
34+
func HandlerFunc(cfg *config.EndpointConfig, opts *kconfig.RouterOpts, gsfn state.GetterFn,
35+
skipPaths []string, next gin.HandlerFunc) gin.HandlerFunc {
5436

55-
if opts == nil || (opts.DisableMetrics && opts.DisableTraces) {
56-
if opts != nil && opts.DisablePropagation {
37+
// skip paths will not try to read the propagation header, because nothing
38+
// in the downstream pipeline will be instruemented. The header can be passed
39+
// using the regular `headers` feature.
40+
for _, sp := range skipPaths {
41+
if cfg.Endpoint == sp {
5742
return next
5843
}
59-
return PropagationMiddleware(next, s.Propagator())
6044
}
6145

62-
if len(opts.SkipPaths) == 0 {
63-
// if there are no defined skip paths, we use the default ones:
64-
// to avoid using defaultSkipPaths, provide a list with an empty string
65-
opts.SkipPaths = defaultSkipPaths
66-
}
67-
for _, sp := range opts.SkipPaths {
68-
if cfg.Endpoint == sp {
46+
s := gsfn()
47+
if opts == nil || (opts.DisableMetrics && opts.DisableTraces) {
48+
if opts != nil && opts.DisablePropagation {
6949
return next
7050
}
51+
return PropagationMiddleware(next, s.Propagator())
7152
}
7253

7354
// TODO: check that the endpoint path parameters are all standarized;

router/gin/propagation.go

-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package gin
22

33
import (
4-
"fmt"
5-
64
"github.com/gin-gonic/gin"
75
"go.opentelemetry.io/otel/propagation"
86
"go.opentelemetry.io/otel/trace"

0 commit comments

Comments
 (0)