Skip to content

Commit a46cd29

Browse files
authored
Merge pull request #11573 from owncloud/otelhttp_for_tracing
Otelhttp for tracing
2 parents c55cc70 + 8b8c7f0 commit a46cd29

File tree

45 files changed

+163
-2085
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+163
-2085
lines changed

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ require (
7171
github.com/pkg/xattr v0.4.12
7272
github.com/prometheus/client_golang v1.22.0
7373
github.com/r3labs/sse/v2 v2.10.0
74-
github.com/riandyrn/otelchi v0.12.1
7574
github.com/rogpeppe/go-internal v1.14.1
7675
github.com/rs/cors v1.11.1
7776
github.com/rs/zerolog v1.34.0

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -775,8 +775,6 @@ github.com/r3labs/sse/v2 v2.10.0 h1:hFEkLLFY4LDifoHdiCN/LlGBAdVJYsANaLqNYa1l/v0=
775775
github.com/r3labs/sse/v2 v2.10.0/go.mod h1:Igau6Whc+F17QUgML1fYe1VPZzTV6EMCnYktEmkNJ7I=
776776
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg=
777777
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
778-
github.com/riandyrn/otelchi v0.12.1 h1:FdRKK3/RgZ/T+d+qTH5Uw3MFx0KwRF38SkdfTMMq/m8=
779-
github.com/riandyrn/otelchi v0.12.1/go.mod h1:weZZeUJURvtCcbWsdb7Y6F8KFZGedJlSrgUjq9VirV8=
780778
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
781779
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
782780
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=

ocis-pkg/middleware/tracing.go

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,78 @@ package middleware
33
import (
44
"net/http"
55

6+
"github.com/owncloud/ocis/v2/ocis-pkg/tracing"
7+
"go-micro.dev/v4/metadata"
8+
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
69
"go.opentelemetry.io/otel/propagation"
10+
"go.opentelemetry.io/otel/trace"
711
)
812

9-
var propagator = propagation.NewCompositeTextMapPropagator(
10-
propagation.Baggage{},
11-
propagation.TraceContext{},
12-
)
13+
// GetOtelhttpMiddleware gets a new tracing middleware based on otelhttp
14+
// to trace the requests.
15+
// This middleware will use the otelhttp middleware and then store the
16+
// incoming data into the go-micro's metadata so it can be propagated through
17+
// go-micro.
18+
func GetOtelhttpMiddleware(service string, tp trace.TracerProvider) func(http.Handler) http.Handler {
19+
otelMid := otelhttp.NewMiddleware(
20+
service,
21+
otelhttp.WithTracerProvider(tp),
22+
otelhttp.WithPropagators(tracing.GetPropagator()),
23+
otelhttp.WithSpanOptions(trace.WithSpanKind(trace.SpanKindServer)),
24+
otelhttp.WithSpanNameFormatter(func(name string, r *http.Request) string {
25+
return r.Method + " " + r.URL.Path
26+
}),
27+
)
28+
29+
httpToMicroMid := otelhttpToGoMicroGrpc()
30+
31+
return func(next http.Handler) http.Handler {
32+
return otelMid(httpToMicroMid(next))
33+
}
34+
}
35+
36+
func otelhttpToGoMicroGrpc() func(http.Handler) http.Handler {
37+
return func(next http.Handler) http.Handler {
38+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
39+
ctx := r.Context()
40+
propagator := tracing.GetPropagator()
41+
42+
// based on go-micro plugin for opentelemetry
43+
// inject telemetry data into go-micro's metadata
44+
// in order to propagate the info to go-micro's calls
45+
md := make(metadata.Metadata)
46+
carrier := make(propagation.MapCarrier)
47+
propagator.Inject(ctx, carrier)
48+
for k, v := range carrier {
49+
md.Set(k, v)
50+
}
51+
mdCtx := metadata.NewContext(ctx, md)
52+
r = r.WithContext(mdCtx)
53+
54+
next.ServeHTTP(w, r)
55+
})
56+
}
57+
}
58+
59+
// GetOtelhttpClient will get a new HTTP client that will use telemetry and
60+
// automatically set the telemetry headers. It will wrap the default transport
61+
// in order to use telemetry.
62+
func GetOtelhttpClient(tp trace.TracerProvider) *http.Client {
63+
return &http.Client{
64+
Transport: GetOtelhttpClientTransport(http.DefaultTransport, tp),
65+
}
66+
}
1367

14-
// TraceContext unpacks the request context looking for an existing trace id.
15-
func TraceContext(next http.Handler) http.Handler {
16-
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
17-
ctx := propagator.Extract(r.Context(), propagation.HeaderCarrier(r.Header))
18-
next.ServeHTTP(w, r.WithContext(ctx))
19-
})
68+
// GetOtelhttpClientTransport will get a new wrapped transport that will
69+
// include telemetry automatically. You can use the http.DefaultTransport
70+
// as base transport
71+
func GetOtelhttpClientTransport(baseTransport http.RoundTripper, tp trace.TracerProvider) http.RoundTripper {
72+
return otelhttp.NewTransport(
73+
baseTransport,
74+
otelhttp.WithTracerProvider(tp),
75+
otelhttp.WithPropagators(tracing.GetPropagator()),
76+
otelhttp.WithSpanNameFormatter(func(name string, r *http.Request) string {
77+
return r.Method + " " + r.URL.Path
78+
}),
79+
)
2080
}

ocis-pkg/tracing/tracing.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import (
88
"net/url"
99
"reflect"
1010
"strings"
11+
"sync"
1112
"time"
1213

1314
rtrace "github.com/owncloud/reva/v2/pkg/trace"
15+
"go.opentelemetry.io/otel"
1416
"go.opentelemetry.io/otel/attribute"
1517
"go.opentelemetry.io/otel/exporters/jaeger"
1618
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
@@ -60,6 +62,20 @@ func GetPropagator() propagation.TextMapPropagator {
6062
)
6163
}
6264

65+
// propagatorOnceFn is needed to ensure we set the global propagator only once
66+
var propagatorOnceFn sync.Once
67+
68+
// setGlobalPropagatorOnce set the global propagator only once. This is needed
69+
// because go-micro uses the global propagator to extract and inject data and
70+
// we want to use the same.
71+
// Note: in case of services running in different hosts, this needs to be run
72+
// in all of them.
73+
func setGlobalPropagatorOnce() {
74+
propagatorOnceFn.Do(func() {
75+
otel.SetTextMapPropagator(GetPropagator())
76+
})
77+
}
78+
6379
// GetTraceProvider returns a configured open-telemetry trace provider.
6480
func GetTraceProvider(endpoint, collector, serviceName, traceType string) (*sdktrace.TracerProvider, error) {
6581
switch t := traceType; t {
@@ -141,6 +157,7 @@ func GetTraceProvider(endpoint, collector, serviceName, traceType string) (*sdkt
141157
sdktrace.WithResource(resources),
142158
)
143159
rtrace.SetDefaultTracerProvider(tp)
160+
setGlobalPropagatorOnce()
144161
return tp, nil
145162
case "agent":
146163
fallthrough

services/activitylog/pkg/server/http/server.go

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ import (
1111
"github.com/owncloud/ocis/v2/ocis-pkg/cors"
1212
"github.com/owncloud/ocis/v2/ocis-pkg/middleware"
1313
"github.com/owncloud/ocis/v2/ocis-pkg/service/http"
14-
"github.com/owncloud/ocis/v2/ocis-pkg/tracing"
1514
"github.com/owncloud/ocis/v2/ocis-pkg/version"
1615
svc "github.com/owncloud/ocis/v2/services/activitylog/pkg/service"
17-
"github.com/riandyrn/otelchi"
1816
"go-micro.dev/v4"
1917
)
2018

@@ -44,6 +42,7 @@ func Server(opts ...Option) (http.Service, error) {
4442
}
4543

4644
middlewares := []func(stdhttp.Handler) stdhttp.Handler{
45+
middleware.GetOtelhttpMiddleware(options.Config.Service.Name, options.TraceProvider),
4746
chimiddleware.RequestID,
4847
middleware.Version(
4948
options.Config.Service.Name,
@@ -68,15 +67,6 @@ func Server(opts ...Option) (http.Service, error) {
6867
mux := chi.NewMux()
6968
mux.Use(middlewares...)
7069

71-
mux.Use(
72-
otelchi.Middleware(
73-
"actitivylog",
74-
otelchi.WithChiRoutes(mux),
75-
otelchi.WithTracerProvider(options.TraceProvider),
76-
otelchi.WithPropagators(tracing.GetPropagator()),
77-
),
78-
)
79-
8070
handle, err := svc.New(
8171
svc.Logger(options.Logger),
8272
svc.Stream(options.Stream),

services/auth-app/pkg/server/http/server.go

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ import (
1111
"github.com/owncloud/ocis/v2/ocis-pkg/cors"
1212
"github.com/owncloud/ocis/v2/ocis-pkg/middleware"
1313
"github.com/owncloud/ocis/v2/ocis-pkg/service/http"
14-
"github.com/owncloud/ocis/v2/ocis-pkg/tracing"
1514
"github.com/owncloud/ocis/v2/ocis-pkg/version"
1615
svc "github.com/owncloud/ocis/v2/services/auth-app/pkg/service"
17-
"github.com/riandyrn/otelchi"
1816
"go-micro.dev/v4"
1917
)
2018

@@ -44,6 +42,7 @@ func Server(opts ...Option) (http.Service, error) {
4442
}
4543

4644
middlewares := []func(stdhttp.Handler) stdhttp.Handler{
45+
middleware.GetOtelhttpMiddleware(options.Config.Service.Name, options.TracerProvider),
4746
chimiddleware.RequestID,
4847
middleware.Version(
4948
options.Config.Service.Name,
@@ -68,15 +67,6 @@ func Server(opts ...Option) (http.Service, error) {
6867
mux := chi.NewMux()
6968
mux.Use(middlewares...)
7069

71-
mux.Use(
72-
otelchi.Middleware(
73-
"auth-app",
74-
otelchi.WithChiRoutes(mux),
75-
otelchi.WithTracerProvider(options.TracerProvider),
76-
otelchi.WithPropagators(tracing.GetPropagator()),
77-
),
78-
)
79-
8070
handle, err := svc.NewAuthAppService(
8171
svc.Logger(options.Logger),
8272
svc.Mux(mux),

services/collaboration/pkg/server/http/server.go

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@ import (
1010
"github.com/owncloud/ocis/v2/ocis-pkg/log"
1111
"github.com/owncloud/ocis/v2/ocis-pkg/middleware"
1212
"github.com/owncloud/ocis/v2/ocis-pkg/service/http"
13-
"github.com/owncloud/ocis/v2/ocis-pkg/tracing"
1413
"github.com/owncloud/ocis/v2/ocis-pkg/version"
1514
colabmiddleware "github.com/owncloud/ocis/v2/services/collaboration/pkg/middleware"
16-
"github.com/riandyrn/otelchi"
1715
"go-micro.dev/v4"
1816
)
1917

@@ -39,6 +37,7 @@ func Server(opts ...Option) (http.Service, error) {
3937
}
4038

4139
middlewares := []func(stdhttp.Handler) stdhttp.Handler{
40+
middleware.GetOtelhttpMiddleware(options.Config.Service.Name+"."+options.Config.App.Name, options.TracerProvider),
4241
chimiddleware.RequestID,
4342
middleware.Version(
4443
options.Config.Service.Name+"."+options.Config.App.Name,
@@ -67,16 +66,6 @@ func Server(opts ...Option) (http.Service, error) {
6766
mux := chi.NewMux()
6867
mux.Use(middlewares...)
6968

70-
mux.Use(
71-
otelchi.Middleware(
72-
options.Config.Service.Name+"."+options.Config.App.Name,
73-
otelchi.WithChiRoutes(mux),
74-
otelchi.WithTracerProvider(options.TracerProvider),
75-
otelchi.WithPropagators(tracing.GetPropagator()),
76-
otelchi.WithRequestMethodInSpanName(true),
77-
),
78-
)
79-
8069
prepareRoutes(mux, options)
8170

8271
// in debug mode print out the actual routes

services/graph/pkg/server/http/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func Server(opts ...Option) (http.Service, error) {
6565
}
6666

6767
middlewares := []func(stdhttp.Handler) stdhttp.Handler{
68-
middleware.TraceContext,
68+
middleware.GetOtelhttpMiddleware(options.Config.Service.Name, options.TraceProvider),
6969
chimiddleware.RequestID,
7070
middleware.Version(
7171
options.Config.Service.Name,

services/idp/pkg/server/http/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ func Server(opts ...Option) (http.Service, error) {
5757
svc.Logger(options.Logger),
5858
svc.Config(options.Config),
5959
svc.Middleware(
60+
middleware.GetOtelhttpMiddleware(options.Config.Service.Name, options.TraceProvider),
6061
chimiddleware.RealIP,
6162
chimiddleware.RequestID,
62-
middleware.TraceContext,
6363
middleware.NoCache,
6464
middleware.Version(
6565
options.Config.Service.Name,

services/idp/pkg/service/v0/service.go

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,10 @@ import (
2020
"github.com/libregraph/lico/server"
2121
"github.com/owncloud/ocis/v2/ocis-pkg/ldap"
2222
"github.com/owncloud/ocis/v2/ocis-pkg/log"
23-
"github.com/owncloud/ocis/v2/ocis-pkg/tracing"
2423
"github.com/owncloud/ocis/v2/services/idp/pkg/assets"
2524
cs3BackendSupport "github.com/owncloud/ocis/v2/services/idp/pkg/backends/cs3/bootstrap"
2625
"github.com/owncloud/ocis/v2/services/idp/pkg/config"
2726
"github.com/owncloud/ocis/v2/services/idp/pkg/middleware"
28-
"github.com/riandyrn/otelchi"
2927
"go.opentelemetry.io/otel/trace"
3028
"gopkg.in/yaml.v2"
3129
"stash.kopano.io/kgol/rndm"
@@ -125,7 +123,7 @@ func NewService(opts ...Option) Service {
125123
routes := []server.WithRoutes{managers.Must("identity").(server.WithRoutes)}
126124
handlers := managers.Must("handler").(http.Handler)
127125

128-
svc := IDP{
126+
svc := &IDP{
129127
logger: options.Logger,
130128
config: options.Config,
131129
assets: assetVFS,
@@ -282,15 +280,6 @@ func (idp *IDP) initMux(ctx context.Context, r []server.WithRoutes, h http.Handl
282280
idp.tp,
283281
))
284282

285-
idp.mux.Use(
286-
otelchi.Middleware(
287-
"idp",
288-
otelchi.WithChiRoutes(idp.mux),
289-
otelchi.WithTracerProvider(idp.tp),
290-
otelchi.WithPropagators(tracing.GetPropagator()),
291-
),
292-
)
293-
294283
// handle / | index.html with a template that needs to have the BASE_PREFIX replaced
295284
idp.mux.Get("/signin/v1/identifier", idp.Index())
296285
idp.mux.Get("/signin/v1/identifier/", idp.Index())
@@ -305,12 +294,12 @@ func (idp *IDP) initMux(ctx context.Context, r []server.WithRoutes, h http.Handl
305294
}
306295

307296
// ServeHTTP implements the Service interface.
308-
func (idp IDP) ServeHTTP(w http.ResponseWriter, r *http.Request) {
297+
func (idp *IDP) ServeHTTP(w http.ResponseWriter, r *http.Request) {
309298
idp.mux.ServeHTTP(w, r)
310299
}
311300

312301
// Index renders the static html with templated variables.
313-
func (idp IDP) Index() http.HandlerFunc {
302+
func (idp *IDP) Index() http.HandlerFunc {
314303
f, err := idp.assets.Open("/identifier/index.html")
315304
if err != nil {
316305
idp.logger.Fatal().Err(err).Msg("Could not open index template")

0 commit comments

Comments
 (0)