diff --git a/cmd/revad/runtime/runtime.go b/cmd/revad/runtime/runtime.go index d37732eb9b..8ea8879e8b 100644 --- a/cmd/revad/runtime/runtime.go +++ b/cmd/revad/runtime/runtime.go @@ -34,7 +34,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/sharedconf" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" @@ -73,25 +73,17 @@ func RunWithOptions(mainConf map[string]interface{}, pidFile string, opts ...Opt } type coreConf struct { - MaxCPUs string `mapstructure:"max_cpus"` - TracingEnabled bool `mapstructure:"tracing_enabled"` - TracingEndpoint string `mapstructure:"tracing_endpoint"` - TracingCollector string `mapstructure:"tracing_collector"` - TracingServiceName string `mapstructure:"tracing_service_name"` - - // TracingService specifies the service. i.e OpenCensus, OpenTelemetry, OpenTracing... - TracingService string `mapstructure:"tracing_service"` + MaxCPUs string `mapstructure:"max_cpus"` } func run(mainConf map[string]interface{}, coreConf *coreConf, logger *zerolog.Logger, filename string) { host, _ := os.Hostname() logger.Info().Msgf("host info: %s", host) - if coreConf.TracingEnabled { - initTracing(coreConf) - } initCPUCount(coreConf, logger) + tracing.Init(mainConf["tracing"], tracing.WithLogger(logger.With().Str("pkg", "tracing").Logger())) + servers := initServers(mainConf, logger) watcher, err := initWatcher(logger, filename) if err != nil { @@ -148,10 +140,6 @@ func initServers(mainConf map[string]interface{}, log *zerolog.Logger) map[strin return servers } -func initTracing(conf *coreConf) { - rtrace.SetTraceProvider(conf.TracingCollector, conf.TracingEndpoint, conf.TracingServiceName) -} - func initCPUCount(conf *coreConf, log *zerolog.Logger) { ncpus, err := adjustCPU(conf.MaxCPUs) if err != nil { @@ -264,7 +252,8 @@ func getHTTPServer(conf interface{}, l *zerolog.Logger) (*rhttp.Server, error) { return s, nil } -// adjustCPU parses string cpu and sets GOMAXPROCS +// adjustCPU parses string cpu and sets GOMAXPROCS +// // according to its value. It accepts either // a number (e.g. 3) or a percent (e.g. 50%). // Default is to use all available cores. @@ -311,15 +300,6 @@ func parseCoreConfOrDie(v interface{}) *coreConf { os.Exit(1) } - // tracing defaults to enabled if not explicitly configured - if v == nil { - c.TracingEnabled = true - c.TracingEndpoint = "localhost:6831" - } else if _, ok := v.(map[string]interface{})["tracing_enabled"]; !ok { - c.TracingEnabled = true - c.TracingEndpoint = "localhost:6831" - } - return c } diff --git a/go.mod b/go.mod index 4939ba9cf9..67cea71363 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,7 @@ require ( github.com/rs/zerolog v1.27.0 github.com/sciencemesh/meshdirectory-web v1.0.4 github.com/sethvargo/go-password v0.2.0 - github.com/stretchr/testify v1.7.2 + github.com/stretchr/testify v1.8.0 github.com/studio-b12/gowebdav v0.0.0-20210917133250-a3a86976a1df github.com/thanhpk/randstr v1.0.4 github.com/tidwall/pretty v1.2.0 // indirect @@ -68,17 +68,19 @@ require ( go-micro.dev/v4 v4.3.1-0.20211108085239-0c2041e43908 go.opencensus.io v0.23.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.32.0 - go.opentelemetry.io/otel v1.7.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.33.0 + go.opentelemetry.io/contrib/propagators/jaeger v1.7.0 + go.opentelemetry.io/otel v1.8.0 go.opentelemetry.io/otel/exporters/jaeger v1.7.0 go.opentelemetry.io/otel/sdk v1.7.0 - go.opentelemetry.io/otel/trace v1.7.0 + go.opentelemetry.io/otel/trace v1.8.0 golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 golang.org/x/image v0.0.0-20220617043117-41969df76e82 // indirect golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 + golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 - golang.org/x/text v0.3.7 // indirect + golang.org/x/text v0.3.7 google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb google.golang.org/grpc v1.47.0 google.golang.org/protobuf v1.28.0 diff --git a/go.sum b/go.sum index 23b9512afe..0423d5e3d6 100644 --- a/go.sum +++ b/go.sum @@ -273,6 +273,8 @@ github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= @@ -946,8 +948,9 @@ github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As= github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -955,8 +958,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/studio-b12/gowebdav v0.0.0-20210917133250-a3a86976a1df h1:C+J/LwTqP8gRPt1MdSzBNZP0OYuDm5wsmDKgwpLjYzo= github.com/studio-b12/gowebdav v0.0.0-20210917133250-a3a86976a1df/go.mod h1:gCcfDlA1Y7GqOaeEKw5l9dOGx1VLdc/HuQSlQAaZ30s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -1025,14 +1029,22 @@ go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.32.0 h1:WenoaOMNP71oq3KkMZ/jnxI9xU/JSCLw8yZILSI2lfU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.32.0/go.mod h1:J0dBVrt7dPS/lKJyQoW0xzQiUr4r2Ik1VwPjAUWnofI= -go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.33.0 h1:Z0lVKLXU+jxGf3ANoh+UWx9Ai5bjpQVnZXI1zEzvqS0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.33.0/go.mod h1:U5rUt7Rw6zuORsWNfpMRy8XMNKLrmIlv/4HgLVW/d5M= +go.opentelemetry.io/contrib/propagators/jaeger v1.7.0 h1:x2mXKtONfOJFfNFSx4QXFx1fms6bKIPVvWvgdiaPdRI= +go.opentelemetry.io/contrib/propagators/jaeger v1.7.0/go.mod h1:kt2lNImfxV6dETRsDCENd6jU6G0mPRS+P0qlNuvtkTE= go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= +go.opentelemetry.io/otel v1.8.0 h1:zcvBFizPbpa1q7FehvFiHbQwGzmPILebO0tyqIR5Djg= +go.opentelemetry.io/otel v1.8.0/go.mod h1:2pkj+iMj0o03Y+cW6/m8Y4WkRdYN3AvCXCnzRMp9yvM= go.opentelemetry.io/otel/exporters/jaeger v1.7.0 h1:wXgjiRldljksZkZrldGVe6XrG9u3kYDyQmkZwmm5dI0= go.opentelemetry.io/otel/exporters/jaeger v1.7.0/go.mod h1:PwQAOqBgqbLQRKlj466DuD2qyMjbtcPpfPfj+AqbSBs= +go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs= +go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A= go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0= go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU= -go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o= go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= +go.opentelemetry.io/otel/trace v1.8.0 h1:cSy0DF9eGI5WIfNwZ1q2iUyGj00tGzP24dE1lOlHrfY= +go.opentelemetry.io/otel/trace v1.8.0/go.mod h1:0Bt3PXY8w+3pheS3hQUt+wow8b1ojPaTBoTCh2zIFI4= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1316,8 +1328,9 @@ golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201113234701-d7a72108b828/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/internal/grpc/interceptors/appctx/appctx.go b/internal/grpc/interceptors/appctx/appctx.go index 1bb8238c46..62e1d5ac0c 100644 --- a/internal/grpc/interceptors/appctx/appctx.go +++ b/internal/grpc/interceptors/appctx/appctx.go @@ -22,22 +22,20 @@ import ( "context" "github.com/cs3org/reva/pkg/appctx" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/rs/zerolog" - "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" ) +const tracerName = "appctx" + // NewUnary returns a new unary interceptor that creates the application context. func NewUnary(log zerolog.Logger) grpc.UnaryServerInterceptor { interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - span := trace.SpanFromContext(ctx) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "appctx UnaryServerInterceptor") defer span.End() - if !span.SpanContext().HasTraceID() { - ctx, span = rtrace.Provider.Tracer("grpc").Start(ctx, "grpc unary") - } - sub := log.With().Str("traceid", span.SpanContext().TraceID().String()).Logger() + sub := log.With().Str("TraceID", span.SpanContext().TraceID().String()).Logger() ctx = appctx.WithLogger(ctx, &sub) res, err := handler(ctx, req) return res, err @@ -50,24 +48,21 @@ func NewUnary(log zerolog.Logger) grpc.UnaryServerInterceptor { func NewStream(log zerolog.Logger) grpc.StreamServerInterceptor { interceptor := func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { ctx := ss.Context() - span := trace.SpanFromContext(ctx) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "appctx StreamServerInterceptor") defer span.End() - if !span.SpanContext().HasTraceID() { - ctx, span = rtrace.Provider.Tracer("grpc").Start(ctx, "grpc stream") - } - - sub := log.With().Str("traceid", span.SpanContext().TraceID().String()).Logger() + sub := log.With().Str("TraceID", span.SpanContext().TraceID().String()).Logger() ctx = appctx.WithLogger(ctx, &sub) wrapped := newWrappedServerStream(ctx, ss) - err := handler(srv, wrapped) - return err + return handler(srv, wrapped) } return interceptor } func newWrappedServerStream(ctx context.Context, ss grpc.ServerStream) *wrappedServerStream { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "appctx newWrappedServerStream") + defer span.End() return &wrappedServerStream{ServerStream: ss, newCtx: ctx} } diff --git a/internal/grpc/interceptors/auth/auth.go b/internal/grpc/interceptors/auth/auth.go index 876f91fbc6..77fdea7dd2 100644 --- a/internal/grpc/interceptors/auth/auth.go +++ b/internal/grpc/interceptors/auth/auth.go @@ -33,9 +33,11 @@ import ( "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/token" tokenmgr "github.com/cs3org/reva/pkg/token/manager/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" + semconv "go.opentelemetry.io/otel/semconv/v1.10.0" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -44,6 +46,8 @@ import ( var userGroupsCache gcache.Cache var scopeExpansionCache gcache.Cache +const tracerName = "auth" + type config struct { // TODO(labkode): access a map is more performant as uri as fixed in length // for SkipMethods. @@ -89,6 +93,9 @@ func NewUnary(m map[string]interface{}, unprotected []string) (grpc.UnaryServerI } interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "auth UnaryServerInterceptor") + defer span.End() + log := appctx.GetLogger(ctx) if utils.Skip(info.FullMethod, unprotected) { @@ -99,6 +106,7 @@ func NewUnary(m map[string]interface{}, unprotected []string) (grpc.UnaryServerI if ok { u, err := dismantleToken(ctx, tkn, req, tokenManager, conf.GatewayAddr, true) if err == nil { + span.SetAttributes(semconv.EnduserIDKey.String(u.Username)) ctx = ctxpkg.ContextSetUser(ctx, u) } } @@ -119,6 +127,7 @@ func NewUnary(m map[string]interface{}, unprotected []string) (grpc.UnaryServerI return nil, status.Errorf(codes.PermissionDenied, "auth: core access token is invalid") } + span.SetAttributes(semconv.EnduserIDKey.String(u.Username)) ctx = ctxpkg.ContextSetUser(ctx, u) return handler(ctx, req) } @@ -152,6 +161,9 @@ func NewStream(m map[string]interface{}, unprotected []string) (grpc.StreamServe interceptor := func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { ctx := ss.Context() + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "auth StreamServerInterceptor") + defer span.End() + log := appctx.GetLogger(ctx) if utils.Skip(info.FullMethod, unprotected) { @@ -163,6 +175,7 @@ func NewStream(m map[string]interface{}, unprotected []string) (grpc.StreamServe if ok { u, err := dismantleToken(ctx, tkn, ss, tokenManager, conf.GatewayAddr, true) if err == nil { + span.SetAttributes(semconv.EnduserIDKey.String(u.Username)) ctx = ctxpkg.ContextSetUser(ctx, u) ss = newWrappedServerStream(ctx, ss) } @@ -185,6 +198,7 @@ func NewStream(m map[string]interface{}, unprotected []string) (grpc.StreamServe return status.Errorf(codes.PermissionDenied, "auth: core access token is invalid") } + span.SetAttributes(semconv.EnduserIDKey.String(u.Username)) // store user and core access token in context. ctx = ctxpkg.ContextSetUser(ctx, u) wrapped := newWrappedServerStream(ctx, ss) @@ -194,6 +208,8 @@ func NewStream(m map[string]interface{}, unprotected []string) (grpc.StreamServe } func newWrappedServerStream(ctx context.Context, ss grpc.ServerStream) *wrappedServerStream { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "auth newWrappedServerStream") + defer span.End() return &wrappedServerStream{ServerStream: ss, newCtx: ctx} } @@ -207,17 +223,22 @@ func (ss *wrappedServerStream) Context() context.Context { } func dismantleToken(ctx context.Context, tkn string, req interface{}, mgr token.Manager, gatewayAddr string, unprotected bool) (*userpb.User, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "auth dismantleToken") + defer span.End() + u, tokenScope, err := mgr.DismantleToken(ctx, tkn) if err != nil { return nil, err } + span.SetAttributes(semconv.EnduserIDKey.String(u.Username)) + if unprotected { return u, nil } if sharedconf.SkipUserGroupsInToken() { - client, err := pool.GetGatewayServiceClient(pool.Endpoint(gatewayAddr)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(gatewayAddr)) if err != nil { return nil, err } @@ -245,6 +266,11 @@ func dismantleToken(ctx context.Context, tkn string, req interface{}, mgr token. } func getUserGroups(ctx context.Context, u *userpb.User, client gatewayv1beta1.GatewayAPIClient) ([]string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "auth getUserGroups") + defer span.End() + + span.SetAttributes(semconv.EnduserIDKey.String(u.Username)) + if groupsIf, err := userGroupsCache.Get(u.Id.OpaqueId); err == nil { log := appctx.GetLogger(ctx) log.Info().Msgf("user groups found in cache %s", u.Id.OpaqueId) diff --git a/internal/grpc/interceptors/auth/scope.go b/internal/grpc/interceptors/auth/scope.go index 167648e4d4..d731311626 100644 --- a/internal/grpc/interceptors/auth/scope.go +++ b/internal/grpc/interceptors/auth/scope.go @@ -40,6 +40,7 @@ import ( statuspkg "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/token" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" "google.golang.org/grpc/metadata" @@ -51,8 +52,11 @@ const ( ) func expandAndVerifyScope(ctx context.Context, req interface{}, tokenScope map[string]*authpb.Scope, user *userpb.User, gatewayAddr string, mgr token.Manager) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "auth expandAndVerifyScope") + defer span.End() + log := appctx.GetLogger(ctx) - client, err := pool.GetGatewayServiceClient(pool.Endpoint(gatewayAddr)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(gatewayAddr)) if err != nil { return err } @@ -124,6 +128,9 @@ func expandAndVerifyScope(ctx context.Context, req interface{}, tokenScope map[s } func resolveLightweightScope(ctx context.Context, ref *provider.Reference, scope *authpb.Scope, user *userpb.User, client gateway.GatewayAPIClient, mgr token.Manager) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "auth resolveLightweightScope") + defer span.End() + // Check if this ref is cached key := "lw:" + user.Id.OpaqueId + scopeDelimiter + getRefKey(ref) if _, err := scopeExpansionCache.Get(key); err == nil { @@ -152,6 +159,9 @@ func resolveLightweightScope(ctx context.Context, ref *provider.Reference, scope } func resolvePublicShare(ctx context.Context, ref *provider.Reference, scope *authpb.Scope, client gateway.GatewayAPIClient, mgr token.Manager) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "auth resolvePublicShare") + defer span.End() + var share link.PublicShare err := utils.UnmarshalJSONToProtoV1(scope.Resource.Value, &share) if err != nil { @@ -162,6 +172,9 @@ func resolvePublicShare(ctx context.Context, ref *provider.Reference, scope *aut } func resolveUserShare(ctx context.Context, ref *provider.Reference, scope *authpb.Scope, client gateway.GatewayAPIClient, mgr token.Manager) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "auth resolveUserShare") + defer span.End() + var share collaboration.Share err := utils.UnmarshalJSONToProtoV1(scope.Resource.Value, &share) if err != nil { @@ -172,6 +185,9 @@ func resolveUserShare(ctx context.Context, ref *provider.Reference, scope *authp } func checkCacheForNestedResource(ctx context.Context, ref *provider.Reference, resource *provider.ResourceId, client gateway.GatewayAPIClient, mgr token.Manager) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "auth checkCacheForNestedResource") + defer span.End() + // Check if this ref is cached key := resourceid.OwnCloudResourceIDWrap(resource) + scopeDelimiter + getRefKey(ref) if _, err := scopeExpansionCache.Get(key); err == nil { @@ -194,6 +210,9 @@ func isRelativePathOrEmpty(path string) bool { } func checkIfNestedResource(ctx context.Context, ref *provider.Reference, parent *provider.ResourceId, client gateway.GatewayAPIClient, mgr token.Manager) (bool, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "auth checkIfNestedResource") + defer span.End() + // Since the resource ID is obtained from the scope, the current token // has access to it. statResponse, err := client.Stat(ctx, &provider.StatRequest{Ref: &provider.Reference{ResourceId: parent}}) diff --git a/internal/grpc/interceptors/eventsmiddleware/events.go b/internal/grpc/interceptors/eventsmiddleware/events.go index d7603e74c5..090fb56064 100644 --- a/internal/grpc/interceptors/eventsmiddleware/events.go +++ b/internal/grpc/interceptors/eventsmiddleware/events.go @@ -30,8 +30,11 @@ import ( "github.com/cs3org/reva/pkg/events" "github.com/cs3org/reva/pkg/events/server" "github.com/cs3org/reva/pkg/rgrpc" + "github.com/cs3org/reva/pkg/tracing" ) +const tracerName = "eventsmiddleware" + const ( defaultPriority = 200 ) @@ -42,6 +45,7 @@ func init() { // NewUnary returns a new unary interceptor that emits events when needed // no lint because of the switch statement that should be extendable +// //nolint:gocritic func NewUnary(m map[string]interface{}) (grpc.UnaryServerInterceptor, int, error) { publisher, err := publisherFromConfig(m) @@ -50,6 +54,9 @@ func NewUnary(m map[string]interface{}) (grpc.UnaryServerInterceptor, int, error } interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "eventsmiddleware UnaryServerInterceptor") + defer span.End() + res, err := handler(ctx, req) if err != nil { return res, err @@ -76,6 +83,9 @@ func NewUnary(m map[string]interface{}) (grpc.UnaryServerInterceptor, int, error // that creates the application context. func NewStream() grpc.StreamServerInterceptor { interceptor := func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + ctx := ss.Context() + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "eventsmiddleware StreamServerInterceptor") + defer span.End() // TODO: Use ss.RecvMsg() and ss.SendMsg() to send events from a stream return handler(srv, ss) } diff --git a/internal/grpc/interceptors/log/log.go b/internal/grpc/interceptors/log/log.go index 62ec397cf1..a50622b193 100644 --- a/internal/grpc/interceptors/log/log.go +++ b/internal/grpc/interceptors/log/log.go @@ -24,6 +24,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/tracing" "github.com/rs/zerolog" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -31,10 +32,14 @@ import ( "google.golang.org/grpc/status" ) +const tracerName = "log" + // NewUnary returns a new unary interceptor // that logs grpc calls. func NewUnary() grpc.UnaryServerInterceptor { interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "log UnaryServerInterceptor") + defer span.End() start := time.Now() res, err := handler(ctx, req) code := status.Code(err) @@ -72,6 +77,9 @@ func NewUnary() grpc.UnaryServerInterceptor { func NewStream() grpc.StreamServerInterceptor { interceptor := func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { ctx := ss.Context() + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "log StreamServerInterceptor") + defer span.End() + start := time.Now() err := handler(srv, ss) end := time.Now() diff --git a/internal/grpc/interceptors/readonly/readonly.go b/internal/grpc/interceptors/readonly/readonly.go index d1d8801c2d..f67814ea23 100644 --- a/internal/grpc/interceptors/readonly/readonly.go +++ b/internal/grpc/interceptors/readonly/readonly.go @@ -26,11 +26,14 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rgrpc" rstatus "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) +const tracerName = "readonly" + const ( defaultPriority = 200 ) @@ -43,6 +46,9 @@ func init() { // that checks grpc calls and blocks write requests. func NewUnary(map[string]interface{}) (grpc.UnaryServerInterceptor, int, error) { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "readonly UnaryServerInterceptor") + defer span.End() + log := appctx.GetLogger(ctx) switch req.(type) { diff --git a/internal/grpc/interceptors/recovery/recovery.go b/internal/grpc/interceptors/recovery/recovery.go index 7ebe0983ae..cc1289ce5e 100644 --- a/internal/grpc/interceptors/recovery/recovery.go +++ b/internal/grpc/interceptors/recovery/recovery.go @@ -24,27 +24,44 @@ import ( "runtime/debug" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/tracing" grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) +const tracerName = "recovery" + // NewUnary returns a server interceptor that adds telemetry to // grpc calls. func NewUnary() grpc.UnaryServerInterceptor { - interceptor := grpc_recovery.UnaryServerInterceptor(grpc_recovery.WithRecoveryHandlerContext(recoveryFunc)) - return interceptor + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "recovery UnaryServerInterceptor") + defer span.End() + + interceptor := grpc_recovery.UnaryServerInterceptor(grpc_recovery.WithRecoveryHandlerContext(recoveryFunc)) + return interceptor(ctx, req, info, handler) + } } // NewStream returns a streaming server interceptor that adds telemetry to // streaming grpc calls. func NewStream() grpc.StreamServerInterceptor { - interceptor := grpc_recovery.StreamServerInterceptor(grpc_recovery.WithRecoveryHandlerContext(recoveryFunc)) - return interceptor + return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + ctx := ss.Context() + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "recovery StreamServerInterceptor") + defer span.End() + + interceptor := grpc_recovery.StreamServerInterceptor(grpc_recovery.WithRecoveryHandlerContext(recoveryFunc)) + return interceptor(srv, ss, info, handler) + } } func recoveryFunc(ctx context.Context, p interface{}) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "recovery recoveryFunc") + defer span.End() + debug.PrintStack() log := appctx.GetLogger(ctx) log.Error().Msgf("%+v; stack: %s", p, debug.Stack()) diff --git a/internal/grpc/interceptors/token/token.go b/internal/grpc/interceptors/token/token.go index e306f87062..7ea89b197f 100644 --- a/internal/grpc/interceptors/token/token.go +++ b/internal/grpc/interceptors/token/token.go @@ -22,14 +22,20 @@ import ( "context" ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/tracing" "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) +const tracerName = "token" + // NewUnary returns a new unary interceptor that adds // the token to the context. func NewUnary() grpc.UnaryServerInterceptor { interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "token UnaryServerInterceptor") + defer span.End() + md, ok := metadata.FromIncomingContext(ctx) if ok && md != nil { if val, ok := md[ctxpkg.TokenHeader]; ok { @@ -51,6 +57,8 @@ func NewUnary() grpc.UnaryServerInterceptor { func NewStream() grpc.StreamServerInterceptor { interceptor := func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { ctx := ss.Context() + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "token StreamServerInterceptor") + defer span.End() md, ok := metadata.FromIncomingContext(ss.Context()) if ok && md != nil { @@ -70,6 +78,9 @@ func NewStream() grpc.StreamServerInterceptor { } func newWrappedServerStream(ctx context.Context, ss grpc.ServerStream) *wrappedServerStream { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "token newWrappedServerStream") + defer span.End() + return &wrappedServerStream{ServerStream: ss, newCtx: ctx} } diff --git a/internal/grpc/interceptors/useragent/useragent.go b/internal/grpc/interceptors/useragent/useragent.go index d39642e59e..d1e1d2db3c 100644 --- a/internal/grpc/interceptors/useragent/useragent.go +++ b/internal/grpc/interceptors/useragent/useragent.go @@ -22,14 +22,20 @@ import ( "context" ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/tracing" "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) +const tracerName = "useragent" + // NewUnary returns a new unary interceptor that adds // the useragent to the context. func NewUnary() grpc.UnaryServerInterceptor { interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "useragent UnaryServerInterceptor") + defer span.End() + if md, ok := metadata.FromIncomingContext(ctx); ok { if lst, ok := md[ctxpkg.UserAgentHeader]; ok && len(lst) != 0 { ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.UserAgentHeader, lst[0]) @@ -45,6 +51,9 @@ func NewUnary() grpc.UnaryServerInterceptor { func NewStream() grpc.StreamServerInterceptor { interceptor := func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { ctx := ss.Context() + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "useragent StreamServerInterceptor") + defer span.End() + if md, ok := metadata.FromIncomingContext(ctx); ok { if lst, ok := md[ctxpkg.UserAgentHeader]; ok && len(lst) != 0 { ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.UserAgentHeader, lst[0]) @@ -57,6 +66,8 @@ func NewStream() grpc.StreamServerInterceptor { } func newWrappedServerStream(ctx context.Context, ss grpc.ServerStream) *wrappedServerStream { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "useragent newWrappedServerStream") + defer span.End() return &wrappedServerStream{ServerStream: ss, newCtx: ctx} } diff --git a/internal/grpc/services/applicationauth/applicationauth.go b/internal/grpc/services/applicationauth/applicationauth.go index cccf72e8e2..18de402c0c 100644 --- a/internal/grpc/services/applicationauth/applicationauth.go +++ b/internal/grpc/services/applicationauth/applicationauth.go @@ -27,13 +27,17 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const serviceName = "applicationauth" +const tracerName = "applicationauth" + func init() { - rgrpc.Register("applicationauth", New) + rgrpc.Register(serviceName, New) } type config struct { @@ -42,6 +46,7 @@ type config struct { } type service struct { + tracing.GrpcMiddleware conf *config am appauth.Manager } @@ -74,7 +79,6 @@ func parseConfig(m map[string]interface{}) (*config, error) { // New creates a app auth provider svc func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { - c, err := parseConfig(m) if err != nil { return nil, err @@ -103,6 +107,9 @@ func (s *service) UnprotectedEndpoints() []string { } func (s *service) GenerateAppPassword(ctx context.Context, req *appauthpb.GenerateAppPasswordRequest) (*appauthpb.GenerateAppPasswordResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GenerateAppPassword") + defer span.End() + pwd, err := s.am.GenerateAppPassword(ctx, req.TokenScope, req.Label, req.Expiration) if err != nil { return &appauthpb.GenerateAppPasswordResponse{ @@ -117,6 +124,9 @@ func (s *service) GenerateAppPassword(ctx context.Context, req *appauthpb.Genera } func (s *service) ListAppPasswords(ctx context.Context, req *appauthpb.ListAppPasswordsRequest) (*appauthpb.ListAppPasswordsResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListAppPasswords") + defer span.End() + pwds, err := s.am.ListAppPasswords(ctx) if err != nil { return &appauthpb.ListAppPasswordsResponse{ @@ -131,6 +141,9 @@ func (s *service) ListAppPasswords(ctx context.Context, req *appauthpb.ListAppPa } func (s *service) InvalidateAppPassword(ctx context.Context, req *appauthpb.InvalidateAppPasswordRequest) (*appauthpb.InvalidateAppPasswordResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "InvalidateAppPassword") + defer span.End() + err := s.am.InvalidateAppPassword(ctx, req.Password) if err != nil { return &appauthpb.InvalidateAppPasswordResponse{ @@ -144,6 +157,9 @@ func (s *service) InvalidateAppPassword(ctx context.Context, req *appauthpb.Inva } func (s *service) GetAppPassword(ctx context.Context, req *appauthpb.GetAppPasswordRequest) (*appauthpb.GetAppPasswordResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAppPassword") + defer span.End() + pwd, err := s.am.GetAppPassword(ctx, req.User, req.Password) if err != nil { return &appauthpb.GetAppPasswordResponse{ diff --git a/internal/grpc/services/appprovider/appprovider.go b/internal/grpc/services/appprovider/appprovider.go index 881dc4c4b7..963be8a04b 100644 --- a/internal/grpc/services/appprovider/appprovider.go +++ b/internal/grpc/services/appprovider/appprovider.go @@ -37,16 +37,21 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/juliangruber/go-intersect" "github.com/mitchellh/mapstructure" "google.golang.org/grpc" ) +const serviceName = "appprovider" +const tracerName = "appprovider" + func init() { - rgrpc.Register("appprovider", New) + rgrpc.Register(serviceName, New) } type service struct { + tracing.GrpcMiddleware provider app.Provider conf *config } @@ -80,6 +85,9 @@ func parseConfig(m map[string]interface{}) (*config, error) { // New creates a new AppProviderService func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { + ctx, span := tracing.SpanStart(context.Background(), serviceName, tracerName, "New") + defer span.End() + c, err := parseConfig(m) if err != nil { return nil, err @@ -89,21 +97,20 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { if err != nil { return nil, err } - service := &service{ conf: c, provider: provider, } - - go service.registerProvider() + go service.registerProvider(ctx) return service, nil } -func (s *service) registerProvider() { +func (s *service) registerProvider(ctx context.Context) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "registerProvider") + defer span.End() // Give the appregistry service time to come up time.Sleep(2 * time.Second) - ctx := context.Background() log := logger.New().With().Int("pid", os.Getpid()).Logger() pInfo, err := s.provider.GetAppProviderInfo(ctx) if err != nil { @@ -121,7 +128,7 @@ func (s *service) registerProvider() { pInfo.MimeTypes = mimeTypes } - client, err := pool.GetGatewayServiceClient(pool.Endpoint(s.conf.GatewaySvc)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(s.conf.GatewaySvc)) if err != nil { log.Error().Err(err).Msgf("error registering app provider: could not get gateway client") return @@ -171,6 +178,9 @@ func getProvider(c *config) (app.Provider, error) { } func (s *service) OpenInApp(ctx context.Context, req *providerpb.OpenInAppRequest) (*providerpb.OpenInAppResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "OpenInApp") + defer span.End() + appURL, err := s.provider.GetAppURL(ctx, req.ResourceInfo, req.ViewMode, req.AccessToken, s.conf.Language) if err != nil { res := &providerpb.OpenInAppResponse{ diff --git a/internal/grpc/services/appregistry/appregistry.go b/internal/grpc/services/appregistry/appregistry.go index 4b8c08f6d7..724c731fd5 100644 --- a/internal/grpc/services/appregistry/appregistry.go +++ b/internal/grpc/services/appregistry/appregistry.go @@ -29,14 +29,19 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" ) +const serviceName = "appregistry" +const tracerName = "appregistry" + func init() { - rgrpc.Register("appregistry", New) + rgrpc.Register(serviceName, New) } type svc struct { + tracing.GrpcMiddleware reg app.Registry } @@ -65,7 +70,6 @@ func (c *config) init() { // New creates a new StorageRegistryService func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { - c, err := parseConfig(m) if err != nil { return nil, err @@ -100,6 +104,9 @@ func getRegistry(c *config) (app.Registry, error) { } func (s *svc) GetAppProviders(ctx context.Context, req *registrypb.GetAppProvidersRequest) (*registrypb.GetAppProvidersResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAppProviders") + defer span.End() + p, err := s.reg.FindProviders(ctx, req.ResourceInfo.MimeType) if err != nil { return ®istrypb.GetAppProvidersResponse{ @@ -115,6 +122,9 @@ func (s *svc) GetAppProviders(ctx context.Context, req *registrypb.GetAppProvide } func (s *svc) AddAppProvider(ctx context.Context, req *registrypb.AddAppProviderRequest) (*registrypb.AddAppProviderResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "AddAppProvider") + defer span.End() + err := s.reg.AddProvider(ctx, req.Provider) if err != nil { return ®istrypb.AddAppProviderResponse{ @@ -129,6 +139,9 @@ func (s *svc) AddAppProvider(ctx context.Context, req *registrypb.AddAppProvider } func (s *svc) ListAppProviders(ctx context.Context, req *registrypb.ListAppProvidersRequest) (*registrypb.ListAppProvidersResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListAppProviders") + defer span.End() + providers, err := s.reg.ListProviders(ctx) if err != nil { return ®istrypb.ListAppProvidersResponse{ @@ -144,6 +157,9 @@ func (s *svc) ListAppProviders(ctx context.Context, req *registrypb.ListAppProvi } func (s *svc) ListSupportedMimeTypes(ctx context.Context, req *registrypb.ListSupportedMimeTypesRequest) (*registrypb.ListSupportedMimeTypesResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListSupportedMimeTypes") + defer span.End() + mimeTypes, err := s.reg.ListSupportedMimeTypes(ctx) if err != nil { return ®istrypb.ListSupportedMimeTypesResponse{ @@ -166,6 +182,9 @@ func (s *svc) ListSupportedMimeTypes(ctx context.Context, req *registrypb.ListSu } func (s *svc) GetDefaultAppProviderForMimeType(ctx context.Context, req *registrypb.GetDefaultAppProviderForMimeTypeRequest) (*registrypb.GetDefaultAppProviderForMimeTypeResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetDefaultAppProviderForMimeType") + defer span.End() + provider, err := s.reg.GetDefaultProviderForMimeType(ctx, req.MimeType) if err != nil { return ®istrypb.GetDefaultAppProviderForMimeTypeResponse{ @@ -181,6 +200,9 @@ func (s *svc) GetDefaultAppProviderForMimeType(ctx context.Context, req *registr } func (s *svc) SetDefaultAppProviderForMimeType(ctx context.Context, req *registrypb.SetDefaultAppProviderForMimeTypeRequest) (*registrypb.SetDefaultAppProviderForMimeTypeResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetDefaultAppProviderForMimeType") + defer span.End() + err := s.reg.SetDefaultProviderForMimeType(ctx, req.MimeType, req.Provider) if err != nil { return ®istrypb.SetDefaultAppProviderForMimeTypeResponse{ diff --git a/internal/grpc/services/authprovider/authprovider.go b/internal/grpc/services/authprovider/authprovider.go index ae4c7c1050..e51977efea 100644 --- a/internal/grpc/services/authprovider/authprovider.go +++ b/internal/grpc/services/authprovider/authprovider.go @@ -31,13 +31,17 @@ import ( "github.com/cs3org/reva/pkg/plugin" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const serviceName = "authprovider" +const tracerName = "authprovider" + func init() { - rgrpc.Register("authprovider", New) + rgrpc.Register(serviceName, New) } type config struct { @@ -52,6 +56,7 @@ func (c *config) init() { } type service struct { + tracing.GrpcMiddleware authmgr auth.Manager conf *config plugin *plugin.RevaPlugin @@ -131,6 +136,9 @@ func (s *service) Register(ss *grpc.Server) { } func (s *service) Authenticate(ctx context.Context, req *provider.AuthenticateRequest) (*provider.AuthenticateResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + log := appctx.GetLogger(ctx) username := req.ClientId password := req.ClientSecret diff --git a/internal/grpc/services/authregistry/authregistry.go b/internal/grpc/services/authregistry/authregistry.go index a449a28be9..e218643d73 100644 --- a/internal/grpc/services/authregistry/authregistry.go +++ b/internal/grpc/services/authregistry/authregistry.go @@ -27,15 +27,20 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "google.golang.org/grpc" ) +const serviceName = "authregistry" +const tracerName = "authregistry" + func init() { - rgrpc.Register("authregistry", New) + rgrpc.Register(serviceName, New) } type service struct { + tracing.GrpcMiddleware reg auth.Registry } @@ -102,6 +107,9 @@ func getRegistry(c *config) (auth.Registry, error) { } func (s *service) ListAuthProviders(ctx context.Context, req *registrypb.ListAuthProvidersRequest) (*registrypb.ListAuthProvidersResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListAuthProviders") + defer span.End() + pinfos, err := s.reg.ListProviders(ctx) if err != nil { return ®istrypb.ListAuthProvidersResponse{ @@ -117,6 +125,9 @@ func (s *service) ListAuthProviders(ctx context.Context, req *registrypb.ListAut } func (s *service) GetAuthProviders(ctx context.Context, req *registrypb.GetAuthProvidersRequest) (*registrypb.GetAuthProvidersResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAuthProviders") + defer span.End() + pinfo, err := s.reg.GetProvider(ctx, req.Type) if err != nil { return ®istrypb.GetAuthProvidersResponse{ diff --git a/internal/grpc/services/datatx/datatx.go b/internal/grpc/services/datatx/datatx.go index 8c2c2b87e2..6054c1c5ae 100644 --- a/internal/grpc/services/datatx/datatx.go +++ b/internal/grpc/services/datatx/datatx.go @@ -35,13 +35,17 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const serviceName = "datatx" +const tracerName = "datatx" + func init() { - rgrpc.Register("datatx", New) + rgrpc.Register(serviceName, New) } type config struct { @@ -56,6 +60,7 @@ type config struct { } type service struct { + tracing.GrpcMiddleware conf *config txManager txdriver.Manager txShareDriver *txShareDriver @@ -118,7 +123,6 @@ func parseConfig(m map[string]interface{}) (*config, error) { // New creates a new datatx svc func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { - c, err := parseConfig(m) if err != nil { return nil, err @@ -157,6 +161,9 @@ func (s *service) UnprotectedEndpoints() []string { } func (s *service) PullTransfer(ctx context.Context, req *datatx.PullTransferRequest) (*datatx.PullTransferResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "PullTransfer") + defer span.End() + srcEp, err := s.extractEndpointInfo(ctx, req.SrcTargetUri) if err != nil { return nil, err @@ -210,6 +217,9 @@ func (s *service) PullTransfer(ctx context.Context, req *datatx.PullTransferRequ } func (s *service) GetTransferStatus(ctx context.Context, req *datatx.GetTransferStatusRequest) (*datatx.GetTransferStatusResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetTransferStatus") + defer span.End() + txShare, ok := s.txShareDriver.model.TxShares[req.GetTxId().GetOpaqueId()] if !ok { return nil, errtypes.InternalError("datatx service: transfer not found") @@ -233,6 +243,9 @@ func (s *service) GetTransferStatus(ctx context.Context, req *datatx.GetTransfer } func (s *service) CancelTransfer(ctx context.Context, req *datatx.CancelTransferRequest) (*datatx.CancelTransferResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CancelTransfer") + defer span.End() + txShare, ok := s.txShareDriver.model.TxShares[req.GetTxId().GetOpaqueId()] if !ok { return nil, errtypes.InternalError("datatx service: transfer not found") @@ -257,6 +270,9 @@ func (s *service) CancelTransfer(ctx context.Context, req *datatx.CancelTransfer } func (s *service) ListTransfers(ctx context.Context, req *datatx.ListTransfersRequest) (*datatx.ListTransfersResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListTransfers") + defer span.End() + filters := req.Filters var txInfos []*datatx.TxInfo for _, txShare := range s.txShareDriver.model.TxShares { @@ -286,6 +302,9 @@ func (s *service) ListTransfers(ctx context.Context, req *datatx.ListTransfersRe } func (s *service) RetryTransfer(ctx context.Context, req *datatx.RetryTransferRequest) (*datatx.RetryTransferResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RetryTransfer") + defer span.End() + txShare, ok := s.txShareDriver.model.TxShares[req.GetTxId().GetOpaqueId()] if !ok { return nil, errtypes.InternalError("datatx service: transfer not found") @@ -309,6 +328,9 @@ func (s *service) RetryTransfer(ctx context.Context, req *datatx.RetryTransferRe } func (s *service) extractEndpointInfo(ctx context.Context, targetURL string) (*webdavEndpoint, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "extractEndpointInfo") + defer span.End() + if targetURL == "" { return nil, errtypes.BadRequest("datatx service: ref target is an empty uri") } diff --git a/internal/grpc/services/gateway/applicationauth.go b/internal/grpc/services/gateway/applicationauth.go index dd0ab0027f..c6dba4e67f 100644 --- a/internal/grpc/services/gateway/applicationauth.go +++ b/internal/grpc/services/gateway/applicationauth.go @@ -24,11 +24,15 @@ import ( appauthpb "github.com/cs3org/go-cs3apis/cs3/auth/applications/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (s *svc) GenerateAppPassword(ctx context.Context, req *appauthpb.GenerateAppPasswordRequest) (*appauthpb.GenerateAppPasswordResponse, error) { - c, err := pool.GetAppAuthProviderServiceClient(pool.Endpoint(s.c.ApplicationAuthEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GenerateAppPassword") + defer span.End() + + c, err := pool.GetAppAuthProviderServiceClient(ctx, pool.Endpoint(s.c.ApplicationAuthEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetAppAuthProviderServiceClient") return &appauthpb.GenerateAppPasswordResponse{ @@ -45,7 +49,10 @@ func (s *svc) GenerateAppPassword(ctx context.Context, req *appauthpb.GenerateAp } func (s *svc) ListAppPasswords(ctx context.Context, req *appauthpb.ListAppPasswordsRequest) (*appauthpb.ListAppPasswordsResponse, error) { - c, err := pool.GetAppAuthProviderServiceClient(pool.Endpoint(s.c.ApplicationAuthEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListAppPasswords") + defer span.End() + + c, err := pool.GetAppAuthProviderServiceClient(ctx, pool.Endpoint(s.c.ApplicationAuthEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetAppAuthProviderServiceClient") return &appauthpb.ListAppPasswordsResponse{ @@ -62,7 +69,10 @@ func (s *svc) ListAppPasswords(ctx context.Context, req *appauthpb.ListAppPasswo } func (s *svc) InvalidateAppPassword(ctx context.Context, req *appauthpb.InvalidateAppPasswordRequest) (*appauthpb.InvalidateAppPasswordResponse, error) { - c, err := pool.GetAppAuthProviderServiceClient(pool.Endpoint(s.c.ApplicationAuthEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "InvalidateAppPassword") + defer span.End() + + c, err := pool.GetAppAuthProviderServiceClient(ctx, pool.Endpoint(s.c.ApplicationAuthEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetAppAuthProviderServiceClient") return &appauthpb.InvalidateAppPasswordResponse{ @@ -79,7 +89,10 @@ func (s *svc) InvalidateAppPassword(ctx context.Context, req *appauthpb.Invalida } func (s *svc) GetAppPassword(ctx context.Context, req *appauthpb.GetAppPasswordRequest) (*appauthpb.GetAppPasswordResponse, error) { - c, err := pool.GetAppAuthProviderServiceClient(pool.Endpoint(s.c.ApplicationAuthEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAppPassword") + defer span.End() + + c, err := pool.GetAppAuthProviderServiceClient(ctx, pool.Endpoint(s.c.ApplicationAuthEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetAppAuthProviderServiceClient") return &appauthpb.GetAppPasswordResponse{ diff --git a/internal/grpc/services/gateway/appprovider.go b/internal/grpc/services/gateway/appprovider.go index 413ad77b90..1245132fda 100644 --- a/internal/grpc/services/gateway/appprovider.go +++ b/internal/grpc/services/gateway/appprovider.go @@ -37,6 +37,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -45,6 +46,9 @@ import ( ) func (s *svc) OpenInApp(ctx context.Context, req *gateway.OpenInAppRequest) (*providerpb.OpenInAppResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "OpenInApp") + defer span.End() + p, st := s.getPath(ctx, req.Ref) if st.Code != rpc.Code_CODE_OK { if st.Code == rpc.Code_CODE_NOT_FOUND { @@ -119,6 +123,9 @@ func (s *svc) OpenInApp(ctx context.Context, req *gateway.OpenInAppRequest) (*pr func (s *svc) openFederatedShares(ctx context.Context, targetURL string, vm gateway.OpenInAppRequest_ViewMode, app string, insecure, skipVerify bool, nameQueries ...string) (*providerpb.OpenInAppResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "openFederatedShares") + defer span.End() + log := appctx.GetLogger(ctx) targetURL, err := appendNameQuery(targetURL, nameQueries...) if err != nil { @@ -170,6 +177,8 @@ func (s *svc) openFederatedShares(ctx context.Context, targetURL string, vm gate func (s *svc) openLocalResources(ctx context.Context, ri *storageprovider.ResourceInfo, vm gateway.OpenInAppRequest_ViewMode, app string) (*providerpb.OpenInAppResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "openLocalResources") + defer span.End() accessToken, ok := ctxpkg.ContextGetToken(ctx) if !ok || accessToken == "" { @@ -189,7 +198,7 @@ func (s *svc) openLocalResources(ctx context.Context, ri *storageprovider.Resour return nil, err } - appProviderClient, err := pool.GetAppProviderClient(pool.Endpoint(provider.Address)) + appProviderClient, err := pool.GetAppProviderClient(ctx, pool.Endpoint(provider.Address)) if err != nil { return nil, errors.Wrap(err, "gateway: error calling GetAppProviderClient") } @@ -209,7 +218,10 @@ func (s *svc) openLocalResources(ctx context.Context, ri *storageprovider.Resour } func (s *svc) findAppProvider(ctx context.Context, ri *storageprovider.ResourceInfo, app string) (*registry.ProviderInfo, error) { - c, err := pool.GetAppRegistryClient(pool.Endpoint(s.c.AppRegistryEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "findAppProvider") + defer span.End() + + c, err := pool.GetAppRegistryClient(ctx, pool.Endpoint(s.c.AppRegistryEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error getting appregistry client") return nil, err diff --git a/internal/grpc/services/gateway/appregistry.go b/internal/grpc/services/gateway/appregistry.go index ee62a2cfda..d5415f2a9b 100644 --- a/internal/grpc/services/gateway/appregistry.go +++ b/internal/grpc/services/gateway/appregistry.go @@ -24,11 +24,15 @@ import ( registry "github.com/cs3org/go-cs3apis/cs3/app/registry/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (s *svc) GetAppProviders(ctx context.Context, req *registry.GetAppProvidersRequest) (*registry.GetAppProvidersResponse, error) { - c, err := pool.GetAppRegistryClient(pool.Endpoint(s.c.AppRegistryEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAppProviders") + defer span.End() + + c, err := pool.GetAppRegistryClient(ctx, pool.Endpoint(s.c.AppRegistryEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetAppRegistryClient") return ®istry.GetAppProvidersResponse{ @@ -45,7 +49,10 @@ func (s *svc) GetAppProviders(ctx context.Context, req *registry.GetAppProviders } func (s *svc) AddAppProvider(ctx context.Context, req *registry.AddAppProviderRequest) (*registry.AddAppProviderResponse, error) { - c, err := pool.GetAppRegistryClient(pool.Endpoint(s.c.AppRegistryEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "AddAppProvider") + defer span.End() + + c, err := pool.GetAppRegistryClient(ctx, pool.Endpoint(s.c.AppRegistryEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetAppRegistryClient") return ®istry.AddAppProviderResponse{ @@ -62,7 +69,10 @@ func (s *svc) AddAppProvider(ctx context.Context, req *registry.AddAppProviderRe } func (s *svc) ListAppProviders(ctx context.Context, req *registry.ListAppProvidersRequest) (*registry.ListAppProvidersResponse, error) { - c, err := pool.GetAppRegistryClient(pool.Endpoint(s.c.AppRegistryEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListAppProviders") + defer span.End() + + c, err := pool.GetAppRegistryClient(ctx, pool.Endpoint(s.c.AppRegistryEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetAppRegistryClient") return ®istry.ListAppProvidersResponse{ @@ -79,7 +89,10 @@ func (s *svc) ListAppProviders(ctx context.Context, req *registry.ListAppProvide } func (s *svc) ListSupportedMimeTypes(ctx context.Context, req *registry.ListSupportedMimeTypesRequest) (*registry.ListSupportedMimeTypesResponse, error) { - c, err := pool.GetAppRegistryClient(pool.Endpoint(s.c.AppRegistryEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListSupportedMimeTypes") + defer span.End() + + c, err := pool.GetAppRegistryClient(ctx, pool.Endpoint(s.c.AppRegistryEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetAppRegistryClient") return ®istry.ListSupportedMimeTypesResponse{ @@ -96,7 +109,10 @@ func (s *svc) ListSupportedMimeTypes(ctx context.Context, req *registry.ListSupp } func (s *svc) GetDefaultAppProviderForMimeType(ctx context.Context, req *registry.GetDefaultAppProviderForMimeTypeRequest) (*registry.GetDefaultAppProviderForMimeTypeResponse, error) { - c, err := pool.GetAppRegistryClient(pool.Endpoint(s.c.AppRegistryEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetDefaultAppProviderForMimeType") + defer span.End() + + c, err := pool.GetAppRegistryClient(ctx, pool.Endpoint(s.c.AppRegistryEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetAppRegistryClient") return ®istry.GetDefaultAppProviderForMimeTypeResponse{ @@ -113,7 +129,10 @@ func (s *svc) GetDefaultAppProviderForMimeType(ctx context.Context, req *registr } func (s *svc) SetDefaultAppProviderForMimeType(ctx context.Context, req *registry.SetDefaultAppProviderForMimeTypeRequest) (*registry.SetDefaultAppProviderForMimeTypeResponse, error) { - c, err := pool.GetAppRegistryClient(pool.Endpoint(s.c.AppRegistryEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetDefaultAppProviderForMimeType") + defer span.End() + + c, err := pool.GetAppRegistryClient(ctx, pool.Endpoint(s.c.AppRegistryEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetAppRegistryClient") return ®istry.SetDefaultAppProviderForMimeTypeResponse{ diff --git a/internal/grpc/services/gateway/authprovider.go b/internal/grpc/services/gateway/authprovider.go index 786755bc13..38cc250c38 100644 --- a/internal/grpc/services/gateway/authprovider.go +++ b/internal/grpc/services/gateway/authprovider.go @@ -34,11 +34,15 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" "google.golang.org/grpc/metadata" ) func (s *svc) Authenticate(ctx context.Context, req *gateway.AuthenticateRequest) (*gateway.AuthenticateResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + log := appctx.GetLogger(ctx) // find auth provider @@ -183,6 +187,9 @@ func (s *svc) Authenticate(ctx context.Context, req *gateway.AuthenticateRequest } func (s *svc) WhoAmI(ctx context.Context, req *gateway.WhoAmIRequest) (*gateway.WhoAmIResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "WhoAmI") + defer span.End() + u, _, err := s.tokenmgr.DismantleToken(ctx, req.Token) if err != nil { err = errors.Wrap(err, "gateway: error getting user from token") @@ -207,7 +214,10 @@ func (s *svc) WhoAmI(ctx context.Context, req *gateway.WhoAmIRequest) (*gateway. } func (s *svc) findAuthProvider(ctx context.Context, authType string) (authpb.ProviderAPIClient, error) { - c, err := pool.GetAuthRegistryServiceClient(pool.Endpoint(s.c.AuthRegistryEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "findAuthProvider") + defer span.End() + + c, err := pool.GetAuthRegistryServiceClient(ctx, pool.Endpoint(s.c.AuthRegistryEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error getting auth registry client") return nil, err @@ -224,7 +234,7 @@ func (s *svc) findAuthProvider(ctx context.Context, authType string) (authpb.Pro if res.Status.Code == rpc.Code_CODE_OK && res.Providers != nil && len(res.Providers) > 0 { // TODO(labkode): check for capabilities here - c, err := pool.GetAuthProviderServiceClient(pool.Endpoint(res.Providers[0].Address)) + c, err := pool.GetAuthProviderServiceClient(ctx, pool.Endpoint(res.Providers[0].Address)) if err != nil { err = errors.Wrap(err, "gateway: error getting an auth provider client") return nil, err diff --git a/internal/grpc/services/gateway/authregistry.go b/internal/grpc/services/gateway/authregistry.go index 0e4f10cf06..06ed532c73 100644 --- a/internal/grpc/services/gateway/authregistry.go +++ b/internal/grpc/services/gateway/authregistry.go @@ -26,11 +26,15 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (s *svc) ListAuthProviders(ctx context.Context, req *registry.ListAuthProvidersRequest) (*gateway.ListAuthProvidersResponse, error) { - c, err := pool.GetAuthRegistryServiceClient(pool.Endpoint(s.c.AuthRegistryEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListAuthProviders") + defer span.End() + + c, err := pool.GetAuthRegistryServiceClient(ctx, pool.Endpoint(s.c.AuthRegistryEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error getting auth registry client") return &gateway.ListAuthProvidersResponse{ diff --git a/internal/grpc/services/gateway/datatx.go b/internal/grpc/services/gateway/datatx.go index 3416ecd5f4..0daa75de79 100644 --- a/internal/grpc/services/gateway/datatx.go +++ b/internal/grpc/services/gateway/datatx.go @@ -24,11 +24,15 @@ import ( datatx "github.com/cs3org/go-cs3apis/cs3/tx/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (s *svc) PullTransfer(ctx context.Context, req *datatx.PullTransferRequest) (*datatx.PullTransferResponse, error) { - c, err := pool.GetDataTxClient(pool.Endpoint(s.c.DataTxEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "PullTransfer") + defer span.End() + + c, err := pool.GetDataTxClient(ctx, pool.Endpoint(s.c.DataTxEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetDataTxClient") return &datatx.PullTransferResponse{ @@ -45,7 +49,10 @@ func (s *svc) PullTransfer(ctx context.Context, req *datatx.PullTransferRequest) } func (s *svc) GetTransferStatus(ctx context.Context, req *datatx.GetTransferStatusRequest) (*datatx.GetTransferStatusResponse, error) { - c, err := pool.GetDataTxClient(pool.Endpoint(s.c.DataTxEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetTransferStatus") + defer span.End() + + c, err := pool.GetDataTxClient(ctx, pool.Endpoint(s.c.DataTxEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetDataTxClient") return &datatx.GetTransferStatusResponse{ @@ -62,7 +69,10 @@ func (s *svc) GetTransferStatus(ctx context.Context, req *datatx.GetTransferStat } func (s *svc) CancelTransfer(ctx context.Context, req *datatx.CancelTransferRequest) (*datatx.CancelTransferResponse, error) { - c, err := pool.GetDataTxClient(pool.Endpoint(s.c.DataTxEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CancelTransfer") + defer span.End() + + c, err := pool.GetDataTxClient(ctx, pool.Endpoint(s.c.DataTxEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetDataTxClient") return &datatx.CancelTransferResponse{ @@ -79,7 +89,10 @@ func (s *svc) CancelTransfer(ctx context.Context, req *datatx.CancelTransferRequ } func (s *svc) ListTransfers(ctx context.Context, req *datatx.ListTransfersRequest) (*datatx.ListTransfersResponse, error) { - c, err := pool.GetDataTxClient(pool.Endpoint(s.c.DataTxEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListTransfers") + defer span.End() + + c, err := pool.GetDataTxClient(ctx, pool.Endpoint(s.c.DataTxEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetDataTxClient") return &datatx.ListTransfersResponse{ @@ -96,7 +109,10 @@ func (s *svc) ListTransfers(ctx context.Context, req *datatx.ListTransfersReques } func (s *svc) RetryTransfer(ctx context.Context, req *datatx.RetryTransferRequest) (*datatx.RetryTransferResponse, error) { - c, err := pool.GetDataTxClient(pool.Endpoint(s.c.DataTxEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RetryTransfer") + defer span.End() + + c, err := pool.GetDataTxClient(ctx, pool.Endpoint(s.c.DataTxEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetDataTxClient") return &datatx.RetryTransferResponse{ diff --git a/internal/grpc/services/gateway/gateway.go b/internal/grpc/services/gateway/gateway.go index 5108abf501..adee2c49a8 100644 --- a/internal/grpc/services/gateway/gateway.go +++ b/internal/grpc/services/gateway/gateway.go @@ -32,13 +32,17 @@ import ( "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/token" "github.com/cs3org/reva/pkg/token/manager/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const serviceName = "gateway" +const tracerName = "gateway" + func init() { - rgrpc.Register("gateway", New) + rgrpc.Register(serviceName, New) } type config struct { @@ -119,6 +123,7 @@ func (c *config) init() { } type svc struct { + tracing.GrpcMiddleware c *config dataGatewayURL url.URL tokenmgr token.Manager diff --git a/internal/grpc/services/gateway/groupprovider.go b/internal/grpc/services/gateway/groupprovider.go index 6965d46f3a..a42623dc37 100644 --- a/internal/grpc/services/gateway/groupprovider.go +++ b/internal/grpc/services/gateway/groupprovider.go @@ -24,11 +24,15 @@ import ( group "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (s *svc) GetGroup(ctx context.Context, req *group.GetGroupRequest) (*group.GetGroupResponse, error) { - c, err := pool.GetGroupProviderServiceClient(pool.Endpoint(s.c.GroupProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetGroup") + defer span.End() + + c, err := pool.GetGroupProviderServiceClient(ctx, pool.Endpoint(s.c.GroupProviderEndpoint)) if err != nil { return &group.GetGroupResponse{ Status: status.NewInternal(ctx, err, "error getting auth client"), @@ -44,7 +48,10 @@ func (s *svc) GetGroup(ctx context.Context, req *group.GetGroupRequest) (*group. } func (s *svc) GetGroupByClaim(ctx context.Context, req *group.GetGroupByClaimRequest) (*group.GetGroupByClaimResponse, error) { - c, err := pool.GetGroupProviderServiceClient(pool.Endpoint(s.c.GroupProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetGroupByClaim") + defer span.End() + + c, err := pool.GetGroupProviderServiceClient(ctx, pool.Endpoint(s.c.GroupProviderEndpoint)) if err != nil { return &group.GetGroupByClaimResponse{ Status: status.NewInternal(ctx, err, "error getting auth client"), @@ -60,7 +67,10 @@ func (s *svc) GetGroupByClaim(ctx context.Context, req *group.GetGroupByClaimReq } func (s *svc) FindGroups(ctx context.Context, req *group.FindGroupsRequest) (*group.FindGroupsResponse, error) { - c, err := pool.GetGroupProviderServiceClient(pool.Endpoint(s.c.GroupProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "FindGroups") + defer span.End() + + c, err := pool.GetGroupProviderServiceClient(ctx, pool.Endpoint(s.c.GroupProviderEndpoint)) if err != nil { return &group.FindGroupsResponse{ Status: status.NewInternal(ctx, err, "error getting auth client"), @@ -76,7 +86,10 @@ func (s *svc) FindGroups(ctx context.Context, req *group.FindGroupsRequest) (*gr } func (s *svc) GetMembers(ctx context.Context, req *group.GetMembersRequest) (*group.GetMembersResponse, error) { - c, err := pool.GetGroupProviderServiceClient(pool.Endpoint(s.c.GroupProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetMembers") + defer span.End() + + c, err := pool.GetGroupProviderServiceClient(ctx, pool.Endpoint(s.c.GroupProviderEndpoint)) if err != nil { return &group.GetMembersResponse{ Status: status.NewInternal(ctx, err, "error getting auth client"), @@ -92,7 +105,10 @@ func (s *svc) GetMembers(ctx context.Context, req *group.GetMembersRequest) (*gr } func (s *svc) HasMember(ctx context.Context, req *group.HasMemberRequest) (*group.HasMemberResponse, error) { - c, err := pool.GetGroupProviderServiceClient(pool.Endpoint(s.c.GroupProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "HasMember") + defer span.End() + + c, err := pool.GetGroupProviderServiceClient(ctx, pool.Endpoint(s.c.GroupProviderEndpoint)) if err != nil { return &group.HasMemberResponse{ Status: status.NewInternal(ctx, err, "error getting auth client"), diff --git a/internal/grpc/services/gateway/ocmcore.go b/internal/grpc/services/gateway/ocmcore.go index e9a81622c2..ca1e99f387 100644 --- a/internal/grpc/services/gateway/ocmcore.go +++ b/internal/grpc/services/gateway/ocmcore.go @@ -24,11 +24,15 @@ import ( ocmcore "github.com/cs3org/go-cs3apis/cs3/ocm/core/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (s *svc) CreateOCMCoreShare(ctx context.Context, req *ocmcore.CreateOCMCoreShareRequest) (*ocmcore.CreateOCMCoreShareResponse, error) { - c, err := pool.GetOCMCoreClient(pool.Endpoint(s.c.OCMCoreEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateOCMCoreShare") + defer span.End() + + c, err := pool.GetOCMCoreClient(ctx, pool.Endpoint(s.c.OCMCoreEndpoint)) if err != nil { return &ocmcore.CreateOCMCoreShareResponse{ Status: status.NewInternal(ctx, err, "error getting ocm core client"), diff --git a/internal/grpc/services/gateway/ocminvitemanager.go b/internal/grpc/services/gateway/ocminvitemanager.go index a75646f384..d398db89b6 100644 --- a/internal/grpc/services/gateway/ocminvitemanager.go +++ b/internal/grpc/services/gateway/ocminvitemanager.go @@ -24,11 +24,15 @@ import ( invitepb "github.com/cs3org/go-cs3apis/cs3/ocm/invite/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (s *svc) GenerateInviteToken(ctx context.Context, req *invitepb.GenerateInviteTokenRequest) (*invitepb.GenerateInviteTokenResponse, error) { - c, err := pool.GetOCMInviteManagerClient(pool.Endpoint(s.c.OCMInviteManagerEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GenerateInviteToken") + defer span.End() + + c, err := pool.GetOCMInviteManagerClient(ctx, pool.Endpoint(s.c.OCMInviteManagerEndpoint)) if err != nil { return &invitepb.GenerateInviteTokenResponse{ Status: status.NewInternal(ctx, err, "error getting user invite provider client"), @@ -44,7 +48,10 @@ func (s *svc) GenerateInviteToken(ctx context.Context, req *invitepb.GenerateInv } func (s *svc) ForwardInvite(ctx context.Context, req *invitepb.ForwardInviteRequest) (*invitepb.ForwardInviteResponse, error) { - c, err := pool.GetOCMInviteManagerClient(pool.Endpoint(s.c.OCMInviteManagerEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ForwardInvite") + defer span.End() + + c, err := pool.GetOCMInviteManagerClient(ctx, pool.Endpoint(s.c.OCMInviteManagerEndpoint)) if err != nil { return &invitepb.ForwardInviteResponse{ Status: status.NewInternal(ctx, err, "error getting user invite provider client"), @@ -60,7 +67,10 @@ func (s *svc) ForwardInvite(ctx context.Context, req *invitepb.ForwardInviteRequ } func (s *svc) AcceptInvite(ctx context.Context, req *invitepb.AcceptInviteRequest) (*invitepb.AcceptInviteResponse, error) { - c, err := pool.GetOCMInviteManagerClient(pool.Endpoint(s.c.OCMInviteManagerEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "AcceptInvite") + defer span.End() + + c, err := pool.GetOCMInviteManagerClient(ctx, pool.Endpoint(s.c.OCMInviteManagerEndpoint)) if err != nil { return &invitepb.AcceptInviteResponse{ Status: status.NewInternal(ctx, err, "error getting user invite provider client"), @@ -76,7 +86,10 @@ func (s *svc) AcceptInvite(ctx context.Context, req *invitepb.AcceptInviteReques } func (s *svc) GetAcceptedUser(ctx context.Context, req *invitepb.GetAcceptedUserRequest) (*invitepb.GetAcceptedUserResponse, error) { - c, err := pool.GetOCMInviteManagerClient(pool.Endpoint(s.c.OCMInviteManagerEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAcceptedUser") + defer span.End() + + c, err := pool.GetOCMInviteManagerClient(ctx, pool.Endpoint(s.c.OCMInviteManagerEndpoint)) if err != nil { return &invitepb.GetAcceptedUserResponse{ Status: status.NewInternal(ctx, err, "error getting user invite provider client"), @@ -92,7 +105,10 @@ func (s *svc) GetAcceptedUser(ctx context.Context, req *invitepb.GetAcceptedUser } func (s *svc) FindAcceptedUsers(ctx context.Context, req *invitepb.FindAcceptedUsersRequest) (*invitepb.FindAcceptedUsersResponse, error) { - c, err := pool.GetOCMInviteManagerClient(pool.Endpoint(s.c.OCMInviteManagerEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "FindAcceptedUsers") + defer span.End() + + c, err := pool.GetOCMInviteManagerClient(ctx, pool.Endpoint(s.c.OCMInviteManagerEndpoint)) if err != nil { return &invitepb.FindAcceptedUsersResponse{ Status: status.NewInternal(ctx, err, "error getting user invite provider client"), diff --git a/internal/grpc/services/gateway/ocmproviderauthorizer.go b/internal/grpc/services/gateway/ocmproviderauthorizer.go index 6fc4e3be77..ed4e43308e 100644 --- a/internal/grpc/services/gateway/ocmproviderauthorizer.go +++ b/internal/grpc/services/gateway/ocmproviderauthorizer.go @@ -24,11 +24,15 @@ import ( ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (s *svc) IsProviderAllowed(ctx context.Context, req *ocmprovider.IsProviderAllowedRequest) (*ocmprovider.IsProviderAllowedResponse, error) { - c, err := pool.GetOCMProviderAuthorizerClient(pool.Endpoint(s.c.OCMProviderAuthorizerEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "IsProviderAllowed") + defer span.End() + + c, err := pool.GetOCMProviderAuthorizerClient(ctx, pool.Endpoint(s.c.OCMProviderAuthorizerEndpoint)) if err != nil { return &ocmprovider.IsProviderAllowedResponse{ Status: status.NewInternal(ctx, err, "error getting ocm authorizer provider client"), @@ -44,7 +48,10 @@ func (s *svc) IsProviderAllowed(ctx context.Context, req *ocmprovider.IsProvider } func (s *svc) GetInfoByDomain(ctx context.Context, req *ocmprovider.GetInfoByDomainRequest) (*ocmprovider.GetInfoByDomainResponse, error) { - c, err := pool.GetOCMProviderAuthorizerClient(pool.Endpoint(s.c.OCMProviderAuthorizerEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetInfoByDomain") + defer span.End() + + c, err := pool.GetOCMProviderAuthorizerClient(ctx, pool.Endpoint(s.c.OCMProviderAuthorizerEndpoint)) if err != nil { return &ocmprovider.GetInfoByDomainResponse{ Status: status.NewInternal(ctx, err, "error getting ocm authorizer provider client"), @@ -60,7 +67,10 @@ func (s *svc) GetInfoByDomain(ctx context.Context, req *ocmprovider.GetInfoByDom } func (s *svc) ListAllProviders(ctx context.Context, req *ocmprovider.ListAllProvidersRequest) (*ocmprovider.ListAllProvidersResponse, error) { - c, err := pool.GetOCMProviderAuthorizerClient(pool.Endpoint(s.c.OCMProviderAuthorizerEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListAllProviders") + defer span.End() + + c, err := pool.GetOCMProviderAuthorizerClient(ctx, pool.Endpoint(s.c.OCMProviderAuthorizerEndpoint)) if err != nil { return &ocmprovider.ListAllProvidersResponse{ Status: status.NewInternal(ctx, err, "error getting ocm authorizer provider client"), diff --git a/internal/grpc/services/gateway/ocmshareprovider.go b/internal/grpc/services/gateway/ocmshareprovider.go index e0ffd6913c..e0808be79d 100644 --- a/internal/grpc/services/gateway/ocmshareprovider.go +++ b/internal/grpc/services/gateway/ocmshareprovider.go @@ -36,12 +36,16 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) // TODO(labkode): add multi-phase commit logic when commit share or commit ref is enabled. func (s *svc) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareRequest) (*ocm.CreateOCMShareResponse, error) { - c, err := pool.GetOCMShareProviderClient(pool.Endpoint(s.c.OCMShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateOCMShare") + defer span.End() + + c, err := pool.GetOCMShareProviderClient(ctx, pool.Endpoint(s.c.OCMShareProviderEndpoint)) if err != nil { return &ocm.CreateOCMShareResponse{ Status: status.NewInternal(ctx, err, "error getting user share provider client"), @@ -75,7 +79,10 @@ func (s *svc) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareRequest } func (s *svc) RemoveOCMShare(ctx context.Context, req *ocm.RemoveOCMShareRequest) (*ocm.RemoveOCMShareResponse, error) { - c, err := pool.GetOCMShareProviderClient(pool.Endpoint(s.c.OCMShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RemoveOCMShare") + defer span.End() + + c, err := pool.GetOCMShareProviderClient(ctx, pool.Endpoint(s.c.OCMShareProviderEndpoint)) if err != nil { return &ocm.RemoveOCMShareResponse{ Status: status.NewInternal(ctx, err, "error getting user share provider client"), @@ -133,11 +140,17 @@ func (s *svc) RemoveOCMShare(ctx context.Context, req *ocm.RemoveOCMShareRequest // If there are any inconsistencies, the share needs to be flag as invalid and a background process // or active fix needs to be performed. func (s *svc) GetOCMShare(ctx context.Context, req *ocm.GetOCMShareRequest) (*ocm.GetOCMShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetOCMShare") + defer span.End() + return s.getOCMShare(ctx, req) } func (s *svc) getOCMShare(ctx context.Context, req *ocm.GetOCMShareRequest) (*ocm.GetOCMShareResponse, error) { - c, err := pool.GetOCMShareProviderClient(pool.Endpoint(s.c.OCMShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getOCMShare") + defer span.End() + + c, err := pool.GetOCMShareProviderClient(ctx, pool.Endpoint(s.c.OCMShareProviderEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetOCMShareProviderClient") return &ocm.GetOCMShareResponse{ @@ -155,7 +168,10 @@ func (s *svc) getOCMShare(ctx context.Context, req *ocm.GetOCMShareRequest) (*oc // TODO(labkode): read GetShare comment. func (s *svc) ListOCMShares(ctx context.Context, req *ocm.ListOCMSharesRequest) (*ocm.ListOCMSharesResponse, error) { - c, err := pool.GetOCMShareProviderClient(pool.Endpoint(s.c.OCMShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListOCMShares") + defer span.End() + + c, err := pool.GetOCMShareProviderClient(ctx, pool.Endpoint(s.c.OCMShareProviderEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetOCMShareProviderClient") return &ocm.ListOCMSharesResponse{ @@ -172,7 +188,10 @@ func (s *svc) ListOCMShares(ctx context.Context, req *ocm.ListOCMSharesRequest) } func (s *svc) UpdateOCMShare(ctx context.Context, req *ocm.UpdateOCMShareRequest) (*ocm.UpdateOCMShareResponse, error) { - c, err := pool.GetOCMShareProviderClient(pool.Endpoint(s.c.OCMShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateOCMShare") + defer span.End() + + c, err := pool.GetOCMShareProviderClient(ctx, pool.Endpoint(s.c.OCMShareProviderEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetOCMShareProviderClient") return &ocm.UpdateOCMShareResponse{ @@ -189,7 +208,10 @@ func (s *svc) UpdateOCMShare(ctx context.Context, req *ocm.UpdateOCMShareRequest } func (s *svc) ListReceivedOCMShares(ctx context.Context, req *ocm.ListReceivedOCMSharesRequest) (*ocm.ListReceivedOCMSharesResponse, error) { - c, err := pool.GetOCMShareProviderClient(pool.Endpoint(s.c.OCMShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "IsProviderAllowed") + defer span.End() + + c, err := pool.GetOCMShareProviderClient(ctx, pool.Endpoint(s.c.OCMShareProviderEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetOCMShareProviderClient") return &ocm.ListReceivedOCMSharesResponse{ @@ -206,8 +228,11 @@ func (s *svc) ListReceivedOCMShares(ctx context.Context, req *ocm.ListReceivedOC } func (s *svc) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateReceivedOCMShareRequest) (*ocm.UpdateReceivedOCMShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateReceivedOCMShare") + defer span.End() + log := appctx.GetLogger(ctx) - c, err := pool.GetOCMShareProviderClient(pool.Endpoint(s.c.OCMShareProviderEndpoint)) + c, err := pool.GetOCMShareProviderClient(ctx, pool.Endpoint(s.c.OCMShareProviderEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetOCMShareProviderClient") return &ocm.UpdateReceivedOCMShareResponse{ @@ -434,7 +459,10 @@ func (s *svc) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateReceive } func (s *svc) GetReceivedOCMShare(ctx context.Context, req *ocm.GetReceivedOCMShareRequest) (*ocm.GetReceivedOCMShareResponse, error) { - c, err := pool.GetOCMShareProviderClient(pool.Endpoint(s.c.OCMShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetReceivedOCMShare") + defer span.End() + + c, err := pool.GetOCMShareProviderClient(ctx, pool.Endpoint(s.c.OCMShareProviderEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetOCMShareProviderClient") return &ocm.GetReceivedOCMShareResponse{ @@ -451,6 +479,9 @@ func (s *svc) GetReceivedOCMShare(ctx context.Context, req *ocm.GetReceivedOCMSh } func (s *svc) removeOCMReference(ctx context.Context, resourceID *provider.ResourceId) *rpc.Status { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "removeOCMReference") + defer span.End() + log := appctx.GetLogger(ctx) idReference := &provider.Reference{ResourceId: resourceID} @@ -522,6 +553,8 @@ func (s *svc) removeOCMReference(ctx context.Context, resourceID *provider.Resou } func (s *svc) createOCMReference(ctx context.Context, share *ocm.Share) (*rpc.Status, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "createOCMReference") + defer span.End() log := appctx.GetLogger(ctx) diff --git a/internal/grpc/services/gateway/permissions.go b/internal/grpc/services/gateway/permissions.go index b6514b0441..a0fda525cb 100644 --- a/internal/grpc/services/gateway/permissions.go +++ b/internal/grpc/services/gateway/permissions.go @@ -24,11 +24,15 @@ import ( permissions "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (s *svc) CheckPermission(ctx context.Context, req *permissions.CheckPermissionRequest) (*permissions.CheckPermissionResponse, error) { - c, err := pool.GetPermissionsClient(pool.Endpoint(s.c.PermissionsEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CheckPermission") + defer span.End() + + c, err := pool.GetPermissionsClient(ctx, pool.Endpoint(s.c.PermissionsEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetPermissionssClient") return &permissions.CheckPermissionResponse{ diff --git a/internal/grpc/services/gateway/preferences.go b/internal/grpc/services/gateway/preferences.go index a33f351ae4..849f736f62 100644 --- a/internal/grpc/services/gateway/preferences.go +++ b/internal/grpc/services/gateway/preferences.go @@ -24,11 +24,15 @@ import ( preferences "github.com/cs3org/go-cs3apis/cs3/preferences/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (s *svc) SetKey(ctx context.Context, req *preferences.SetKeyRequest) (*preferences.SetKeyResponse, error) { - c, err := pool.GetPreferencesClient(pool.Endpoint(s.c.PreferencesEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetKey") + defer span.End() + + c, err := pool.GetPreferencesClient(ctx, pool.Endpoint(s.c.PreferencesEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetPreferencesClient") return &preferences.SetKeyResponse{ @@ -45,7 +49,10 @@ func (s *svc) SetKey(ctx context.Context, req *preferences.SetKeyRequest) (*pref } func (s *svc) GetKey(ctx context.Context, req *preferences.GetKeyRequest) (*preferences.GetKeyResponse, error) { - c, err := pool.GetPreferencesClient(pool.Endpoint(s.c.PreferencesEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetKey") + defer span.End() + + c, err := pool.GetPreferencesClient(ctx, pool.Endpoint(s.c.PreferencesEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetPreferencesClient") return &preferences.GetKeyResponse{ diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index ec899792a3..7ea2a48ea5 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -26,10 +26,14 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShareRequest) (*link.CreatePublicShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreatePublicShare") + defer span.End() + if s.isSharedFolder(ctx, req.ResourceInfo.GetPath()) { return nil, errtypes.AlreadyExists("gateway: can't create a public share of the share folder itself") } @@ -37,7 +41,7 @@ func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShare log := appctx.GetLogger(ctx) log.Info().Msg("create public share") - c, err := pool.GetPublicShareProviderClient(pool.Endpoint(s.c.PublicShareProviderEndpoint)) + c, err := pool.GetPublicShareProviderClient(ctx, pool.Endpoint(s.c.PublicShareProviderEndpoint)) if err != nil { return nil, err } @@ -51,10 +55,13 @@ func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShare } func (s *svc) RemovePublicShare(ctx context.Context, req *link.RemovePublicShareRequest) (*link.RemovePublicShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RemovePublicShare") + defer span.End() + log := appctx.GetLogger(ctx) log.Info().Msg("remove public share") - driver, err := pool.GetPublicShareProviderClient(pool.Endpoint(s.c.PublicShareProviderEndpoint)) + driver, err := pool.GetPublicShareProviderClient(ctx, pool.Endpoint(s.c.PublicShareProviderEndpoint)) if err != nil { return nil, err } @@ -66,10 +73,13 @@ func (s *svc) RemovePublicShare(ctx context.Context, req *link.RemovePublicShare } func (s *svc) GetPublicShareByToken(ctx context.Context, req *link.GetPublicShareByTokenRequest) (*link.GetPublicShareByTokenResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPublicShareByToken") + defer span.End() + log := appctx.GetLogger(ctx) log.Info().Msg("get public share by token") - driver, err := pool.GetPublicShareProviderClient(pool.Endpoint(s.c.PublicShareProviderEndpoint)) + driver, err := pool.GetPublicShareProviderClient(ctx, pool.Endpoint(s.c.PublicShareProviderEndpoint)) if err != nil { return nil, err } @@ -83,10 +93,13 @@ func (s *svc) GetPublicShareByToken(ctx context.Context, req *link.GetPublicShar } func (s *svc) GetPublicShare(ctx context.Context, req *link.GetPublicShareRequest) (*link.GetPublicShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPublicShare") + defer span.End() + log := appctx.GetLogger(ctx) log.Info().Msg("get public share") - pClient, err := pool.GetPublicShareProviderClient(pool.Endpoint(s.c.PublicShareProviderEndpoint)) + pClient, err := pool.GetPublicShareProviderClient(ctx, pool.Endpoint(s.c.PublicShareProviderEndpoint)) if err != nil { log.Err(err).Msg("error connecting to a public share provider") return &link.GetPublicShareResponse{ @@ -100,10 +113,13 @@ func (s *svc) GetPublicShare(ctx context.Context, req *link.GetPublicShareReques } func (s *svc) ListPublicShares(ctx context.Context, req *link.ListPublicSharesRequest) (*link.ListPublicSharesResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListPublicShares") + defer span.End() + log := appctx.GetLogger(ctx) log.Info().Msg("listing public shares") - pClient, err := pool.GetPublicShareProviderClient(pool.Endpoint(s.c.PublicShareProviderEndpoint)) + pClient, err := pool.GetPublicShareProviderClient(ctx, pool.Endpoint(s.c.PublicShareProviderEndpoint)) if err != nil { log.Err(err).Msg("error connecting to a public share provider") return &link.ListPublicSharesResponse{ @@ -122,10 +138,13 @@ func (s *svc) ListPublicShares(ctx context.Context, req *link.ListPublicSharesRe } func (s *svc) UpdatePublicShare(ctx context.Context, req *link.UpdatePublicShareRequest) (*link.UpdatePublicShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdatePublicShare") + defer span.End() + log := appctx.GetLogger(ctx) log.Info().Msg("update public share") - pClient, err := pool.GetPublicShareProviderClient(pool.Endpoint(s.c.PublicShareProviderEndpoint)) + pClient, err := pool.GetPublicShareProviderClient(ctx, pool.Endpoint(s.c.PublicShareProviderEndpoint)) if err != nil { log.Err(err).Msg("error connecting to a public share provider") return &link.UpdatePublicShareResponse{ diff --git a/internal/grpc/services/gateway/sharesstorageprovider.go b/internal/grpc/services/gateway/sharesstorageprovider.go index 2aa02bd475..4ff9985fbc 100644 --- a/internal/grpc/services/gateway/sharesstorageprovider.go +++ b/internal/grpc/services/gateway/sharesstorageprovider.go @@ -29,25 +29,38 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/storage/utils/etag" + "github.com/cs3org/reva/pkg/tracing" ) func (s *svc) getSharedFolder(ctx context.Context) string { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getSharedFolder") + defer span.End() + return path.Join("/", s.c.ShareFolder) } // check if the path contains the prefix of the shared folder func (s *svc) inSharedFolder(ctx context.Context, p string) bool { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "inSharedFolder") + defer span.End() + sharedFolder := s.getSharedFolder(ctx) return strings.HasPrefix(p, sharedFolder) } // /MyShares/ func (s *svc) isSharedFolder(ctx context.Context, p string) bool { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "isSharedFolder") + defer span.End() + return p == s.getSharedFolder(ctx) } // /MyShares/photos/ func (s *svc) isShareName(ctx context.Context, p string) bool { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "isShareName") + defer span.End() + sharedFolder := s.getSharedFolder(ctx) rel := strings.Trim(strings.TrimPrefix(p, sharedFolder), "/") return strings.HasPrefix(p, sharedFolder) && len(strings.Split(rel, "/")) == 1 @@ -55,6 +68,9 @@ func (s *svc) isShareName(ctx context.Context, p string) bool { // /MyShares/photos/Ibiza/beach.png func (s *svc) isShareChild(ctx context.Context, p string) bool { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "isShareChild") + defer span.End() + sharedFolder := s.getSharedFolder(ctx) rel := strings.Trim(strings.TrimPrefix(p, sharedFolder), "/") return strings.HasPrefix(p, sharedFolder) && len(strings.Split(rel, "/")) > 1 @@ -63,6 +79,9 @@ func (s *svc) isShareChild(ctx context.Context, p string) bool { // path must contain a share path with share children, if not it will panic. // should be called after checking isShareChild == true func (s *svc) splitShare(ctx context.Context, p string) (string, string) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "splitShare") + defer span.End() + sharedFolder := s.getSharedFolder(ctx) p = strings.Trim(strings.TrimPrefix(p, sharedFolder), "/") parts := strings.SplitN(p, "/", 2) @@ -76,6 +95,9 @@ func (s *svc) splitShare(ctx context.Context, p string) (string, string) { } func (s *svc) statSharesFolder(ctx context.Context) (*provider.StatResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "statSharesFolder") + defer span.End() + statRes, err := s.stat(ctx, &provider.StatRequest{ Ref: &provider.Reference{ Path: s.getSharedFolder(ctx), @@ -118,6 +140,9 @@ func (s *svc) statSharesFolder(ctx context.Context) (*provider.StatResponse, err } func (s *svc) listSharesFolder(ctx context.Context) (*provider.ListContainerResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listSharesFolder") + defer span.End() + lcr, err := s.listContainer(ctx, &provider.ListContainerRequest{ Ref: &provider.Reference{ Path: s.getSharedFolder(ctx), diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index ae8ccc77b3..28f1466436 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -37,7 +37,7 @@ import ( types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" ctxpkg "github.com/cs3org/reva/pkg/ctx" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/appctx" @@ -58,7 +58,10 @@ type transferClaims struct { Target string `json:"target"` } -func (s *svc) sign(_ context.Context, target string) (string, error) { +func (s *svc) sign(ctx context.Context, target string) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "sign") + defer span.End() + // Tus sends a separate request to the datagateway service for every chunk. // For large files, this can take a long time, so we extend the expiration ttl := time.Duration(s.c.TransferExpires) * time.Second @@ -82,6 +85,9 @@ func (s *svc) sign(_ context.Context, target string) (string, error) { } func (s *svc) CreateHome(ctx context.Context, req *provider.CreateHomeRequest) (*provider.CreateHomeResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateHome") + defer span.End() + log := appctx.GetLogger(ctx) home := s.getHome(ctx) @@ -103,6 +109,9 @@ func (s *svc) CreateHome(ctx context.Context, req *provider.CreateHomeRequest) ( } func (s *svc) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateStorageSpace") + defer span.End() + log := appctx.GetLogger(ctx) // TODO: needs to be fixed c, err := s.findByPath(ctx, "/users") @@ -123,6 +132,9 @@ func (s *svc) CreateStorageSpace(ctx context.Context, req *provider.CreateStorag } func (s *svc) ListStorageSpaces(ctx context.Context, req *provider.ListStorageSpacesRequest) (*provider.ListStorageSpacesResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListStorageSpaces") + defer span.End() + log := appctx.GetLogger(ctx) var id *provider.StorageSpaceId for _, f := range req.Filters { @@ -135,7 +147,7 @@ func (s *svc) ListStorageSpaces(ctx context.Context, req *provider.ListStorageSp providers []*registry.ProviderInfo err error ) - c, err := pool.GetStorageRegistryClient(pool.Endpoint(s.c.StorageRegistryEndpoint)) + c, err := pool.GetStorageRegistryClient(ctx, pool.Endpoint(s.c.StorageRegistryEndpoint)) if err != nil { return nil, errors.Wrap(err, "gateway: error getting storage registry client") } @@ -234,6 +246,9 @@ func (s *svc) ListStorageSpaces(ctx context.Context, req *provider.ListStorageSp } func (s *svc) listStorageSpacesOnProvider(ctx context.Context, req *provider.ListStorageSpacesRequest, res *[]*provider.StorageSpace, p *registry.ProviderInfo, e *error, wg *sync.WaitGroup) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listStorageSpacesOnProvider") + defer span.End() + defer wg.Done() c, err := s.getStorageProviderClient(ctx, p) if err != nil { @@ -251,6 +266,9 @@ func (s *svc) listStorageSpacesOnProvider(ctx context.Context, req *provider.Lis } func (s *svc) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateStorageSpace") + defer span.End() + log := appctx.GetLogger(ctx) // TODO: needs to be fixed c, err := s.find(ctx, &provider.Reference{ResourceId: req.StorageSpace.Root}) @@ -271,6 +289,9 @@ func (s *svc) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorag } func (s *svc) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorageSpaceRequest) (*provider.DeleteStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DeleteStorageSpace") + defer span.End() + log := appctx.GetLogger(ctx) // TODO: needs to be fixed storageid, opaqeid, err := utils.SplitStorageSpaceID(req.Id.OpaqueId) @@ -300,18 +321,27 @@ func (s *svc) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorag } func (s *svc) GetHome(ctx context.Context, _ *provider.GetHomeRequest) (*provider.GetHomeResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetHome") + defer span.End() + return &provider.GetHomeResponse{ Path: s.getHome(ctx), Status: status.NewOK(ctx), }, nil } -func (s *svc) getHome(_ context.Context) string { +func (s *svc) getHome(ctx context.Context) string { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getHome") + defer span.End() + // TODO(labkode): issue #601, /home will be hardcoded. return "/home" } func (s *svc) InitiateFileDownload(ctx context.Context, req *provider.InitiateFileDownloadRequest) (*gateway.InitiateFileDownloadResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "InitiateFileDownload") + defer span.End() + log := appctx.GetLogger(ctx) if utils.IsRelativeReference(req.Ref) { @@ -475,6 +505,9 @@ func (s *svc) InitiateFileDownload(ctx context.Context, req *provider.InitiateFi } func (s *svc) initiateFileDownload(ctx context.Context, req *provider.InitiateFileDownloadRequest) (*gateway.InitiateFileDownloadResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "initiateFileDownload") + defer span.End() + // TODO(ishank011): enable downloading references spread across storage providers, eg. /eos c, err := s.find(ctx, req.Ref) if err != nil { @@ -530,6 +563,9 @@ func (s *svc) initiateFileDownload(ctx context.Context, req *provider.InitiateFi } func (s *svc) InitiateFileUpload(ctx context.Context, req *provider.InitiateFileUploadRequest) (*gateway.InitiateFileUploadResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "InitiateFileUpload") + defer span.End() + log := appctx.GetLogger(ctx) if utils.IsRelativeReference(req.Ref) { return s.initiateFileUpload(ctx, req) @@ -677,6 +713,9 @@ func (s *svc) InitiateFileUpload(ctx context.Context, req *provider.InitiateFile } func (s *svc) initiateFileUpload(ctx context.Context, req *provider.InitiateFileUploadRequest) (*gateway.InitiateFileUploadResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "initiateFileUpload") + defer span.End() + c, err := s.find(ctx, req.Ref) if err != nil { return &gateway.InitiateFileUploadResponse{ @@ -738,6 +777,9 @@ func (s *svc) initiateFileUpload(ctx context.Context, req *provider.InitiateFile } func (s *svc) GetPath(ctx context.Context, req *provider.GetPathRequest) (*provider.GetPathResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPath") + defer span.End() + statReq := &provider.StatRequest{Ref: &provider.Reference{ResourceId: req.ResourceId}} statRes, err := s.stat(ctx, statReq) if err != nil { @@ -758,6 +800,9 @@ func (s *svc) GetPath(ctx context.Context, req *provider.GetPathRequest) (*provi } func (s *svc) CreateContainer(ctx context.Context, req *provider.CreateContainerRequest) (*provider.CreateContainerResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateContainer") + defer span.End() + log := appctx.GetLogger(ctx) if utils.IsRelativeReference(req.Ref) { @@ -830,6 +875,9 @@ func (s *svc) CreateContainer(ctx context.Context, req *provider.CreateContainer } func (s *svc) createContainer(ctx context.Context, req *provider.CreateContainerRequest) (*provider.CreateContainerResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "createContainer") + defer span.End() + c, err := s.find(ctx, req.Ref) if err != nil { return &provider.CreateContainerResponse{ @@ -849,6 +897,9 @@ func (s *svc) createContainer(ctx context.Context, req *provider.CreateContainer } func (s *svc) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*provider.TouchFileResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "TouchFile") + defer span.End() + c, err := s.find(ctx, req.Ref) if err != nil { return &provider.TouchFileResponse{ @@ -868,6 +919,9 @@ func (s *svc) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*p } func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Delete") + defer span.End() + log := appctx.GetLogger(ctx) p, st := s.getPath(ctx, req.Ref) if st.Code != rpc.Code_CODE_OK { @@ -876,17 +930,12 @@ func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provide }, nil } - ctx, span := rtrace.Provider.Tracer("reva").Start(ctx, "Delete") - defer span.End() - if !s.inSharedFolder(ctx, p) { return s.delete(ctx, req) } if s.isSharedFolder(ctx, p) { // TODO(labkode): deleting share names should be allowed, means unmounting. - err := errtypes.BadRequest("gateway: cannot delete share folder or share name: path=" + p) - span.RecordError(err) return &provider.DeleteResponse{ Status: status.NewInvalidArg(ctx, "path points to share folder or share name"), }, nil @@ -1001,6 +1050,9 @@ func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provide } func (s *svc) delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "delete") + defer span.End() + // TODO(ishank011): enable deleting references spread across storage providers, eg. /eos c, err := s.find(ctx, req.Ref) if err != nil { @@ -1021,6 +1073,9 @@ func (s *svc) delete(ctx context.Context, req *provider.DeleteRequest) (*provide } func (s *svc) Move(ctx context.Context, req *provider.MoveRequest) (*provider.MoveResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Move") + defer span.End() + log := appctx.GetLogger(ctx) p, st := s.getPath(ctx, req.Source) if st.Code != rpc.Code_CODE_OK { @@ -1136,6 +1191,9 @@ func (s *svc) Move(ctx context.Context, req *provider.MoveRequest) (*provider.Mo } func (s *svc) move(ctx context.Context, req *provider.MoveRequest) (*provider.MoveResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "move") + defer span.End() + srcProviders, err := s.findProviders(ctx, req.Source) if err != nil { return &provider.MoveResponse{ @@ -1179,6 +1237,9 @@ func (s *svc) move(ctx context.Context, req *provider.MoveRequest) (*provider.Mo } func (s *svc) SetArbitraryMetadata(ctx context.Context, req *provider.SetArbitraryMetadataRequest) (*provider.SetArbitraryMetadataResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetArbitraryMetadata") + defer span.End() + // TODO(ishank011): enable for references spread across storage providers, eg. /eos c, err := s.find(ctx, req.Ref) if err != nil { @@ -1199,6 +1260,9 @@ func (s *svc) SetArbitraryMetadata(ctx context.Context, req *provider.SetArbitra } func (s *svc) UnsetArbitraryMetadata(ctx context.Context, req *provider.UnsetArbitraryMetadataRequest) (*provider.UnsetArbitraryMetadataResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UnsetArbitraryMetadata") + defer span.End() + // TODO(ishank011): enable for references spread across storage providers, eg. /eos c, err := s.find(ctx, req.Ref) if err != nil { @@ -1220,6 +1284,9 @@ func (s *svc) UnsetArbitraryMetadata(ctx context.Context, req *provider.UnsetArb // SetLock puts a lock on the given reference func (s *svc) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provider.SetLockResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetLock") + defer span.End() + c, err := s.find(ctx, req.Ref) if err != nil { return &provider.SetLockResponse{ @@ -1240,6 +1307,9 @@ func (s *svc) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provi // GetLock returns an existing lock on the given reference func (s *svc) GetLock(ctx context.Context, req *provider.GetLockRequest) (*provider.GetLockResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetLock") + defer span.End() + c, err := s.find(ctx, req.Ref) if err != nil { return &provider.GetLockResponse{ @@ -1260,6 +1330,9 @@ func (s *svc) GetLock(ctx context.Context, req *provider.GetLockRequest) (*provi // RefreshLock refreshes an existing lock on the given reference func (s *svc) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) (*provider.RefreshLockResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RefreshLock") + defer span.End() + c, err := s.find(ctx, req.Ref) if err != nil { return &provider.RefreshLockResponse{ @@ -1280,6 +1353,9 @@ func (s *svc) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) // Unlock removes an existing lock from the given reference func (s *svc) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provider.UnlockResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Unlock") + defer span.End() + c, err := s.find(ctx, req.Ref) if err != nil { return &provider.UnlockResponse{ @@ -1299,13 +1375,16 @@ func (s *svc) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provide } func (s *svc) stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "stat") + defer span.End() + providers, err := s.findProviders(ctx, req.Ref) if err != nil { return &provider.StatResponse{ Status: status.NewStatusFromErrType(ctx, "stat ref: "+req.Ref.String(), err), }, nil } - providers = getUniqueProviders(providers) + providers = s.getUniqueProviders(ctx, providers) resPath := req.Ref.GetPath() if len(providers) == 1 && (utils.IsRelativeReference(req.Ref) || resPath == "" || strings.HasPrefix(resPath, providers[0].ProviderPath)) { @@ -1326,6 +1405,9 @@ func (s *svc) stat(ctx context.Context, req *provider.StatRequest) (*provider.St } func (s *svc) statAcrossProviders(ctx context.Context, req *provider.StatRequest, providers []*registry.ProviderInfo) (*provider.StatResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "statAcrossProviders") + defer span.End() + // TODO(ishank011): aggregrate properties such as etag, checksum, etc. log := appctx.GetLogger(ctx) info := &provider.ResourceInfo{ @@ -1379,6 +1461,9 @@ func (s *svc) statAcrossProviders(ctx context.Context, req *provider.StatRequest } func (s *svc) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Stat") + defer span.End() + if utils.IsRelativeReference(req.Ref) { return s.stat(ctx, req) } @@ -1525,6 +1610,9 @@ func (s *svc) Stat(ctx context.Context, req *provider.StatRequest) (*provider.St } func (s *svc) checkRef(ctx context.Context, ri *provider.ResourceInfo) (*provider.ResourceInfo, string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "checkRef") + defer span.End() + if ri.Type != provider.ResourceType_RESOURCE_TYPE_REFERENCE { panic("gateway: calling checkRef on a non reference type:" + ri.String()) } @@ -1553,6 +1641,9 @@ func (s *svc) checkRef(ctx context.Context, ri *provider.ResourceInfo) (*provide } func (s *svc) handleCS3Ref(ctx context.Context, opaque string) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "handleCS3Ref") + defer span.End() + // a cs3 ref has the following layout: / parts := strings.SplitN(opaque, "/", 2) if len(parts) < 2 { @@ -1604,6 +1695,9 @@ func (s *svc) ListContainerStream(_ *provider.ListContainerStreamRequest, _ gate } func (s *svc) filterProvidersByUserAgent(ctx context.Context, providers []*registry.ProviderInfo) []*registry.ProviderInfo { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "filterProvidersByUserAgent") + defer span.End() + cat, ok := ctxpkg.ContextGetUserAgentCategory(ctx) if !ok { return providers @@ -1611,14 +1705,17 @@ func (s *svc) filterProvidersByUserAgent(ctx context.Context, providers []*regis filters := []*registry.ProviderInfo{} for _, p := range providers { - if s.isPathAllowed(cat, p.ProviderPath) { + if s.isPathAllowed(ctx, cat, p.ProviderPath) { filters = append(filters, p) } } return filters } -func (s *svc) isPathAllowed(cat string, path string) bool { +func (s *svc) isPathAllowed(ctx context.Context, cat string, path string) bool { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "isPathAllowed") + defer span.End() + allowedUserAgents, ok := s.c.AllowedUserAgents[path] if !ok { // if no user agent is defined for a path, all user agents are allowed @@ -1634,13 +1731,16 @@ func (s *svc) isPathAllowed(cat string, path string) bool { } func (s *svc) listContainer(ctx context.Context, req *provider.ListContainerRequest) (*provider.ListContainerResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listContainer") + defer span.End() + providers, err := s.findProviders(ctx, req.Ref) if err != nil { return &provider.ListContainerResponse{ Status: status.NewStatusFromErrType(ctx, "listContainer ref: "+req.Ref.String(), err), }, nil } - providers = getUniqueProviders(providers) + providers = s.getUniqueProviders(ctx, providers) resPath := req.Ref.GetPath() @@ -1662,6 +1762,9 @@ func (s *svc) listContainer(ctx context.Context, req *provider.ListContainerRequ } func (s *svc) listContainerAcrossProviders(ctx context.Context, req *provider.ListContainerRequest, providers []*registry.ProviderInfo) (*provider.ListContainerResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listContainerAcrossProviders") + defer span.End() + nestedInfos := make(map[string]*provider.ResourceInfo) log := appctx.GetLogger(ctx) @@ -1723,6 +1826,9 @@ func (s *svc) listContainerAcrossProviders(ctx context.Context, req *provider.Li } func (s *svc) ListContainer(ctx context.Context, req *provider.ListContainerRequest) (*provider.ListContainerResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListContainer") + defer span.End() + log := appctx.GetLogger(ctx) if utils.IsRelativeReference(req.Ref) { @@ -1901,6 +2007,8 @@ func (s *svc) ListContainer(ctx context.Context, req *provider.ListContainerRequ } func (s *svc) getPath(ctx context.Context, ref *provider.Reference, keys ...string) (string, *rpc.Status) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getPath") + defer span.End() // check if it is an id based or combined reference first if ref.ResourceId != nil { @@ -1923,12 +2031,18 @@ func (s *svc) getPath(ctx context.Context, ref *provider.Reference, keys ...stri } func (s *svc) CreateSymlink(ctx context.Context, req *provider.CreateSymlinkRequest) (*provider.CreateSymlinkResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateSymlink") + defer span.End() + return &provider.CreateSymlinkResponse{ Status: status.NewUnimplemented(ctx, errtypes.NotSupported("CreateSymlink not implemented"), "CreateSymlink not implemented"), }, nil } func (s *svc) ListFileVersions(ctx context.Context, req *provider.ListFileVersionsRequest) (*provider.ListFileVersionsResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListFileVersions") + defer span.End() + c, err := s.find(ctx, req.Ref) if err != nil { return &provider.ListFileVersionsResponse{ @@ -1945,6 +2059,9 @@ func (s *svc) ListFileVersions(ctx context.Context, req *provider.ListFileVersio } func (s *svc) RestoreFileVersion(ctx context.Context, req *provider.RestoreFileVersionRequest) (*provider.RestoreFileVersionResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreFileVersion") + defer span.End() + c, err := s.find(ctx, req.Ref) if err != nil { return &provider.RestoreFileVersionResponse{ @@ -1966,6 +2083,9 @@ func (s *svc) ListRecycleStream(_ *provider.ListRecycleStreamRequest, _ gateway. // TODO use the ListRecycleRequest.Ref to only list the trash of a specific storage func (s *svc) ListRecycle(ctx context.Context, req *provider.ListRecycleRequest) (*provider.ListRecycleResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListRecycle") + defer span.End() + c, err := s.find(ctx, req.GetRef()) if err != nil { return &provider.ListRecycleResponse{ @@ -1982,6 +2102,9 @@ func (s *svc) ListRecycle(ctx context.Context, req *provider.ListRecycleRequest) } func (s *svc) RestoreRecycleItem(ctx context.Context, req *provider.RestoreRecycleItemRequest) (*provider.RestoreRecycleItemResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreRecycleItem") + defer span.End() + c, err := s.find(ctx, req.Ref) if err != nil { return &provider.RestoreRecycleItemResponse{ @@ -1998,6 +2121,9 @@ func (s *svc) RestoreRecycleItem(ctx context.Context, req *provider.RestoreRecyc } func (s *svc) PurgeRecycle(ctx context.Context, req *provider.PurgeRecycleRequest) (*provider.PurgeRecycleResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "PurgeRecycle") + defer span.End() + c, err := s.find(ctx, req.Ref) if err != nil { return &provider.PurgeRecycleResponse{ @@ -2013,6 +2139,9 @@ func (s *svc) PurgeRecycle(ctx context.Context, req *provider.PurgeRecycleReques } func (s *svc) GetQuota(ctx context.Context, req *gateway.GetQuotaRequest) (*provider.GetQuotaResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetQuota") + defer span.End() + c, err := s.find(ctx, req.Ref) if err != nil { return &provider.GetQuotaResponse{ @@ -2031,11 +2160,17 @@ func (s *svc) GetQuota(ctx context.Context, req *gateway.GetQuotaRequest) (*prov } func (s *svc) findByPath(ctx context.Context, path string) (provider.ProviderAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "findByPath") + defer span.End() + ref := &provider.Reference{Path: path} return s.find(ctx, ref) } func (s *svc) find(ctx context.Context, ref *provider.Reference) (provider.ProviderAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "find") + defer span.End() + p, err := s.findProviders(ctx, ref) if err != nil { return nil, err @@ -2043,8 +2178,11 @@ func (s *svc) find(ctx context.Context, ref *provider.Reference) (provider.Provi return s.getStorageProviderClient(ctx, p[0]) } -func (s *svc) getStorageProviderClient(_ context.Context, p *registry.ProviderInfo) (provider.ProviderAPIClient, error) { - c, err := pool.GetStorageProviderServiceClient(pool.Endpoint(p.Address)) +func (s *svc) getStorageProviderClient(ctx context.Context, p *registry.ProviderInfo) (provider.ProviderAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getStorageProviderClient") + defer span.End() + + c, err := pool.GetStorageProviderServiceClient(ctx, pool.Endpoint(p.Address)) if err != nil { err = errors.Wrap(err, "gateway: error getting a storage provider client") return nil, err @@ -2054,7 +2192,10 @@ func (s *svc) getStorageProviderClient(_ context.Context, p *registry.ProviderIn } func (s *svc) findProviders(ctx context.Context, ref *provider.Reference) ([]*registry.ProviderInfo, error) { - c, err := pool.GetStorageRegistryClient(pool.Endpoint(s.c.StorageRegistryEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "findProviders") + defer span.End() + + c, err := pool.GetStorageRegistryClient(ctx, pool.Endpoint(s.c.StorageRegistryEndpoint)) if err != nil { return nil, errors.Wrap(err, "gateway: error getting storage registry client") } @@ -2089,7 +2230,10 @@ func (s *svc) findProviders(ctx context.Context, ref *provider.Reference) ([]*re return res.Providers, nil } -func getUniqueProviders(providers []*registry.ProviderInfo) []*registry.ProviderInfo { +func (s *svc) getUniqueProviders(ctx context.Context, providers []*registry.ProviderInfo) []*registry.ProviderInfo { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getUniqueProviders") + defer span.End() + unique := make(map[string]*registry.ProviderInfo) for _, p := range providers { unique[p.Address] = p diff --git a/internal/grpc/services/gateway/userprovider.go b/internal/grpc/services/gateway/userprovider.go index 8a4fd1c011..a832876310 100644 --- a/internal/grpc/services/gateway/userprovider.go +++ b/internal/grpc/services/gateway/userprovider.go @@ -24,11 +24,15 @@ import ( user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (s *svc) GetUser(ctx context.Context, req *user.GetUserRequest) (*user.GetUserResponse, error) { - c, err := pool.GetUserProviderServiceClient(pool.Endpoint(s.c.UserProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetUser") + defer span.End() + + c, err := pool.GetUserProviderServiceClient(ctx, pool.Endpoint(s.c.UserProviderEndpoint)) if err != nil { return &user.GetUserResponse{ Status: status.NewInternal(ctx, err, "error getting auth client"), @@ -44,7 +48,10 @@ func (s *svc) GetUser(ctx context.Context, req *user.GetUserRequest) (*user.GetU } func (s *svc) GetUserByClaim(ctx context.Context, req *user.GetUserByClaimRequest) (*user.GetUserByClaimResponse, error) { - c, err := pool.GetUserProviderServiceClient(pool.Endpoint(s.c.UserProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetUserByClaim") + defer span.End() + + c, err := pool.GetUserProviderServiceClient(ctx, pool.Endpoint(s.c.UserProviderEndpoint)) if err != nil { return &user.GetUserByClaimResponse{ Status: status.NewInternal(ctx, err, "error getting auth client"), @@ -60,7 +67,10 @@ func (s *svc) GetUserByClaim(ctx context.Context, req *user.GetUserByClaimReques } func (s *svc) FindUsers(ctx context.Context, req *user.FindUsersRequest) (*user.FindUsersResponse, error) { - c, err := pool.GetUserProviderServiceClient(pool.Endpoint(s.c.UserProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "FindUsers") + defer span.End() + + c, err := pool.GetUserProviderServiceClient(ctx, pool.Endpoint(s.c.UserProviderEndpoint)) if err != nil { return &user.FindUsersResponse{ Status: status.NewInternal(ctx, err, "error getting auth client"), @@ -76,7 +86,10 @@ func (s *svc) FindUsers(ctx context.Context, req *user.FindUsersRequest) (*user. } func (s *svc) GetUserGroups(ctx context.Context, req *user.GetUserGroupsRequest) (*user.GetUserGroupsResponse, error) { - c, err := pool.GetUserProviderServiceClient(pool.Endpoint(s.c.UserProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetUserGroups") + defer span.End() + + c, err := pool.GetUserProviderServiceClient(ctx, pool.Endpoint(s.c.UserProviderEndpoint)) if err != nil { return &user.GetUserGroupsResponse{ Status: status.NewInternal(ctx, err, "error getting auth client"), diff --git a/internal/grpc/services/gateway/usershareprovider.go b/internal/grpc/services/gateway/usershareprovider.go index 86d3bed499..db93c69bbd 100644 --- a/internal/grpc/services/gateway/usershareprovider.go +++ b/internal/grpc/services/gateway/usershareprovider.go @@ -34,18 +34,21 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/storage/utils/grants" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/pkg/errors" ) // TODO(labkode): add multi-phase commit logic when commit share or commit ref is enabled. func (s *svc) CreateShare(ctx context.Context, req *collaboration.CreateShareRequest) (*collaboration.CreateShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateShare") + defer span.End() if s.isSharedFolder(ctx, req.ResourceInfo.GetPath()) { return nil, errtypes.AlreadyExists("gateway: can't share the share folder itself") } - c, err := pool.GetUserShareProviderClient(pool.Endpoint(s.c.UserShareProviderEndpoint)) + c, err := pool.GetUserShareProviderClient(ctx, pool.Endpoint(s.c.UserShareProviderEndpoint)) if err != nil { return &collaboration.CreateShareResponse{ Status: status.NewInternal(ctx, err, "error getting user share provider client"), @@ -98,7 +101,10 @@ func (s *svc) CreateShare(ctx context.Context, req *collaboration.CreateShareReq } func (s *svc) RemoveShare(ctx context.Context, req *collaboration.RemoveShareRequest) (*collaboration.RemoveShareResponse, error) { - c, err := pool.GetUserShareProviderClient(pool.Endpoint(s.c.UserShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RemoveShare") + defer span.End() + + c, err := pool.GetUserShareProviderClient(ctx, pool.Endpoint(s.c.UserShareProviderEndpoint)) if err != nil { return &collaboration.RemoveShareResponse{ Status: status.NewInternal(ctx, err, "error getting user share provider client"), @@ -156,11 +162,17 @@ func (s *svc) RemoveShare(ctx context.Context, req *collaboration.RemoveShareReq // If there are any inconsistencies, the share needs to be flag as invalid and a background process // or active fix needs to be performed. func (s *svc) GetShare(ctx context.Context, req *collaboration.GetShareRequest) (*collaboration.GetShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetShare") + defer span.End() + return s.getShare(ctx, req) } func (s *svc) getShare(ctx context.Context, req *collaboration.GetShareRequest) (*collaboration.GetShareResponse, error) { - c, err := pool.GetUserShareProviderClient(pool.Endpoint(s.c.UserShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getShare") + defer span.End() + + c, err := pool.GetUserShareProviderClient(ctx, pool.Endpoint(s.c.UserShareProviderEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetUserShareProviderClient") return &collaboration.GetShareResponse{ @@ -178,7 +190,10 @@ func (s *svc) getShare(ctx context.Context, req *collaboration.GetShareRequest) // TODO(labkode): read GetShare comment. func (s *svc) ListShares(ctx context.Context, req *collaboration.ListSharesRequest) (*collaboration.ListSharesResponse, error) { - c, err := pool.GetUserShareProviderClient(pool.Endpoint(s.c.UserShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListShares") + defer span.End() + + c, err := pool.GetUserShareProviderClient(ctx, pool.Endpoint(s.c.UserShareProviderEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetUserShareProviderClient") return &collaboration.ListSharesResponse{ @@ -195,7 +210,10 @@ func (s *svc) ListShares(ctx context.Context, req *collaboration.ListSharesReque } func (s *svc) UpdateShare(ctx context.Context, req *collaboration.UpdateShareRequest) (*collaboration.UpdateShareResponse, error) { - c, err := pool.GetUserShareProviderClient(pool.Endpoint(s.c.UserShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateShare") + defer span.End() + + c, err := pool.GetUserShareProviderClient(ctx, pool.Endpoint(s.c.UserShareProviderEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetUserShareProviderClient") return &collaboration.UpdateShareResponse{ @@ -239,7 +257,10 @@ func (s *svc) UpdateShare(ctx context.Context, req *collaboration.UpdateShareReq // received shares. The display name of the shares should be the a friendly name, like the basename // of the original file. func (s *svc) ListReceivedShares(ctx context.Context, req *collaboration.ListReceivedSharesRequest) (*collaboration.ListReceivedSharesResponse, error) { - c, err := pool.GetUserShareProviderClient(pool.Endpoint(s.c.UserShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListReceivedShares") + defer span.End() + + c, err := pool.GetUserShareProviderClient(ctx, pool.Endpoint(s.c.UserShareProviderEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetUserShareProviderClient") return &collaboration.ListReceivedSharesResponse{ @@ -255,7 +276,10 @@ func (s *svc) ListReceivedShares(ctx context.Context, req *collaboration.ListRec } func (s *svc) GetReceivedShare(ctx context.Context, req *collaboration.GetReceivedShareRequest) (*collaboration.GetReceivedShareResponse, error) { - c, err := pool.GetUserShareProviderClient(pool.Endpoint(s.c.UserShareProviderEndpoint)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetReceivedShare") + defer span.End() + + c, err := pool.GetUserShareProviderClient(ctx, pool.Endpoint(s.c.UserShareProviderEndpoint)) if err != nil { err := errors.Wrap(err, "gateway: error getting user share provider client") return &collaboration.GetReceivedShareResponse{ @@ -273,9 +297,12 @@ func (s *svc) GetReceivedShare(ctx context.Context, req *collaboration.GetReceiv // When updating a received share: // if the update contains update for displayName: -// 1) if received share is mounted: we also do a rename in the storage -// 2) if received share is not mounted: we only rename in user share provider. +// 1. if received share is mounted: we also do a rename in the storage +// 2. if received share is not mounted: we only rename in user share provider. func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.UpdateReceivedShareRequest) (*collaboration.UpdateReceivedShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateReceivedShare") + defer span.End() + log := appctx.GetLogger(ctx) // sanity checks @@ -298,7 +325,7 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update }, nil } - c, err := pool.GetUserShareProviderClient(pool.Endpoint(s.c.UserShareProviderEndpoint)) + c, err := pool.GetUserShareProviderClient(ctx, pool.Endpoint(s.c.UserShareProviderEndpoint)) if err != nil { err = errors.Wrap(err, "gateway: error calling GetUserShareProviderClient") return &collaboration.UpdateReceivedShareResponse{ @@ -369,6 +396,9 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update } func (s *svc) removeReference(ctx context.Context, share *collaboration.Share) *rpc.Status { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "removeReference") + defer span.End() + log := appctx.GetLogger(ctx) idReference := &provider.Reference{ResourceId: share.ResourceId} @@ -457,6 +487,9 @@ func (s *svc) removeReference(ctx context.Context, share *collaboration.Share) * } func (s *svc) createReference(ctx context.Context, share *collaboration.Share) *rpc.Status { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "createReference") + defer span.End() + ref := &provider.Reference{ ResourceId: share.ResourceId, } @@ -546,6 +579,9 @@ func (s *svc) createReference(ctx context.Context, share *collaboration.Share) * } func (s *svc) denyGrant(ctx context.Context, id *provider.ResourceId, g *provider.Grantee) (*rpc.Status, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "denyGrant") + defer span.End() + ref := &provider.Reference{ ResourceId: id, } @@ -576,6 +612,9 @@ func (s *svc) denyGrant(ctx context.Context, id *provider.ResourceId, g *provide } func (s *svc) addGrant(ctx context.Context, id *provider.ResourceId, g *provider.Grantee, p *provider.ResourcePermissions) (*rpc.Status, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "addGrant") + defer span.End() + ref := &provider.Reference{ ResourceId: id, } @@ -609,6 +648,9 @@ func (s *svc) addGrant(ctx context.Context, id *provider.ResourceId, g *provider } func (s *svc) updateGrant(ctx context.Context, id *provider.ResourceId, g *provider.Grantee, p *provider.ResourcePermissions) (*rpc.Status, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "updateGrant") + defer span.End() + ref := &provider.Reference{ ResourceId: id, } @@ -641,6 +683,9 @@ func (s *svc) updateGrant(ctx context.Context, id *provider.ResourceId, g *provi } func (s *svc) removeGrant(ctx context.Context, id *provider.ResourceId, g *provider.Grantee, p *provider.ResourcePermissions) (*rpc.Status, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "removeGrant") + defer span.End() + ref := &provider.Reference{ ResourceId: id, } diff --git a/internal/grpc/services/gateway/webdavstorageprovider.go b/internal/grpc/services/gateway/webdavstorageprovider.go index c7cdc94077..6b3499652a 100644 --- a/internal/grpc/services/gateway/webdavstorageprovider.go +++ b/internal/grpc/services/gateway/webdavstorageprovider.go @@ -30,6 +30,7 @@ import ( types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" "github.com/studio-b12/gowebdav" ) @@ -41,6 +42,9 @@ type webdavEndpoint struct { } func (s *svc) webdavRefStat(ctx context.Context, targetURL string, nameQueries ...string) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "webdavRefStat") + defer span.End() + targetURL, err := appendNameQuery(targetURL, nameQueries...) if err != nil { return nil, err @@ -68,6 +72,9 @@ func (s *svc) webdavRefStat(ctx context.Context, targetURL string, nameQueries . } func (s *svc) webdavRefLs(ctx context.Context, targetURL string, nameQueries ...string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "webdavRefLs") + defer span.End() + targetURL, err := appendNameQuery(targetURL, nameQueries...) if err != nil { return nil, err @@ -101,6 +108,9 @@ func (s *svc) webdavRefLs(ctx context.Context, targetURL string, nameQueries ... } func (s *svc) webdavRefMkdir(ctx context.Context, targetURL string, nameQueries ...string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "webdavRefMkdir") + defer span.End() + targetURL, err := appendNameQuery(targetURL, nameQueries...) if err != nil { return err @@ -126,6 +136,9 @@ func (s *svc) webdavRefMkdir(ctx context.Context, targetURL string, nameQueries } func (s *svc) webdavRefMove(ctx context.Context, targetURL, src, destination string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "webdavRefMove") + defer span.End() + srcURL, err := appendNameQuery(targetURL, src) if err != nil { return err @@ -159,6 +172,9 @@ func (s *svc) webdavRefMove(ctx context.Context, targetURL, src, destination str } func (s *svc) webdavRefDelete(ctx context.Context, targetURL string, nameQueries ...string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "webdavRefDelete") + defer span.End() + targetURL, err := appendNameQuery(targetURL, nameQueries...) if err != nil { return err @@ -184,6 +200,9 @@ func (s *svc) webdavRefDelete(ctx context.Context, targetURL string, nameQueries } func (s *svc) webdavRefTransferEndpoint(ctx context.Context, targetURL string, nameQueries ...string) (string, *types.Opaque, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "webdavRefTransferEndpoint") + defer span.End() + targetURL, err := appendNameQuery(targetURL, nameQueries...) if err != nil { return "", nil, err @@ -213,6 +232,9 @@ func (s *svc) webdavRefTransferEndpoint(ctx context.Context, targetURL string, n } func (s *svc) extractEndpointInfo(ctx context.Context, targetURL string) (*webdavEndpoint, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "extractEndpointInfo") + defer span.End() + if targetURL == "" { return nil, errtypes.BadRequest("gateway: ref target is an empty uri") } @@ -238,6 +260,9 @@ func (s *svc) extractEndpointInfo(ctx context.Context, targetURL string) (*webda } func (s *svc) getWebdavEndpoint(ctx context.Context, domain string) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getWebdavEndpoint") + defer span.End() + meshProvider, err := s.GetInfoByDomain(ctx, &ocmprovider.GetInfoByDomainRequest{ Domain: domain, }) diff --git a/internal/grpc/services/groupprovider/groupprovider.go b/internal/grpc/services/groupprovider/groupprovider.go index 75cf828962..490cfe0cde 100644 --- a/internal/grpc/services/groupprovider/groupprovider.go +++ b/internal/grpc/services/groupprovider/groupprovider.go @@ -29,13 +29,17 @@ import ( "github.com/cs3org/reva/pkg/group/manager/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const serviceName = "groupprovider" +const tracerName = "groupprovider" + func init() { - rgrpc.Register("groupprovider", New) + rgrpc.Register(serviceName, New) } type config struct { @@ -85,6 +89,7 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { } type service struct { + tracing.GrpcMiddleware groupmgr group.Manager } @@ -101,6 +106,9 @@ func (s *service) Register(ss *grpc.Server) { } func (s *service) GetGroup(ctx context.Context, req *grouppb.GetGroupRequest) (*grouppb.GetGroupResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetGroup") + defer span.End() + group, err := s.groupmgr.GetGroup(ctx, req.GroupId, req.SkipFetchingMembers) if err != nil { res := &grouppb.GetGroupResponse{} @@ -120,6 +128,9 @@ func (s *service) GetGroup(ctx context.Context, req *grouppb.GetGroupRequest) (* } func (s *service) GetGroupByClaim(ctx context.Context, req *grouppb.GetGroupByClaimRequest) (*grouppb.GetGroupByClaimResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetGroupByClaim") + defer span.End() + group, err := s.groupmgr.GetGroupByClaim(ctx, req.Claim, req.Value, req.SkipFetchingMembers) if err != nil { res := &grouppb.GetGroupByClaimResponse{} @@ -139,6 +150,9 @@ func (s *service) GetGroupByClaim(ctx context.Context, req *grouppb.GetGroupByCl } func (s *service) FindGroups(ctx context.Context, req *grouppb.FindGroupsRequest) (*grouppb.FindGroupsResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "FindGroups") + defer span.End() + groups, err := s.groupmgr.FindGroups(ctx, req.Filter, req.SkipFetchingMembers) if err != nil { err = errors.Wrap(err, "groupprovidersvc: error finding groups") @@ -159,6 +173,9 @@ func (s *service) FindGroups(ctx context.Context, req *grouppb.FindGroupsRequest } func (s *service) GetMembers(ctx context.Context, req *grouppb.GetMembersRequest) (*grouppb.GetMembersResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetMembers") + defer span.End() + members, err := s.groupmgr.GetMembers(ctx, req.GroupId) if err != nil { err = errors.Wrap(err, "groupprovidersvc: error getting group members") @@ -174,6 +191,9 @@ func (s *service) GetMembers(ctx context.Context, req *grouppb.GetMembersRequest } func (s *service) HasMember(ctx context.Context, req *grouppb.HasMemberRequest) (*grouppb.HasMemberResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "HasMember") + defer span.End() + ok, err := s.groupmgr.HasMember(ctx, req.GroupId, req.UserId) if err != nil { err = errors.Wrap(err, "groupprovidersvc: error checking for group member") diff --git a/internal/grpc/services/helloworld/helloworld.go b/internal/grpc/services/helloworld/helloworld.go index 1f8bac3815..1ad4101fa5 100644 --- a/internal/grpc/services/helloworld/helloworld.go +++ b/internal/grpc/services/helloworld/helloworld.go @@ -24,11 +24,14 @@ import ( "github.com/cs3org/reva/internal/grpc/services/helloworld/proto" "github.com/cs3org/reva/pkg/rgrpc" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const tracerName = "helloworld" + func init() { rgrpc.Register("helloworld", New) } @@ -37,6 +40,7 @@ type conf struct { Message string `mapstructure:"message"` } type service struct { + tracing.GrpcMiddleware conf *conf } @@ -70,6 +74,9 @@ func (s *service) Register(ss *grpc.Server) { } func (s *service) Hello(ctx context.Context, req *proto.HelloRequest) (*proto.HelloResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Hello") + defer span.End() + if req.Name == "" { req.Name = "Mr. Nobody" } diff --git a/internal/grpc/services/ocmcore/ocmcore.go b/internal/grpc/services/ocmcore/ocmcore.go index 2f2dcf615f..3bf7cdc844 100644 --- a/internal/grpc/services/ocmcore/ocmcore.go +++ b/internal/grpc/services/ocmcore/ocmcore.go @@ -32,11 +32,14 @@ import ( "github.com/cs3org/reva/pkg/ocm/share/manager/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const tracerName = "ocmcore" + func init() { rgrpc.Register("ocmcore", New) } @@ -47,6 +50,7 @@ type config struct { } type service struct { + tracing.GrpcMiddleware conf *config sm share.Manager } @@ -79,7 +83,6 @@ func parseConfig(m map[string]interface{}) (*config, error) { // New creates a new ocm core svc func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { - c, err := parseConfig(m) if err != nil { return nil, err @@ -109,6 +112,9 @@ func (s *service) UnprotectedEndpoints() []string { // CreateOCMCoreShare is called when an OCM request comes into this reva instance from func (s *service) CreateOCMCoreShare(ctx context.Context, req *ocmcore.CreateOCMCoreShareRequest) (*ocmcore.CreateOCMCoreShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateOCMCoreShare") + defer span.End() + resource := &provider.ResourceId{ StorageId: "remote", OpaqueId: req.Name, diff --git a/internal/grpc/services/ocminvitemanager/ocminvitemanager.go b/internal/grpc/services/ocminvitemanager/ocminvitemanager.go index 6821f7d29e..759ea3c445 100644 --- a/internal/grpc/services/ocminvitemanager/ocminvitemanager.go +++ b/internal/grpc/services/ocminvitemanager/ocminvitemanager.go @@ -27,11 +27,14 @@ import ( "github.com/cs3org/reva/pkg/ocm/invite/manager/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const tracerName = "ocminvitemanager" + func init() { rgrpc.Register("ocminvitemanager", New) } @@ -42,6 +45,7 @@ type config struct { } type service struct { + tracing.GrpcMiddleware conf *config im invite.Manager } @@ -74,7 +78,6 @@ func parseConfig(m map[string]interface{}) (*config, error) { // New creates a new OCM invite manager svc func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { - c, err := parseConfig(m) if err != nil { return nil, err @@ -102,6 +105,9 @@ func (s *service) UnprotectedEndpoints() []string { } func (s *service) GenerateInviteToken(ctx context.Context, req *invitepb.GenerateInviteTokenRequest) (*invitepb.GenerateInviteTokenResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GenerateInviteToken") + defer span.End() + token, err := s.im.GenerateToken(ctx) if err != nil { return &invitepb.GenerateInviteTokenResponse{ @@ -116,6 +122,9 @@ func (s *service) GenerateInviteToken(ctx context.Context, req *invitepb.Generat } func (s *service) ForwardInvite(ctx context.Context, req *invitepb.ForwardInviteRequest) (*invitepb.ForwardInviteResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ForwardInvite") + defer span.End() + err := s.im.ForwardInvite(ctx, req.InviteToken, req.OriginSystemProvider) if err != nil { return &invitepb.ForwardInviteResponse{ @@ -129,6 +138,9 @@ func (s *service) ForwardInvite(ctx context.Context, req *invitepb.ForwardInvite } func (s *service) AcceptInvite(ctx context.Context, req *invitepb.AcceptInviteRequest) (*invitepb.AcceptInviteResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "AcceptInvite") + defer span.End() + err := s.im.AcceptInvite(ctx, req.InviteToken, req.RemoteUser) if err != nil { return &invitepb.AcceptInviteResponse{ @@ -142,6 +154,9 @@ func (s *service) AcceptInvite(ctx context.Context, req *invitepb.AcceptInviteRe } func (s *service) GetAcceptedUser(ctx context.Context, req *invitepb.GetAcceptedUserRequest) (*invitepb.GetAcceptedUserResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAcceptedUser") + defer span.End() + remoteUser, err := s.im.GetAcceptedUser(ctx, req.RemoteUserId) if err != nil { return &invitepb.GetAcceptedUserResponse{ @@ -156,6 +171,9 @@ func (s *service) GetAcceptedUser(ctx context.Context, req *invitepb.GetAccepted } func (s *service) FindAcceptedUsers(ctx context.Context, req *invitepb.FindAcceptedUsersRequest) (*invitepb.FindAcceptedUsersResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "FindAcceptedUsers") + defer span.End() + acceptedUsers, err := s.im.FindAcceptedUsers(ctx, req.Filter) if err != nil { return &invitepb.FindAcceptedUsersResponse{ diff --git a/internal/grpc/services/ocmproviderauthorizer/ocmproviderauthorizer.go b/internal/grpc/services/ocmproviderauthorizer/ocmproviderauthorizer.go index 8d89fccdd1..cb376d2bc0 100644 --- a/internal/grpc/services/ocmproviderauthorizer/ocmproviderauthorizer.go +++ b/internal/grpc/services/ocmproviderauthorizer/ocmproviderauthorizer.go @@ -27,11 +27,14 @@ import ( "github.com/cs3org/reva/pkg/ocm/provider/authorizer/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const tracerName = "ocmproviderauthorizer" + func init() { rgrpc.Register("ocmproviderauthorizer", New) } @@ -42,6 +45,7 @@ type config struct { } type service struct { + tracing.GrpcMiddleware conf *config pa provider.Authorizer } @@ -74,7 +78,6 @@ func parseConfig(m map[string]interface{}) (*config, error) { // New creates a new OCM provider authorizer svc func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { - c, err := parseConfig(m) if err != nil { return nil, err @@ -105,6 +108,9 @@ func (s *service) UnprotectedEndpoints() []string { } func (s *service) GetInfoByDomain(ctx context.Context, req *ocmprovider.GetInfoByDomainRequest) (*ocmprovider.GetInfoByDomainResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetInfoByDomain") + defer span.End() + domainInfo, err := s.pa.GetInfoByDomain(ctx, req.Domain) if err != nil { return &ocmprovider.GetInfoByDomainResponse{ @@ -119,6 +125,9 @@ func (s *service) GetInfoByDomain(ctx context.Context, req *ocmprovider.GetInfoB } func (s *service) IsProviderAllowed(ctx context.Context, req *ocmprovider.IsProviderAllowedRequest) (*ocmprovider.IsProviderAllowedResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "IsProviderAllowed") + defer span.End() + err := s.pa.IsProviderAllowed(ctx, req.Provider) if err != nil { return &ocmprovider.IsProviderAllowedResponse{ @@ -132,6 +141,9 @@ func (s *service) IsProviderAllowed(ctx context.Context, req *ocmprovider.IsProv } func (s *service) ListAllProviders(ctx context.Context, req *ocmprovider.ListAllProvidersRequest) (*ocmprovider.ListAllProvidersResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListAllProviders") + defer span.End() + providers, err := s.pa.ListAllProviders(ctx) if err != nil { return &ocmprovider.ListAllProvidersResponse{ diff --git a/internal/grpc/services/ocmshareprovider/ocmshareprovider.go b/internal/grpc/services/ocmshareprovider/ocmshareprovider.go index 2cf80c15f3..c5ac80ba86 100644 --- a/internal/grpc/services/ocmshareprovider/ocmshareprovider.go +++ b/internal/grpc/services/ocmshareprovider/ocmshareprovider.go @@ -27,11 +27,14 @@ import ( "github.com/cs3org/reva/pkg/ocm/share/manager/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const tracerName = "ocmshareprovider" + func init() { rgrpc.Register("ocmshareprovider", New) } @@ -42,6 +45,7 @@ type config struct { } type service struct { + tracing.GrpcMiddleware conf *config sm share.Manager } @@ -74,7 +78,6 @@ func parseConfig(m map[string]interface{}) (*config, error) { // New creates a new ocm share provider svc func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { - c, err := parseConfig(m) if err != nil { return nil, err @@ -116,6 +119,9 @@ func (s *service) UnprotectedEndpoints() []string { // on the OCM share manager: // pkg/ocm/share/manager/{json|nextcloud|...} func (s *service) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareRequest) (*ocm.CreateOCMShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateOCMShare") + defer span.End() + if req.Opaque == nil { return &ocm.CreateOCMShareResponse{ Status: status.NewInternal(ctx, errtypes.BadRequest("can't find resource permissions"), ""), @@ -190,6 +196,9 @@ func (s *service) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareReq } func (s *service) RemoveOCMShare(ctx context.Context, req *ocm.RemoveOCMShareRequest) (*ocm.RemoveOCMShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RemoveOCMShare") + defer span.End() + err := s.sm.Unshare(ctx, req.Ref) if err != nil { return &ocm.RemoveOCMShareResponse{ @@ -203,6 +212,9 @@ func (s *service) RemoveOCMShare(ctx context.Context, req *ocm.RemoveOCMShareReq } func (s *service) GetOCMShare(ctx context.Context, req *ocm.GetOCMShareRequest) (*ocm.GetOCMShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetOCMShare") + defer span.End() + share, err := s.sm.GetShare(ctx, req.Ref) if err != nil { return &ocm.GetOCMShareResponse{ @@ -217,6 +229,9 @@ func (s *service) GetOCMShare(ctx context.Context, req *ocm.GetOCMShareRequest) } func (s *service) ListOCMShares(ctx context.Context, req *ocm.ListOCMSharesRequest) (*ocm.ListOCMSharesResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListOCMShares") + defer span.End() + shares, err := s.sm.ListShares(ctx, req.Filters) // TODO(labkode): add filter to share manager if err != nil { return &ocm.ListOCMSharesResponse{ @@ -232,6 +247,9 @@ func (s *service) ListOCMShares(ctx context.Context, req *ocm.ListOCMSharesReque } func (s *service) UpdateOCMShare(ctx context.Context, req *ocm.UpdateOCMShareRequest) (*ocm.UpdateOCMShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateOCMShare") + defer span.End() + _, err := s.sm.UpdateShare(ctx, req.Ref, req.Field.GetPermissions()) // TODO(labkode): check what to update if err != nil { return &ocm.UpdateOCMShareResponse{ @@ -246,6 +264,9 @@ func (s *service) UpdateOCMShare(ctx context.Context, req *ocm.UpdateOCMShareReq } func (s *service) ListReceivedOCMShares(ctx context.Context, req *ocm.ListReceivedOCMSharesRequest) (*ocm.ListReceivedOCMSharesResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListReceivedOCMShares") + defer span.End() + shares, err := s.sm.ListReceivedShares(ctx) if err != nil { return &ocm.ListReceivedOCMSharesResponse{ @@ -261,6 +282,9 @@ func (s *service) ListReceivedOCMShares(ctx context.Context, req *ocm.ListReceiv } func (s *service) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateReceivedOCMShareRequest) (*ocm.UpdateReceivedOCMShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateReceivedOCMShare") + defer span.End() + _, err := s.sm.UpdateReceivedShare(ctx, req.Share, req.UpdateMask) // TODO(labkode): check what to update if err != nil { return &ocm.UpdateReceivedOCMShareResponse{ @@ -275,6 +299,9 @@ func (s *service) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateRec } func (s *service) GetReceivedOCMShare(ctx context.Context, req *ocm.GetReceivedOCMShareRequest) (*ocm.GetReceivedOCMShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetReceivedOCMShare") + defer span.End() + share, err := s.sm.GetReceivedShare(ctx, req.Ref) if err != nil { return &ocm.GetReceivedOCMShareResponse{ diff --git a/internal/grpc/services/permissions/permissions.go b/internal/grpc/services/permissions/permissions.go index 4479fdb88c..5dcd35c2cc 100644 --- a/internal/grpc/services/permissions/permissions.go +++ b/internal/grpc/services/permissions/permissions.go @@ -27,11 +27,14 @@ import ( "github.com/cs3org/reva/pkg/permission" "github.com/cs3org/reva/pkg/permission/manager/registry" "github.com/cs3org/reva/pkg/rgrpc" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const tracerName = "permissions" + func init() { rgrpc.Register("permissions", New) } @@ -51,6 +54,7 @@ func parseConfig(m map[string]interface{}) (*config, error) { } type service struct { + tracing.GrpcMiddleware manager permission.Manager } @@ -87,6 +91,9 @@ func (s *service) Register(ss *grpc.Server) { } func (s *service) CheckPermission(ctx context.Context, req *permissions.CheckPermissionRequest) (*permissions.CheckPermissionResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CheckPermission") + defer span.End() + var subject string switch ref := req.SubjectRef.Spec.(type) { case *permissions.SubjectReference_UserId: diff --git a/internal/grpc/services/preferences/preferences.go b/internal/grpc/services/preferences/preferences.go index 6920fc7069..e43aeb43b0 100644 --- a/internal/grpc/services/preferences/preferences.go +++ b/internal/grpc/services/preferences/preferences.go @@ -29,10 +29,13 @@ import ( "github.com/cs3org/reva/pkg/preferences/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) +const tracerName = "preferences" + func init() { rgrpc.Register("preferences", New) } @@ -49,6 +52,7 @@ func (c *config) init() { } type service struct { + tracing.GrpcMiddleware conf *config pm preferences.Manager } @@ -102,6 +106,9 @@ func (s *service) Register(ss *grpc.Server) { } func (s *service) SetKey(ctx context.Context, req *preferencespb.SetKeyRequest) (*preferencespb.SetKeyResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetKey") + defer span.End() + err := s.pm.SetKey(ctx, req.Key.Key, req.Key.Namespace, req.Val) if err != nil { return &preferencespb.SetKeyResponse{ @@ -115,6 +122,9 @@ func (s *service) SetKey(ctx context.Context, req *preferencespb.SetKeyRequest) } func (s *service) GetKey(ctx context.Context, req *preferencespb.GetKeyRequest) (*preferencespb.GetKeyResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetKey") + defer span.End() + val, err := s.pm.GetKey(ctx, req.Key.Key, req.Key.Namespace) if err != nil { st := status.NewInternal(ctx, err, "error retrieving key") diff --git a/internal/grpc/services/publicshareprovider/publicshareprovider.go b/internal/grpc/services/publicshareprovider/publicshareprovider.go index 192185e2a7..bd3b9732aa 100644 --- a/internal/grpc/services/publicshareprovider/publicshareprovider.go +++ b/internal/grpc/services/publicshareprovider/publicshareprovider.go @@ -31,11 +31,14 @@ import ( "github.com/cs3org/reva/pkg/publicshare/manager/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const tracerName = "publicshareprovider" + func init() { rgrpc.Register("publicshareprovider", New) } @@ -53,6 +56,7 @@ func (c *config) init() { } type service struct { + tracing.GrpcMiddleware conf *config sm publicshare.Manager allowedPathsForShares []*regexp.Regexp @@ -88,7 +92,6 @@ func parseConfig(m map[string]interface{}) (*config, error) { // New creates a new user share provider svc func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { - c, err := parseConfig(m) if err != nil { return nil, err @@ -132,6 +135,9 @@ func (s *service) isPathAllowed(path string) bool { } func (s *service) CreatePublicShare(ctx context.Context, req *link.CreatePublicShareRequest) (*link.CreatePublicShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreatePublicShare") + defer span.End() + log := appctx.GetLogger(ctx) log.Info().Str("publicshareprovider", "create").Msg("create public share") @@ -159,6 +165,9 @@ func (s *service) CreatePublicShare(ctx context.Context, req *link.CreatePublicS } func (s *service) RemovePublicShare(ctx context.Context, req *link.RemovePublicShareRequest) (*link.RemovePublicShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RemovePublicShare") + defer span.End() + log := appctx.GetLogger(ctx) log.Info().Str("publicshareprovider", "remove").Msg("remove public share") @@ -175,6 +184,9 @@ func (s *service) RemovePublicShare(ctx context.Context, req *link.RemovePublicS } func (s *service) GetPublicShareByToken(ctx context.Context, req *link.GetPublicShareByTokenRequest) (*link.GetPublicShareByTokenResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPublicShareByToken") + defer span.End() + log := appctx.GetLogger(ctx) log.Debug().Msg("getting public share by token") @@ -202,6 +214,9 @@ func (s *service) GetPublicShareByToken(ctx context.Context, req *link.GetPublic } func (s *service) GetPublicShare(ctx context.Context, req *link.GetPublicShareRequest) (*link.GetPublicShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPublicShare") + defer span.End() + log := appctx.GetLogger(ctx) log.Info().Str("publicshareprovider", "get").Msg("get public share") @@ -222,6 +237,9 @@ func (s *service) GetPublicShare(ctx context.Context, req *link.GetPublicShareRe } func (s *service) ListPublicShares(ctx context.Context, req *link.ListPublicSharesRequest) (*link.ListPublicSharesResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListPublicShares") + defer span.End() + log := appctx.GetLogger(ctx) log.Info().Str("publicshareprovider", "list").Msg("list public share") user, _ := ctxpkg.ContextGetUser(ctx) @@ -248,6 +266,9 @@ func (s *service) ListPublicShares(ctx context.Context, req *link.ListPublicShar } func (s *service) UpdatePublicShare(ctx context.Context, req *link.UpdatePublicShareRequest) (*link.UpdatePublicShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdatePublicShare") + defer span.End() + log := appctx.GetLogger(ctx) log.Info().Str("publicshareprovider", "update").Msg("update public share") diff --git a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go index 13c3d77969..b66994957f 100644 --- a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go +++ b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go @@ -34,16 +34,18 @@ import ( "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" - "go.opentelemetry.io/otel/attribute" "google.golang.org/grpc" "google.golang.org/grpc/codes" gstatus "google.golang.org/grpc/status" ) +const serviceName = "publicstorageprovider" +const tracerName = "publicstorageprovider" + func init() { rgrpc.Register("publicstorageprovider", New) } @@ -55,6 +57,7 @@ type config struct { } type service struct { + tracing.GrpcMiddleware conf *config mountPath string mountID string @@ -84,6 +87,9 @@ func parseConfig(m map[string]interface{}) (*config, error) { // New creates a new IsPublic Storage Provider service. func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { + ctx, span := tracing.SpanStart(context.Background(), serviceName, tracerName, "New") + defer span.End() + c, err := parseConfig(m) if err != nil { return nil, err @@ -92,7 +98,7 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { mountPath := c.MountPath mountID := c.MountID - gateway, err := pool.GetGatewayServiceClient(pool.Endpoint(c.GatewayAddr)) + gateway, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(c.GatewayAddr)) if err != nil { return nil, err } @@ -108,6 +114,9 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { } func (s *service) SetArbitraryMetadata(ctx context.Context, req *provider.SetArbitraryMetadataRequest) (*provider.SetArbitraryMetadataResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetArbitraryMetadata") + defer span.End() + ref, _, _, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) switch { case err != nil: @@ -121,30 +130,48 @@ func (s *service) SetArbitraryMetadata(ctx context.Context, req *provider.SetArb } func (s *service) UnsetArbitraryMetadata(ctx context.Context, req *provider.UnsetArbitraryMetadataRequest) (*provider.UnsetArbitraryMetadataResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UnsetArbitraryMetadata") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } // SetLock puts a lock on the given reference func (s *service) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provider.SetLockResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetLock") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } // GetLock returns an existing lock on the given reference func (s *service) GetLock(ctx context.Context, req *provider.GetLockRequest) (*provider.GetLockResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetLock") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } // RefreshLock refreshes an existing lock on the given reference func (s *service) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) (*provider.RefreshLockResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RefreshLock") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } // Unlock removes an existing lock from the given reference func (s *service) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provider.UnlockResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Unlock") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) InitiateFileDownload(ctx context.Context, req *provider.InitiateFileDownloadRequest) (*provider.InitiateFileDownloadResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "InitiateFileDownload") + defer span.End() + statReq := &provider.StatRequest{Ref: req.Ref} statRes, err := s.Stat(ctx, statReq) if err != nil { @@ -169,6 +196,9 @@ func (s *service) InitiateFileDownload(ctx context.Context, req *provider.Initia } func (s *service) translatePublicRefToCS3Ref(ctx context.Context, ref *provider.Reference) (*provider.Reference, string, *link.PublicShare, *rpc.Status, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "translatePublicRefToCS3Ref") + defer span.End() + log := appctx.GetLogger(ctx) tkn, relativePath, err := s.unwrap(ctx, ref) if err != nil { @@ -208,6 +238,9 @@ func (s *service) translatePublicRefToCS3Ref(ctx context.Context, ref *provider. // end = /einstein/files/public-links/foldera/folderb/ func (s *service) initiateFileDownload(ctx context.Context, req *provider.InitiateFileDownloadRequest) (*provider.InitiateFileDownloadResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "initiateFileDownload") + defer span.End() + cs3Ref, _, ls, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) switch { case err != nil: @@ -260,6 +293,9 @@ func (s *service) initiateFileDownload(ctx context.Context, req *provider.Initia } func (s *service) InitiateFileUpload(ctx context.Context, req *provider.InitiateFileUploadRequest) (*provider.InitiateFileUploadResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "InitiateFileUpload") + defer span.End() + cs3Ref, _, ls, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) switch { case err != nil: @@ -316,42 +352,58 @@ func (s *service) InitiateFileUpload(ctx context.Context, req *provider.Initiate } func (s *service) GetPath(ctx context.Context, req *provider.GetPathRequest) (*provider.GetPathResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPath") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) GetHome(ctx context.Context, req *provider.GetHomeRequest) (*provider.GetHomeResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetHome") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) CreateHome(ctx context.Context, req *provider.CreateHomeRequest) (*provider.CreateHomeResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateHome") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateStorageSpace") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStorageSpacesRequest) (*provider.ListStorageSpacesResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListStorageSpaces") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateStorageSpace") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorageSpaceRequest) (*provider.DeleteStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DeleteStorageSpace") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) CreateContainer(ctx context.Context, req *provider.CreateContainerRequest) (*provider.CreateContainerResponse, error) { - ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "CreateContainer") + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateContainer") defer span.End() - span.SetAttributes(attribute.KeyValue{ - Key: "reference", - Value: attribute.StringValue(req.Ref.String()), - }) - cs3Ref, _, ls, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) switch { case err != nil: @@ -384,6 +436,9 @@ func (s *service) CreateContainer(ctx context.Context, req *provider.CreateConta } func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*provider.TouchFileResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "TouchFile") + defer span.End() + ref, _, _, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) switch { case err != nil: @@ -397,14 +452,9 @@ func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) } func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) { - ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "Delete") + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Delete") defer span.End() - span.SetAttributes(attribute.KeyValue{ - Key: "reference", - Value: attribute.StringValue(req.Ref.String()), - }) - cs3Ref, _, ls, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) switch { case err != nil: @@ -437,20 +487,9 @@ func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*pro } func (s *service) Move(ctx context.Context, req *provider.MoveRequest) (*provider.MoveResponse, error) { - ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "Move") + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Move") defer span.End() - span.SetAttributes( - attribute.KeyValue{ - Key: "source", - Value: attribute.StringValue(req.Source.String()), - }, - attribute.KeyValue{ - Key: "destination", - Value: attribute.StringValue(req.Destination.String()), - }, - ) - cs3RefSource, tknSource, ls, st, err := s.translatePublicRefToCS3Ref(ctx, req.Source) switch { case err != nil: @@ -500,15 +539,9 @@ func (s *service) Move(ctx context.Context, req *provider.MoveRequest) (*provide } func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) { - ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "Stat") + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Stat") defer span.End() - span.SetAttributes( - attribute.KeyValue{ - Key: "source", - Value: attribute.StringValue(req.Ref.String()), - }) - var ( tkn string relativePath string @@ -576,6 +609,9 @@ func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provide } func (s *service) augmentStatResponse(ctx context.Context, res *provider.StatResponse, shareInfo *provider.ResourceInfo, share *link.PublicShare, tkn string) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "augmentStatResponse") + defer span.End() + // prevent leaking internal paths if res.Info != nil { if err := addShare(res.Info, share); err != nil { @@ -622,6 +658,9 @@ func (s *service) ListContainerStream(req *provider.ListContainerStreamRequest, } func (s *service) ListContainer(ctx context.Context, req *provider.ListContainerRequest) (*provider.ListContainerResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListContainer") + defer span.End() + tkn, relativePath, err := s.unwrap(ctx, req.Ref) if err != nil { return nil, err @@ -686,6 +725,9 @@ func filterPermissions(l *provider.ResourcePermissions, r *provider.ResourcePerm } func (s *service) unwrap(ctx context.Context, ref *provider.Reference) (token string, relativePath string, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "unwrap") + defer span.End() + if ref.ResourceId != nil { return "", "", errtypes.BadRequest("need absolute path ref: got " + ref.String()) } @@ -713,58 +755,98 @@ func (s *service) unwrap(ctx context.Context, ref *provider.Reference) (token st } func (s *service) ListFileVersions(ctx context.Context, req *provider.ListFileVersionsRequest) (*provider.ListFileVersionsResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListFileVersions") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) RestoreFileVersion(ctx context.Context, req *provider.RestoreFileVersionRequest) (*provider.RestoreFileVersionResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreFileVersion") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) ListRecycleStream(req *provider.ListRecycleStreamRequest, ss provider.ProviderAPI_ListRecycleStreamServer) error { + return gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) ListRecycle(ctx context.Context, req *provider.ListRecycleRequest) (*provider.ListRecycleResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListRecycle") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) RestoreRecycleItem(ctx context.Context, req *provider.RestoreRecycleItemRequest) (*provider.RestoreRecycleItemResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreRecycleItem") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) PurgeRecycle(ctx context.Context, req *provider.PurgeRecycleRequest) (*provider.PurgeRecycleResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "PurgeRecycle") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) ListGrants(ctx context.Context, req *provider.ListGrantsRequest) (*provider.ListGrantsResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListGrants") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) AddGrant(ctx context.Context, req *provider.AddGrantRequest) (*provider.AddGrantResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "AddGrant") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) DenyGrant(ctx context.Context, req *provider.DenyGrantRequest) (*provider.DenyGrantResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DenyGrant") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) CreateReference(ctx context.Context, req *provider.CreateReferenceRequest) (*provider.CreateReferenceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateReference") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) CreateSymlink(ctx context.Context, req *provider.CreateSymlinkRequest) (*provider.CreateSymlinkResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateSymlink") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) UpdateGrant(ctx context.Context, req *provider.UpdateGrantRequest) (*provider.UpdateGrantResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateGrant") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) RemoveGrant(ctx context.Context, req *provider.RemoveGrantRequest) (*provider.RemoveGrantResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RemoveGrant") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } func (s *service) GetQuota(ctx context.Context, req *provider.GetQuotaRequest) (*provider.GetQuotaResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetQuota") + defer span.End() + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } @@ -777,7 +859,10 @@ func (s *service) trimMountPrefix(fn string) (string, error) { // resolveToken returns the path and share for the publicly shared resource. func (s *service) resolveToken(ctx context.Context, token string) (*link.PublicShare, *provider.ResourceInfo, *rpc.Status, error) { - driver, err := pool.GetGatewayServiceClient(pool.Endpoint(s.conf.GatewayAddr)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "resolveToken") + defer span.End() + + driver, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(s.conf.GatewayAddr)) if err != nil { return nil, nil, nil, err } diff --git a/internal/grpc/services/storageprovider/storageprovider.go b/internal/grpc/services/storageprovider/storageprovider.go index d4e6ccf211..c2fc2f0dc6 100644 --- a/internal/grpc/services/storageprovider/storageprovider.go +++ b/internal/grpc/services/storageprovider/storageprovider.go @@ -41,17 +41,19 @@ import ( "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/google/uuid" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" - "go.opentelemetry.io/otel/attribute" "google.golang.org/grpc" ) +const serviceName = "storageprovider" +const tracerName = "storageprovider" + func init() { - rgrpc.Register("storageprovider", New) + rgrpc.Register(serviceName, New) } type config struct { @@ -99,6 +101,7 @@ func (c *config) init() { } type service struct { + tracing.GrpcMiddleware conf *config storage storage.FS mountPath, mountID string @@ -163,7 +166,6 @@ func registerMimeTypes(mappingFile string) error { // New creates a new storage provider svc func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { - c, err := parseConfig(m) if err != nil { return nil, err @@ -219,6 +221,9 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { } func (s *service) SetArbitraryMetadata(ctx context.Context, req *provider.SetArbitraryMetadataRequest) (*provider.SetArbitraryMetadataResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetArbitraryMetadata") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { err := errors.Wrap(err, "storageprovidersvc: error unwrapping path") @@ -249,6 +254,9 @@ func (s *service) SetArbitraryMetadata(ctx context.Context, req *provider.SetArb } func (s *service) UnsetArbitraryMetadata(ctx context.Context, req *provider.UnsetArbitraryMetadataRequest) (*provider.UnsetArbitraryMetadataResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UnsetArbitraryMetadata") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { err := errors.Wrap(err, "storageprovidersvc: error unwrapping path") @@ -280,6 +288,9 @@ func (s *service) UnsetArbitraryMetadata(ctx context.Context, req *provider.Unse // SetLock puts a lock on the given reference func (s *service) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provider.SetLockResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetLock") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { err := errors.Wrap(err, "storageprovidersvc: error unwrapping path") @@ -313,6 +324,9 @@ func (s *service) SetLock(ctx context.Context, req *provider.SetLockRequest) (*p // GetLock returns an existing lock on the given reference func (s *service) GetLock(ctx context.Context, req *provider.GetLockRequest) (*provider.GetLockResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetLock") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { err := errors.Wrap(err, "storageprovidersvc: error unwrapping path") @@ -346,6 +360,9 @@ func (s *service) GetLock(ctx context.Context, req *provider.GetLockRequest) (*p // RefreshLock refreshes an existing lock on the given reference func (s *service) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) (*provider.RefreshLockResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RefreshLock") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { err := errors.Wrap(err, "storageprovidersvc: error unwrapping path") @@ -379,6 +396,9 @@ func (s *service) RefreshLock(ctx context.Context, req *provider.RefreshLockRequ // Unlock removes an existing lock from the given reference func (s *service) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provider.UnlockResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Unlock") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { err := errors.Wrap(err, "storageprovidersvc: error unwrapping path") @@ -411,6 +431,9 @@ func (s *service) Unlock(ctx context.Context, req *provider.UnlockRequest) (*pro } func (s *service) InitiateFileDownload(ctx context.Context, req *provider.InitiateFileDownloadRequest) (*provider.InitiateFileDownloadResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "InitiateFileDownload") + defer span.End() + // TODO(labkode): maybe add some checks before download starts? eg. check permissions? // TODO(labkode): maybe add short-lived token? // We now simply point the client to the data server. @@ -447,6 +470,9 @@ func (s *service) InitiateFileDownload(ctx context.Context, req *provider.Initia } func (s *service) InitiateFileUpload(ctx context.Context, req *provider.InitiateFileUploadRequest) (*provider.InitiateFileUploadResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "InitiateFileUpload") + defer span.End() + // TODO(labkode): same considerations as download log := appctx.GetLogger(ctx) newRef, err := s.unwrap(ctx, req.Ref) @@ -537,6 +563,9 @@ func (s *service) InitiateFileUpload(ctx context.Context, req *provider.Initiate } func (s *service) GetPath(ctx context.Context, req *provider.GetPathRequest) (*provider.GetPathResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPath") + defer span.End() + // TODO(labkode): check that the storage ID is the same as the storage provider id. fn, err := s.storage.GetPathByID(ctx, req.ResourceId) if err != nil { @@ -554,6 +583,9 @@ func (s *service) GetPath(ctx context.Context, req *provider.GetPathRequest) (*p } func (s *service) GetHome(ctx context.Context, req *provider.GetHomeRequest) (*provider.GetHomeResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetHome") + defer span.End() + home := path.Join(s.mountPath) res := &provider.GetHomeResponse{ @@ -565,6 +597,9 @@ func (s *service) GetHome(ctx context.Context, req *provider.GetHomeRequest) (*p } func (s *service) CreateHome(ctx context.Context, req *provider.CreateHomeRequest) (*provider.CreateHomeResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateHome") + defer span.End() + log := appctx.GetLogger(ctx) if err := s.storage.CreateHome(ctx); err != nil { st := status.NewInternal(ctx, err, "error creating home") @@ -582,6 +617,9 @@ func (s *service) CreateHome(ctx context.Context, req *provider.CreateHomeReques // CreateStorageSpace creates a storage space func (s *service) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateStorageSpace") + defer span.End() + resp, err := s.storage.CreateStorageSpace(ctx, req) if err != nil { return nil, err @@ -597,6 +635,9 @@ func hasNodeID(s *provider.StorageSpace) bool { } func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStorageSpacesRequest) (*provider.ListStorageSpacesResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListStorageSpaces") + defer span.End() + log := appctx.GetLogger(ctx) spaces, err := s.storage.ListStorageSpaces(ctx, req.Filters) @@ -639,16 +680,25 @@ func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStora } func (s *service) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateStorageSpace") + defer span.End() + return s.storage.UpdateStorageSpace(ctx, req) } func (s *service) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorageSpaceRequest) (*provider.DeleteStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DeleteStorageSpace") + defer span.End() + return &provider.DeleteStorageSpaceResponse{ Status: status.NewUnimplemented(ctx, errtypes.NotSupported("DeleteStorageSpace not implemented"), "DeleteStorageSpace not implemented"), }, nil } func (s *service) CreateContainer(ctx context.Context, req *provider.CreateContainerRequest) (*provider.CreateContainerResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateContainer") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { return &provider.CreateContainerResponse{ @@ -679,6 +729,9 @@ func (s *service) CreateContainer(ctx context.Context, req *provider.CreateConta } func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*provider.TouchFileResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "TouchFile") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { return &provider.TouchFileResponse{ @@ -709,6 +762,9 @@ func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) } func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Delete") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { return &provider.DeleteResponse{ @@ -752,6 +808,9 @@ func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*pro } func (s *service) Move(ctx context.Context, req *provider.MoveRequest) (*provider.MoveResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Move") + defer span.End() + sourceRef, err := s.unwrap(ctx, req.Source) if err != nil { return &provider.MoveResponse{ @@ -787,14 +846,9 @@ func (s *service) Move(ctx context.Context, req *provider.MoveRequest) (*provide } func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) { - ctx, span := rtrace.Provider.Tracer("reva").Start(ctx, "stat") + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Stat") defer span.End() - span.SetAttributes(attribute.KeyValue{ - Key: "reference", - Value: attribute.StringValue(req.Ref.String()), - }) - newRef, err := s.unwrap(ctx, req.Ref) if err != nil { // The path might be a virtual view; handle that case @@ -832,6 +886,9 @@ func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provide } func (s *service) statVirtualView(ctx context.Context, ref *provider.Reference) (*provider.StatResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "statVirtualView") + defer span.End() + // The reference in the request encompasses this provider // So we need to stat root, and update the required path md, err := s.storage.GetMD(ctx, &provider.Reference{Path: "/"}, []string{}) @@ -867,6 +924,10 @@ func (s *service) statVirtualView(ctx context.Context, ref *provider.Reference) func (s *service) ListContainerStream(req *provider.ListContainerStreamRequest, ss provider.ProviderAPI_ListContainerStreamServer) error { ctx := ss.Context() + + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListContainerStream") + defer span.End() + log := appctx.GetLogger(ctx) newRef, err := s.unwrap(ctx, req.Ref) @@ -928,6 +989,9 @@ func (s *service) ListContainerStream(req *provider.ListContainerStreamRequest, } func (s *service) ListContainer(ctx context.Context, req *provider.ListContainerRequest) (*provider.ListContainerResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListContainer") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { // The path might be a virtual view; handle that case @@ -974,6 +1038,9 @@ func (s *service) ListContainer(ctx context.Context, req *provider.ListContainer } func (s *service) listVirtualView(ctx context.Context, ref *provider.Reference) (*provider.ListContainerResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listVirtualView") + defer span.End() + // The reference in the request encompasses this provider // So we need to list root, merge the responses and return only the immediate children mds, err := s.storage.ListFolder(ctx, &provider.Reference{Path: "/"}, []string{}) @@ -1049,6 +1116,9 @@ func (s *service) listVirtualView(ctx context.Context, ref *provider.Reference) } func (s *service) ListFileVersions(ctx context.Context, req *provider.ListFileVersionsRequest) (*provider.ListFileVersionsResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListFileVersions") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { return &provider.ListFileVersionsResponse{ @@ -1082,6 +1152,9 @@ func (s *service) ListFileVersions(ctx context.Context, req *provider.ListFileVe } func (s *service) RestoreFileVersion(ctx context.Context, req *provider.RestoreFileVersionRequest) (*provider.RestoreFileVersionResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreFileVersion") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { return &provider.RestoreFileVersionResponse{ @@ -1112,6 +1185,9 @@ func (s *service) RestoreFileVersion(ctx context.Context, req *provider.RestoreF func (s *service) ListRecycleStream(req *provider.ListRecycleStreamRequest, ss provider.ProviderAPI_ListRecycleStreamServer) error { ctx := ss.Context() + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListRecycleStream") + defer span.End() + log := appctx.GetLogger(ctx) ref, err := s.unwrap(ctx, req.Ref) @@ -1156,6 +1232,9 @@ func (s *service) ListRecycleStream(req *provider.ListRecycleStreamRequest, ss p } func (s *service) ListRecycle(ctx context.Context, req *provider.ListRecycleRequest) (*provider.ListRecycleResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListRecycle") + defer span.End() + ref, err := s.unwrap(ctx, req.Ref) if err != nil { return nil, err @@ -1195,6 +1274,9 @@ func (s *service) ListRecycle(ctx context.Context, req *provider.ListRecycleRequ } func (s *service) RestoreRecycleItem(ctx context.Context, req *provider.RestoreRecycleItemRequest) (*provider.RestoreRecycleItemResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreRecycleItem") + defer span.End() + // TODO(labkode): CRITICAL: fill recycle info with storage provider. ref, err := s.unwrap(ctx, req.Ref) if err != nil { @@ -1223,6 +1305,9 @@ func (s *service) RestoreRecycleItem(ctx context.Context, req *provider.RestoreR } func (s *service) PurgeRecycle(ctx context.Context, req *provider.PurgeRecycleRequest) (*provider.PurgeRecycleResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "PurgeRecycle") + defer span.End() + ref, err := s.unwrap(ctx, req.Ref) if err != nil { return nil, err @@ -1267,6 +1352,9 @@ func (s *service) PurgeRecycle(ctx context.Context, req *provider.PurgeRecycleRe } func (s *service) ListGrants(ctx context.Context, req *provider.ListGrantsRequest) (*provider.ListGrantsResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListGrants") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { return &provider.ListGrantsResponse{ @@ -1298,6 +1386,9 @@ func (s *service) ListGrants(ctx context.Context, req *provider.ListGrantsReques } func (s *service) DenyGrant(ctx context.Context, req *provider.DenyGrantRequest) (*provider.DenyGrantResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DenyGrant") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { return &provider.DenyGrantResponse{ @@ -1335,6 +1426,9 @@ func (s *service) DenyGrant(ctx context.Context, req *provider.DenyGrantRequest) } func (s *service) AddGrant(ctx context.Context, req *provider.AddGrantRequest) (*provider.AddGrantResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "AddGrant") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { return &provider.AddGrantResponse{ @@ -1372,6 +1466,9 @@ func (s *service) AddGrant(ctx context.Context, req *provider.AddGrantRequest) ( } func (s *service) UpdateGrant(ctx context.Context, req *provider.UpdateGrantRequest) (*provider.UpdateGrantResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateGrant") + defer span.End() + // check grantee type is valid if req.Grant.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_INVALID { return &provider.UpdateGrantResponse{ @@ -1408,6 +1505,9 @@ func (s *service) UpdateGrant(ctx context.Context, req *provider.UpdateGrantRequ } func (s *service) RemoveGrant(ctx context.Context, req *provider.RemoveGrantRequest) (*provider.RemoveGrantResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RemoveGrant") + defer span.End() + // check targetType is valid if req.Grant.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_INVALID { return &provider.RemoveGrantResponse{ @@ -1444,6 +1544,9 @@ func (s *service) RemoveGrant(ctx context.Context, req *provider.RemoveGrantRequ } func (s *service) CreateReference(ctx context.Context, req *provider.CreateReferenceRequest) (*provider.CreateReferenceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateReference") + defer span.End() + log := appctx.GetLogger(ctx) // parse uri is valid @@ -1484,12 +1587,18 @@ func (s *service) CreateReference(ctx context.Context, req *provider.CreateRefer } func (s *service) CreateSymlink(ctx context.Context, req *provider.CreateSymlinkRequest) (*provider.CreateSymlinkResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateSymlink") + defer span.End() + return &provider.CreateSymlinkResponse{ Status: status.NewUnimplemented(ctx, errtypes.NotSupported("CreateSymlink not implemented"), "CreateSymlink not implemented"), }, nil } func (s *service) GetQuota(ctx context.Context, req *provider.GetQuotaRequest) (*provider.GetQuotaResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetQuota") + defer span.End() + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { return &provider.GetQuotaResponse{ @@ -1528,6 +1637,9 @@ func getFS(c *config) (storage.FS, error) { } func (s *service) unwrap(ctx context.Context, ref *provider.Reference) (*provider.Reference, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "unwrap") + defer span.End() + // all references with an id can be passed on to the driver // there are two cases: // 1. absolute id references (resource_id is set, path is empty) @@ -1557,6 +1669,9 @@ func (s *service) trimMountPrefix(fn string) (string, error) { } func (s *service) wrap(ctx context.Context, ri *provider.ResourceInfo, prefixMountpoint bool) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "wrap") + defer span.End() + if ri.Id.StorageId == "" { // For wrapper drivers, the storage ID might already be set. In that case, skip setting it ri.Id.StorageId = s.mountID @@ -1569,6 +1684,9 @@ func (s *service) wrap(ctx context.Context, ri *provider.ResourceInfo, prefixMou } func (s *service) wrapReference(ctx context.Context, ref *provider.Reference, prefixMountpoint bool) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "wrapReference") + defer span.End() + if ref.ResourceId != nil && ref.ResourceId.StorageId == "" { // For wrapper drivers, the storage ID might already be set. In that case, skip setting it ref.ResourceId.StorageId = s.mountID diff --git a/internal/grpc/services/storageregistry/storageregistry.go b/internal/grpc/services/storageregistry/storageregistry.go index 4f59ae5649..57206619a7 100644 --- a/internal/grpc/services/storageregistry/storageregistry.go +++ b/internal/grpc/services/storageregistry/storageregistry.go @@ -28,15 +28,20 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/registry/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "google.golang.org/grpc" ) +const serviceName = "storageregistry" +const tracerName = "storageregistry" + func init() { - rgrpc.Register("storageregistry", New) + rgrpc.Register(serviceName, New) } type service struct { + tracing.GrpcMiddleware reg storage.Registry } @@ -100,6 +105,9 @@ func getRegistry(c *config) (storage.Registry, error) { } func (s *service) ListStorageProviders(ctx context.Context, req *registrypb.ListStorageProvidersRequest) (*registrypb.ListStorageProvidersResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListStorageProviders") + defer span.End() + pinfos, err := s.reg.ListProviders(ctx) if err != nil { return ®istrypb.ListStorageProvidersResponse{ @@ -115,6 +123,9 @@ func (s *service) ListStorageProviders(ctx context.Context, req *registrypb.List } func (s *service) GetStorageProviders(ctx context.Context, req *registrypb.GetStorageProvidersRequest) (*registrypb.GetStorageProvidersResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetStorageProviders") + defer span.End() + p, err := s.reg.FindProviders(ctx, req.Ref) if err != nil { switch err.(type) { @@ -137,6 +148,9 @@ func (s *service) GetStorageProviders(ctx context.Context, req *registrypb.GetSt } func (s *service) GetHome(ctx context.Context, req *registrypb.GetHomeRequest) (*registrypb.GetHomeResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetHome") + defer span.End() + log := appctx.GetLogger(ctx) p, err := s.reg.GetHome(ctx) if err != nil { diff --git a/internal/grpc/services/userprovider/userprovider.go b/internal/grpc/services/userprovider/userprovider.go index f9e8bc2bd5..cfe5bc13e0 100644 --- a/internal/grpc/services/userprovider/userprovider.go +++ b/internal/grpc/services/userprovider/userprovider.go @@ -29,6 +29,7 @@ import ( "github.com/cs3org/reva/pkg/plugin" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/user" "github.com/cs3org/reva/pkg/user/manager/registry" "github.com/mitchellh/mapstructure" @@ -36,6 +37,8 @@ import ( "google.golang.org/grpc" ) +const tracerName = "userprovider" + func init() { rgrpc.Register("userprovider", New) } @@ -105,6 +108,7 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { } type service struct { + tracing.GrpcMiddleware usermgr user.Manager plugin *plugin.RevaPlugin } @@ -125,6 +129,9 @@ func (s *service) Register(ss *grpc.Server) { } func (s *service) GetUser(ctx context.Context, req *userpb.GetUserRequest) (*userpb.GetUserResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetUser") + defer span.End() + user, err := s.usermgr.GetUser(ctx, req.UserId, req.SkipFetchingUserGroups) if err != nil { res := &userpb.GetUserResponse{} @@ -145,6 +152,9 @@ func (s *service) GetUser(ctx context.Context, req *userpb.GetUserRequest) (*use } func (s *service) GetUserByClaim(ctx context.Context, req *userpb.GetUserByClaimRequest) (*userpb.GetUserByClaimResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetUserByClaim") + defer span.End() + user, err := s.usermgr.GetUserByClaim(ctx, req.Claim, req.Value, req.SkipFetchingUserGroups) if err != nil { res := &userpb.GetUserByClaimResponse{} @@ -165,6 +175,9 @@ func (s *service) GetUserByClaim(ctx context.Context, req *userpb.GetUserByClaim } func (s *service) FindUsers(ctx context.Context, req *userpb.FindUsersRequest) (*userpb.FindUsersResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "FindUsers") + defer span.End() + users, err := s.usermgr.FindUsers(ctx, req.Filter, req.SkipFetchingUserGroups) if err != nil { err = errors.Wrap(err, "userprovidersvc: error finding users") @@ -187,6 +200,9 @@ func (s *service) FindUsers(ctx context.Context, req *userpb.FindUsersRequest) ( } func (s *service) GetUserGroups(ctx context.Context, req *userpb.GetUserGroupsRequest) (*userpb.GetUserGroupsResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetUserGroups") + defer span.End() + groups, err := s.usermgr.GetUserGroups(ctx, req.UserId) if err != nil { err = errors.Wrap(err, "userprovidersvc: error getting user groups") diff --git a/internal/grpc/services/usershareprovider/usershareprovider.go b/internal/grpc/services/usershareprovider/usershareprovider.go index 42573cfd17..496538459a 100644 --- a/internal/grpc/services/usershareprovider/usershareprovider.go +++ b/internal/grpc/services/usershareprovider/usershareprovider.go @@ -32,11 +32,14 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/share" "github.com/cs3org/reva/pkg/share/manager/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc" ) +const tracerName = "usershareprovider" + func init() { rgrpc.Register("usershareprovider", New) } @@ -54,6 +57,7 @@ func (c *config) init() { } type service struct { + tracing.GrpcMiddleware conf *config sm share.Manager allowedPathsForShares []*regexp.Regexp @@ -90,7 +94,6 @@ func parseConfig(m map[string]interface{}) (*config, error) { // New creates a new user share provider svc func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { - c, err := parseConfig(m) if err != nil { return nil, err @@ -134,6 +137,9 @@ func (s *service) isPathAllowed(path string) bool { } func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShareRequest) (*collaboration.CreateShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateShare") + defer span.End() + u := ctxpkg.ContextMustGetUser(ctx) if req.Grant.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_USER && req.Grant.Grantee.GetUserId().Idp == "" { // use logged in user Idp as default. @@ -162,6 +168,9 @@ func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShar } func (s *service) RemoveShare(ctx context.Context, req *collaboration.RemoveShareRequest) (*collaboration.RemoveShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RemoveShare") + defer span.End() + err := s.sm.Unshare(ctx, req.Ref) if err != nil { return &collaboration.RemoveShareResponse{ @@ -175,6 +184,9 @@ func (s *service) RemoveShare(ctx context.Context, req *collaboration.RemoveShar } func (s *service) GetShare(ctx context.Context, req *collaboration.GetShareRequest) (*collaboration.GetShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetShare") + defer span.End() + share, err := s.sm.GetShare(ctx, req.Ref) if err != nil { return &collaboration.GetShareResponse{ @@ -189,6 +201,9 @@ func (s *service) GetShare(ctx context.Context, req *collaboration.GetShareReque } func (s *service) ListShares(ctx context.Context, req *collaboration.ListSharesRequest) (*collaboration.ListSharesResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListShares") + defer span.End() + if req.Opaque != nil { if v, ok := req.Opaque.Map[ctxpkg.ResoucePathCtx]; ok { ctx = ctxpkg.ContextSetResourcePath(ctx, string(v.Value)) @@ -210,6 +225,9 @@ func (s *service) ListShares(ctx context.Context, req *collaboration.ListSharesR } func (s *service) UpdateShare(ctx context.Context, req *collaboration.UpdateShareRequest) (*collaboration.UpdateShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateShare") + defer span.End() + share, err := s.sm.UpdateShare(ctx, req.Ref, req.Field.GetPermissions()) // TODO(labkode): check what to update if err != nil { return &collaboration.UpdateShareResponse{ @@ -225,6 +243,9 @@ func (s *service) UpdateShare(ctx context.Context, req *collaboration.UpdateShar } func (s *service) ListReceivedShares(ctx context.Context, req *collaboration.ListReceivedSharesRequest) (*collaboration.ListReceivedSharesResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListReceivedShares") + defer span.End() + // For the UI add a filter to not display the denial shares foundExclude := false for _, f := range req.Filters { @@ -251,6 +272,9 @@ func (s *service) ListReceivedShares(ctx context.Context, req *collaboration.Lis } func (s *service) GetReceivedShare(ctx context.Context, req *collaboration.GetReceivedShareRequest) (*collaboration.GetReceivedShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetReceivedShare") + defer span.End() + log := appctx.GetLogger(ctx) share, err := s.sm.GetReceivedShare(ctx, req.Ref) @@ -269,6 +293,9 @@ func (s *service) GetReceivedShare(ctx context.Context, req *collaboration.GetRe } func (s *service) UpdateReceivedShare(ctx context.Context, req *collaboration.UpdateReceivedShareRequest) (*collaboration.UpdateReceivedShareResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateReceivedShare") + defer span.End() + share, err := s.sm.UpdateReceivedShare(ctx, req.Share, req.UpdateMask) // TODO(labkode): check what to update if err != nil { return &collaboration.UpdateReceivedShareResponse{ diff --git a/internal/http/interceptors/appctx/appctx.go b/internal/http/interceptors/appctx/appctx.go index 9d34a78981..4345c060ea 100644 --- a/internal/http/interceptors/appctx/appctx.go +++ b/internal/http/interceptors/appctx/appctx.go @@ -25,11 +25,12 @@ import ( "net/http" "github.com/cs3org/reva/pkg/appctx" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/rs/zerolog" - "go.opentelemetry.io/otel/trace" ) +const tracerName = "appctx" + // New returns a new HTTP middleware that stores the log // in the context with request ID information. func New(log zerolog.Logger) func(http.Handler) http.Handler { @@ -42,14 +43,11 @@ func New(log zerolog.Logger) func(http.Handler) http.Handler { func handler(log zerolog.Logger, h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - span := trace.SpanFromContext(ctx) + r, span := tracing.SpanStartFromRequest(r, tracerName, "appctx Interceptor HTTP Handler") defer span.End() - if !span.SpanContext().HasTraceID() { - ctx, span = rtrace.Provider.Tracer("http").Start(ctx, "http interceptor") - } - sub := log.With().Str("traceid", span.SpanContext().TraceID().String()).Logger() + ctx := r.Context() + sub := log.With().Str("TraceID", span.SpanContext().TraceID().String()).Logger() ctx = appctx.WithLogger(ctx, &sub) r = r.WithContext(ctx) h.ServeHTTP(w, r) diff --git a/internal/http/interceptors/auth/auth.go b/internal/http/interceptors/auth/auth.go index 3348e07947..c56d50c369 100644 --- a/internal/http/interceptors/auth/auth.go +++ b/internal/http/interceptors/auth/auth.go @@ -43,13 +43,17 @@ import ( "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/token" tokenmgr "github.com/cs3org/reva/pkg/token/manager/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/rs/zerolog" + semconv "go.opentelemetry.io/otel/semconv/v1.4.0" "google.golang.org/grpc/metadata" ) +const tracerName = "auth" + var userGroupsCache gcache.Cache type config struct { @@ -155,6 +159,9 @@ func New(m map[string]interface{}, unprotected []string) (global.Middleware, err chain := func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "auth Interceptor HTTP Handler") + defer span.End() + // OPTION requests need to pass for preflight requests // TODO(labkode): this will break options for auth protected routes. // Maybe running the CORS middleware before auth kicks in is enough. @@ -188,13 +195,16 @@ func New(m map[string]interface{}, unprotected []string) (global.Middleware, err } func authenticateUser(w http.ResponseWriter, r *http.Request, conf *config, tokenStrategy auth.TokenStrategy, tokenManager token.Manager, tokenWriter auth.TokenWriter, credChain map[string]auth.CredentialStrategy, isUnprotectedEndpoint bool) (context.Context, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "authenticateUser") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) // Add the request user-agent to the ctx ctx = metadata.NewIncomingContext(ctx, metadata.New(map[string]string{ctxpkg.UserAgentHeader: r.UserAgent()})) - client, err := pool.GetGatewayServiceClient(pool.Endpoint(conf.GatewaySvc)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(conf.GatewaySvc)) if err != nil { logError(isUnprotectedEndpoint, log, err, "error getting the authsvc client", http.StatusUnauthorized, w) return nil, err @@ -281,6 +291,8 @@ func authenticateUser(w http.ResponseWriter, r *http.Request, conf *config, toke return nil, err } + span.SetAttributes(semconv.EnduserIDKey.String(u.Username)) + // ensure access to the resource is allowed ok, err := scope.VerifyScope(ctx, tokenScope, r.URL.Path) if err != nil { diff --git a/internal/http/interceptors/auth/credential/strategy/basic/basic.go b/internal/http/interceptors/auth/credential/strategy/basic/basic.go index ab41523981..732d5fa753 100644 --- a/internal/http/interceptors/auth/credential/strategy/basic/basic.go +++ b/internal/http/interceptors/auth/credential/strategy/basic/basic.go @@ -24,8 +24,11 @@ import ( "github.com/cs3org/reva/internal/http/interceptors/auth/credential/registry" "github.com/cs3org/reva/pkg/auth" + "github.com/cs3org/reva/pkg/tracing" ) +const tracerName = "basic" + func init() { registry.Register("basic", New) } @@ -39,6 +42,9 @@ func New(m map[string]interface{}) (auth.CredentialStrategy, error) { } func (s *strategy) GetCredentials(w http.ResponseWriter, r *http.Request) (*auth.Credentials, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "GetCredentials") + defer span.End() + id, secret, ok := r.BasicAuth() if !ok { return nil, fmt.Errorf("no basic auth provided") @@ -47,6 +53,9 @@ func (s *strategy) GetCredentials(w http.ResponseWriter, r *http.Request) (*auth } func (s *strategy) AddWWWAuthenticate(w http.ResponseWriter, r *http.Request, realm string) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "AddWWWAuthenticate") + defer span.End() + // TODO read realm from forwarded header? if realm == "" { // fall back to hostname if not configured diff --git a/internal/http/interceptors/auth/credential/strategy/bearer/bearer.go b/internal/http/interceptors/auth/credential/strategy/bearer/bearer.go index 713aa46396..b17a7a8f1c 100644 --- a/internal/http/interceptors/auth/credential/strategy/bearer/bearer.go +++ b/internal/http/interceptors/auth/credential/strategy/bearer/bearer.go @@ -25,8 +25,11 @@ import ( "github.com/cs3org/reva/internal/http/interceptors/auth/credential/registry" "github.com/cs3org/reva/pkg/auth" + "github.com/cs3org/reva/pkg/tracing" ) +const tracerName = "bearer" + func init() { registry.Register("bearer", New) } @@ -40,6 +43,9 @@ func New(m map[string]interface{}) (auth.CredentialStrategy, error) { } func (s *strategy) GetCredentials(w http.ResponseWriter, r *http.Request) (*auth.Credentials, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "GetCredentials") + defer span.End() + // 1. check Authorization header hdr := r.Header.Get("Authorization") token := strings.TrimPrefix(hdr, "Bearer ") @@ -58,6 +64,9 @@ func (s *strategy) GetCredentials(w http.ResponseWriter, r *http.Request) (*auth } func (s *strategy) AddWWWAuthenticate(w http.ResponseWriter, r *http.Request, realm string) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "AddWWWAuthenticate") + defer span.End() + // TODO read realm from forwarded header? if realm == "" { // fall back to hostname if not configured diff --git a/internal/http/interceptors/auth/credential/strategy/publicshares/publicshares.go b/internal/http/interceptors/auth/credential/strategy/publicshares/publicshares.go index e39289dfd0..9a594f69d9 100644 --- a/internal/http/interceptors/auth/credential/strategy/publicshares/publicshares.go +++ b/internal/http/interceptors/auth/credential/strategy/publicshares/publicshares.go @@ -24,8 +24,11 @@ import ( "github.com/cs3org/reva/internal/http/interceptors/auth/credential/registry" "github.com/cs3org/reva/pkg/auth" + "github.com/cs3org/reva/pkg/tracing" ) +const tracerName = "publicshares" + func init() { registry.Register("publicshares", New) } @@ -43,6 +46,9 @@ func New(m map[string]interface{}) (auth.CredentialStrategy, error) { } func (s *strategy) GetCredentials(w http.ResponseWriter, r *http.Request) (*auth.Credentials, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "GetCredentials") + defer span.End() + token := r.Header.Get(headerShareToken) if token == "" { token = r.URL.Query().Get(headerShareToken) @@ -61,5 +67,7 @@ func (s *strategy) GetCredentials(w http.ResponseWriter, r *http.Request) (*auth } func (s *strategy) AddWWWAuthenticate(w http.ResponseWriter, r *http.Request, realm string) { + _, span := tracing.SpanStartFromRequest(r, tracerName, "AddWWWAuthenticate") + defer span.End() // TODO read realm from forwarded header? } diff --git a/internal/http/interceptors/auth/token/strategy/header/header.go b/internal/http/interceptors/auth/token/strategy/header/header.go index 4cf6974f29..646e56d69b 100644 --- a/internal/http/interceptors/auth/token/strategy/header/header.go +++ b/internal/http/interceptors/auth/token/strategy/header/header.go @@ -24,8 +24,11 @@ import ( "github.com/cs3org/reva/internal/http/interceptors/auth/token/registry" "github.com/cs3org/reva/pkg/auth" ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/tracing" ) +const tracerName = "header" + func init() { registry.Register("header", New) } @@ -40,5 +43,7 @@ func New(m map[string]interface{}) (auth.TokenStrategy, error) { } func (s *strategy) GetToken(r *http.Request) string { + r, span := tracing.SpanStartFromRequest(r, tracerName, "GetCredentials") + defer span.End() return r.Header.Get(s.header) } diff --git a/internal/http/interceptors/log/log.go b/internal/http/interceptors/log/log.go index 3255cc7ad6..dba1ee45e1 100644 --- a/internal/http/interceptors/log/log.go +++ b/internal/http/interceptors/log/log.go @@ -27,9 +27,12 @@ import ( "time" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/tracing" "github.com/rs/zerolog" ) +const tracerName = "log" + // New returns a new HTTP middleware that logs HTTP requests and responses. // TODO(labkode): maybe log to another file? func New() func(http.Handler) http.Handler { @@ -50,6 +53,9 @@ type loggingHandler struct { } func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + req, span := tracing.SpanStartFromRequest(req, tracerName, "log Interceptor HTTP Handler") + defer span.End() + log := appctx.GetLogger(req.Context()) t := time.Now() logger := makeLogger(w) @@ -75,6 +81,9 @@ func makeLogger(w http.ResponseWriter) loggingResponseWriter { } func writeLog(log *zerolog.Logger, req *http.Request, url url.URL, ts time.Time, status, size int) { + req, span := tracing.SpanStartFromRequest(req, tracerName, "writeLog") + defer span.End() + end := time.Now() host, _, err := net.SplitHostPort(req.RemoteAddr) diff --git a/internal/http/interceptors/providerauthorizer/providerauthorizer.go b/internal/http/interceptors/providerauthorizer/providerauthorizer.go index 450614dcc8..176d14c0b4 100644 --- a/internal/http/interceptors/providerauthorizer/providerauthorizer.go +++ b/internal/http/interceptors/providerauthorizer/providerauthorizer.go @@ -31,10 +31,13 @@ import ( "github.com/cs3org/reva/pkg/ocm/provider/authorizer/registry" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/rhttp/router" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/mitchellh/mapstructure" ) +const tracerName = "providerauthorizer" + type config struct { Driver string `mapstructure:"driver"` Drivers map[string]map[string]interface{} `mapstructure:"drivers"` @@ -74,6 +77,8 @@ func New(m map[string]interface{}, unprotected []string, ocmPrefix string) (glob handler := func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "providerauthorizer Interceptor HTTP Handler") + defer span.End() ctx := r.Context() log := appctx.GetLogger(ctx) diff --git a/internal/http/services/appprovider/appprovider.go b/internal/http/services/appprovider/appprovider.go index 7c16c324fd..7d96c27365 100644 --- a/internal/http/services/appprovider/appprovider.go +++ b/internal/http/services/appprovider/appprovider.go @@ -34,6 +34,7 @@ import ( "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/go-chi/chi/v5" @@ -43,6 +44,8 @@ import ( "github.com/rs/zerolog" ) +const tracerName = "appprovider" + func init() { global.Register("appprovider", New) } @@ -62,13 +65,13 @@ func (c *Config) init() { } type svc struct { + tracing.HttpMiddleware conf *Config router *chi.Mux } // New returns a new ocmd object func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) { - conf := &Config{} if err := mapstructure.Decode(m, conf); err != nil { return nil, err @@ -115,9 +118,12 @@ func (s *svc) Handler() http.Handler { } func (s *svc) handleNew(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Appprovider Service HTTP Handler") + defer span.End() + ctx := r.Context() - client, err := pool.GetGatewayServiceClient(pool.Endpoint(s.conf.GatewaySvc)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(s.conf.GatewaySvc)) if err != nil { writeError(w, r, appErrorServerError, "error getting grpc gateway client", err) return @@ -292,8 +298,11 @@ func (s *svc) handleNew(w http.ResponseWriter, r *http.Request) { } func (s *svc) handleList(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleList") + defer span.End() + ctx := r.Context() - client, err := pool.GetGatewayServiceClient(pool.Endpoint(s.conf.GatewaySvc)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(s.conf.GatewaySvc)) if err != nil { writeError(w, r, appErrorServerError, "error getting grpc gateway client", err) return @@ -324,9 +333,12 @@ func (s *svc) handleList(w http.ResponseWriter, r *http.Request) { } func (s *svc) handleOpen(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleOpen") + defer span.End() + ctx := r.Context() - client, err := pool.GetGatewayServiceClient(pool.Endpoint(s.conf.GatewaySvc)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(s.conf.GatewaySvc)) if err != nil { writeError(w, r, appErrorServerError, "Internal error with the gateway, please try again later", err) return diff --git a/internal/http/services/archiver/handler.go b/internal/http/services/archiver/handler.go index bbfe4e8642..141fd22f26 100644 --- a/internal/http/services/archiver/handler.go +++ b/internal/http/services/archiver/handler.go @@ -40,6 +40,7 @@ import ( "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/storage/utils/downloader" "github.com/cs3org/reva/pkg/storage/utils/walker" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/gdexlab/go-render/render" ua "github.com/mileusna/useragent" @@ -47,7 +48,11 @@ import ( "github.com/rs/zerolog" ) +const serviceName = "archiver" +const tracerName = "archiver" + type svc struct { + tracing.HttpMiddleware config *Config gtwClient gateway.GatewayAPIClient log *zerolog.Logger @@ -75,6 +80,9 @@ func init() { // New creates a new archiver service func New(conf map[string]interface{}, log *zerolog.Logger) (global.Service, error) { + ctx, span := tracing.SpanStart(context.Background(), serviceName, tracerName, "New") + defer span.End() + c := &Config{} err := mapstructure.Decode(conf, c) if err != nil { @@ -83,7 +91,7 @@ func New(conf map[string]interface{}, log *zerolog.Logger) (global.Service, erro c.init() - gtw, err := pool.GetGatewayServiceClient(pool.Endpoint(c.GatewaySvc)) + gtw, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(c.GatewaySvc)) if err != nil { return nil, err } @@ -121,6 +129,9 @@ func (c *Config) init() { } func (s *svc) getFiles(ctx context.Context, files, ids []string) ([]string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getFiles") + defer span.End() + if len(files) == 0 && len(ids) == 0 { return nil, errtypes.BadRequest("file and id lists are both empty") } @@ -208,6 +219,9 @@ func (s *svc) writeHTTPError(rw http.ResponseWriter, err error) { func (s *svc) Handler() http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Archiver Service HTTP Handler") + defer span.End() + // get the paths and/or the resources id from the query ctx := r.Context() log := appctx.GetLogger(ctx) diff --git a/internal/http/services/archiver/manager/archiver.go b/internal/http/services/archiver/manager/archiver.go index dd37fbed5c..0af5a15e02 100644 --- a/internal/http/services/archiver/manager/archiver.go +++ b/internal/http/services/archiver/manager/archiver.go @@ -30,8 +30,11 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/storage/utils/downloader" "github.com/cs3org/reva/pkg/storage/utils/walker" + "github.com/cs3org/reva/pkg/tracing" ) +const tracerName = "manager" + // Config is the config for the Archiver type Config struct { MaxNumFiles int64 @@ -115,6 +118,9 @@ func getDeepestCommonDir(files []string) string { // CreateTar creates a tar and write it into the dst Writer func (a *Archiver) CreateTar(ctx context.Context, dst io.Writer) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateTar") + defer span.End() + w := tar.NewWriter(dst) var filesCount, sizeFiles int64 @@ -194,6 +200,9 @@ func (a *Archiver) CreateTar(ctx context.Context, dst io.Writer) error { // CreateZip creates a zip and write it into the dst Writer func (a *Archiver) CreateZip(ctx context.Context, dst io.Writer) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateZip") + defer span.End() + w := zip.NewWriter(dst) var filesCount, sizeFiles int64 diff --git a/internal/http/services/datagateway/datagateway.go b/internal/http/services/datagateway/datagateway.go index dba255f6be..9fd2888e93 100644 --- a/internal/http/services/datagateway/datagateway.go +++ b/internal/http/services/datagateway/datagateway.go @@ -19,7 +19,6 @@ package datagateway import ( - "context" "io" "net/http" "net/url" @@ -32,12 +31,16 @@ import ( "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/golang-jwt/jwt" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/rs/zerolog" ) +const serviceName = "datagateway" +const tracerName = "datagateway" + const ( // TokenTransportHeader holds the header key for the reva transfer token TokenTransportHeader = "X-Reva-Transfer" @@ -70,6 +73,7 @@ func (c *config) init() { } type svc struct { + tracing.HttpMiddleware conf *config handler http.Handler client *http.Client @@ -116,6 +120,9 @@ func (s *svc) Unprotected() []string { func (s *svc) setHandler() { s.handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Datagateway Service HTTP Handler") + defer span.End() + switch r.Method { case "HEAD": addCorsHeader(w) @@ -144,7 +151,10 @@ func addCorsHeader(res http.ResponseWriter) { headers.Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS, HEAD") } -func (s *svc) verify(ctx context.Context, r *http.Request) (*transferClaims, error) { +func (s *svc) verify(r *http.Request) (*transferClaims, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "verify") + defer span.End() + // Extract transfer token from request header. If not existing, assume that it's the last path segment instead. token := r.Header.Get(TokenTransportHeader) if token == "" { @@ -169,10 +179,13 @@ func (s *svc) verify(ctx context.Context, r *http.Request) (*transferClaims, err } func (s *svc) doHead(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "doHead") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) - claims, err := s.verify(ctx, r) + claims, err := s.verify(r) if err != nil { err = errors.Wrap(err, "datagateway: error validating transfer token") log.Error().Err(err).Str("token", r.Header.Get(TokenTransportHeader)).Msg("invalid transfer token") @@ -215,10 +228,13 @@ func (s *svc) doHead(w http.ResponseWriter, r *http.Request) { } func (s *svc) doGet(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "doGet") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) - claims, err := s.verify(ctx, r) + claims, err := s.verify(r) if err != nil { err = errors.Wrap(err, "datagateway: error validating transfer token") log.Error().Err(err).Str("token", r.Header.Get(TokenTransportHeader)).Msg("invalid transfer token") @@ -274,10 +290,13 @@ func (s *svc) doGet(w http.ResponseWriter, r *http.Request) { } func (s *svc) doPut(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "doPut") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) - claims, err := s.verify(ctx, r) + claims, err := s.verify(r) if err != nil { err = errors.Wrap(err, "datagateway: error validating transfer token") log.Err(err).Str("token", r.Header.Get(TokenTransportHeader)).Msg("invalid transfer token") @@ -333,10 +352,13 @@ func (s *svc) doPut(w http.ResponseWriter, r *http.Request) { // TODO: put and post code is pretty much the same. Should be solved in a nicer way in the long run. func (s *svc) doPatch(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "doPatch") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) - claims, err := s.verify(ctx, r) + claims, err := s.verify(r) if err != nil { err = errors.Wrap(err, "datagateway: error validating transfer token") log.Err(err).Str("token", r.Header.Get(TokenTransportHeader)).Msg("invalid transfer token") diff --git a/internal/http/services/dataprovider/dataprovider.go b/internal/http/services/dataprovider/dataprovider.go index a149e7118d..a75ef8b7e7 100644 --- a/internal/http/services/dataprovider/dataprovider.go +++ b/internal/http/services/dataprovider/dataprovider.go @@ -28,10 +28,14 @@ import ( "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/rs/zerolog" ) +const serviceName = "dataprovider" +const tracerName = "dataprovider" + func init() { global.Register("dataprovider", New) } @@ -55,6 +59,7 @@ func (c *config) init() { } type svc struct { + tracing.HttpMiddleware conf *config handler http.Handler storage storage.FS @@ -139,8 +144,10 @@ func (s *svc) Handler() http.Handler { } func (s *svc) setHandler() error { - s.handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Dataprovider Service HTTP Handler") + defer span.End() + log := appctx.GetLogger(r.Context()) log.Debug().Msgf("dataprovider routing: path=%s", r.URL.Path) diff --git a/internal/http/services/helloworld/helloworld.go b/internal/http/services/helloworld/helloworld.go index f194b34602..b590d10437 100644 --- a/internal/http/services/helloworld/helloworld.go +++ b/internal/http/services/helloworld/helloworld.go @@ -23,10 +23,14 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/rs/zerolog" ) +const serviceName = "helloworld" +const tracerName = "helloworld" + func init() { global.Register("helloworld", New) } @@ -64,6 +68,7 @@ func (c *config) init() { } type svc struct { + tracing.HttpMiddleware conf *config } @@ -77,6 +82,9 @@ func (s *svc) Unprotected() []string { func (s *svc) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Helloword Service HTTP Handler") + defer span.End() + log := appctx.GetLogger(r.Context()) if _, err := w.Write([]byte(s.conf.HelloMessage)); err != nil { log.Err(err).Msg("error writing response") diff --git a/internal/http/services/mailer/mailer.go b/internal/http/services/mailer/mailer.go index 3f47a5f64d..01ce3ae799 100644 --- a/internal/http/services/mailer/mailer.go +++ b/internal/http/services/mailer/mailer.go @@ -42,10 +42,14 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/rs/zerolog" ) +const serviceName = "mailer" +const tracerName = "mailer" + func init() { global.Register("mailer", New) } @@ -62,6 +66,7 @@ type config struct { } type svc struct { + tracing.HttpMiddleware conf *config client gateway.GatewayAPIClient tplBody *template.Template @@ -70,6 +75,9 @@ type svc struct { // New creates a new mailer service func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) { + ctx, span := tracing.SpanStart(context.Background(), serviceName, tracerName, "New") + defer span.End() + conf := &config{} if err := mapstructure.Decode(m, conf); err != nil { return nil, err @@ -77,7 +85,7 @@ func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) conf.init() - client, err := pool.GetGatewayServiceClient(pool.Endpoint(conf.GatewaySVC)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(conf.GatewaySVC)) if err != nil { return nil, err } diff --git a/internal/http/services/mentix/mentix.go b/internal/http/services/mentix/mentix.go index af9adb90ed..f95daba24b 100644 --- a/internal/http/services/mentix/mentix.go +++ b/internal/http/services/mentix/mentix.go @@ -22,6 +22,7 @@ import ( "net/http" "github.com/cs3org/reva/pkg/mentix/meshdata" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/rs/zerolog" @@ -32,11 +33,15 @@ import ( "github.com/cs3org/reva/pkg/rhttp/global" ) +const serviceName = "mentix" +const tracerName = "mentix" + func init() { global.Register(serviceName, New) } type svc struct { + tracing.HttpMiddleware conf *config.Configuration mntx *mentix.Mentix log *zerolog.Logger @@ -44,10 +49,6 @@ type svc struct { stopSignal chan struct{} } -const ( - serviceName = "mentix" -) - func (s *svc) Close() error { // Trigger and close the stopSignal signal channel to stop Mentix s.stopSignal <- struct{}{} diff --git a/internal/http/services/meshdirectory/meshdirectory.go b/internal/http/services/meshdirectory/meshdirectory.go index dba4c3d79b..730ddfa8af 100644 --- a/internal/http/services/meshdirectory/meshdirectory.go +++ b/internal/http/services/meshdirectory/meshdirectory.go @@ -19,6 +19,7 @@ package meshdirectory import ( + "context" "encoding/json" "fmt" "net/http" @@ -32,6 +33,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" "github.com/rs/zerolog" @@ -39,6 +41,8 @@ import ( "github.com/mitchellh/mapstructure" ) +const tracerName = "meshdirectory" + func init() { global.Register("meshdirectory", New) } @@ -57,6 +61,7 @@ func (c *config) init() { } type svc struct { + tracing.HttpMiddleware conf *config } @@ -99,16 +104,21 @@ func (s *svc) Close() error { return nil } -func (s *svc) getClient() (gateway.GatewayAPIClient, error) { - return pool.GetGatewayServiceClient(pool.Endpoint(s.conf.GatewaySvc)) +func (s *svc) getClient(ctx context.Context) (gateway.GatewayAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getClient") + defer span.End() + return pool.GetGatewayServiceClient(ctx, pool.Endpoint(s.conf.GatewaySvc)) } func (s *svc) serveJSON(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "serveJSON") + defer span.End() + w.Header().Set("Content-Type", "application/json") ctx := r.Context() - gatewayClient, err := s.getClient() + gatewayClient, err := s.getClient(ctx) if err != nil { ocmd.WriteError(w, r, ocmd.APIErrorServerError, fmt.Sprintf("error getting grpc client on addr: %v", s.conf.GatewaySvc), err) @@ -140,6 +150,9 @@ func (s *svc) serveJSON(w http.ResponseWriter, r *http.Request) { // HTTP service handler func (s *svc) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Meshdirectory Service HTTP Handler") + defer span.End() + var head string head, r.URL.Path = router.ShiftPath(r.URL.Path) switch head { diff --git a/internal/http/services/metrics/metrics.go b/internal/http/services/metrics/metrics.go index 7fee35c6c4..9857e54e4b 100644 --- a/internal/http/services/metrics/metrics.go +++ b/internal/http/services/metrics/metrics.go @@ -26,6 +26,7 @@ import ( "os" "github.com/cs3org/reva/pkg/logger" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/rs/zerolog" @@ -38,9 +39,8 @@ func init() { global.Register(serviceName, New) } -const ( - serviceName = "metrics" -) +const serviceName = "metrics" +const tracerName = "metrics" // Close is called when this service is being stopped. func (s *svc) Close() error { @@ -62,6 +62,9 @@ func (s *svc) Unprotected() []string { // Handler serves all HTTP requests. func (s *svc) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Metrics Service HTTP Handler") + defer span.End() + log := logger.New().With().Int("pid", os.Getpid()).Logger() if _, err := w.Write([]byte("This is the metrics service.\n")); err != nil { log.Error().Err(err).Msg("error writing metrics response") @@ -91,4 +94,5 @@ func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) } type svc struct { + tracing.HttpMiddleware } diff --git a/internal/http/services/ocmd/config.go b/internal/http/services/ocmd/config.go index 79364d890b..59fc7ec93e 100644 --- a/internal/http/services/ocmd/config.go +++ b/internal/http/services/ocmd/config.go @@ -24,6 +24,7 @@ import ( "net/http" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/tracing" ) type configData struct { @@ -77,6 +78,9 @@ func (h *configHandler) init(c *Config) { func (h *configHandler) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Config HTTP Handler") + defer span.End() + log := appctx.GetLogger(r.Context()) w.Header().Set("Content-Type", "application/json") diff --git a/internal/http/services/ocmd/invites.go b/internal/http/services/ocmd/invites.go index eab71c7d90..442d261f17 100644 --- a/internal/http/services/ocmd/invites.go +++ b/internal/http/services/ocmd/invites.go @@ -36,6 +36,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/smtpclient" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" ) @@ -55,6 +56,9 @@ func (h *invitesHandler) init(c *Config) { func (h *invitesHandler) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Invites HTTP Handler") + defer span.End() + log := appctx.GetLogger(r.Context()) var head string head, r.URL.Path = router.ShiftPath(r.URL.Path) @@ -78,10 +82,12 @@ func (h *invitesHandler) Handler() http.Handler { } func (h *invitesHandler) generateInviteToken(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "generateInviteToken") + defer span.End() ctx := r.Context() - gatewayClient, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + gatewayClient, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { WriteError(w, r, APIErrorServerError, "error getting gateway grpc client", err) return @@ -133,6 +139,9 @@ func (h *invitesHandler) generateInviteToken(w http.ResponseWriter, r *http.Requ } func (h *invitesHandler) forwardInvite(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "forwardInvite") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) contentType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) @@ -155,7 +164,7 @@ func (h *invitesHandler) forwardInvite(w http.ResponseWriter, r *http.Request) { return } - gatewayClient, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + gatewayClient, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { WriteError(w, r, APIErrorServerError, "error getting gateway grpc client", err) return @@ -202,6 +211,9 @@ func (h *invitesHandler) forwardInvite(w http.ResponseWriter, r *http.Request) { } func (h *invitesHandler) acceptInvite(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "acceptInvite") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) contentType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) @@ -226,7 +238,7 @@ func (h *invitesHandler) acceptInvite(w http.ResponseWriter, r *http.Request) { return } - gatewayClient, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + gatewayClient, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { WriteError(w, r, APIErrorServerError, "error getting gateway grpc client", err) return @@ -294,10 +306,13 @@ func (h *invitesHandler) acceptInvite(w http.ResponseWriter, r *http.Request) { } func (h *invitesHandler) findAcceptedUsers(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "findAcceptedUsers") + defer span.End() + log := appctx.GetLogger(r.Context()) ctx := r.Context() - gatewayClient, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + gatewayClient, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { WriteError(w, r, APIErrorServerError, "error getting gateway grpc client", err) return @@ -320,10 +335,13 @@ func (h *invitesHandler) findAcceptedUsers(w http.ResponseWriter, r *http.Reques } func (h *invitesHandler) generate(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "generate") + defer span.End() + log := appctx.GetLogger(r.Context()) ctx := r.Context() - gatewayClient, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + gatewayClient, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { WriteError(w, r, APIErrorServerError, "error getting gateway grpc client", err) return diff --git a/internal/http/services/ocmd/notifications.go b/internal/http/services/ocmd/notifications.go index a8a13021a4..f357198330 100644 --- a/internal/http/services/ocmd/notifications.go +++ b/internal/http/services/ocmd/notifications.go @@ -23,6 +23,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/router" + "github.com/cs3org/reva/pkg/tracing" ) type notificationsHandler struct { @@ -33,6 +34,9 @@ func (h *notificationsHandler) init(c *Config) { func (h *notificationsHandler) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Notifications HTTP Handler") + defer span.End() + log := appctx.GetLogger(r.Context()) var head string diff --git a/internal/http/services/ocmd/ocmd.go b/internal/http/services/ocmd/ocmd.go index c65cec5d67..1ecdb548c6 100644 --- a/internal/http/services/ocmd/ocmd.go +++ b/internal/http/services/ocmd/ocmd.go @@ -26,10 +26,14 @@ import ( "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/smtpclient" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/rs/zerolog" ) +const serviceName = "ocmd" +const tracerName = "ocmd" + func init() { global.Register("ocmd", New) } @@ -53,6 +57,7 @@ func (c *Config) init() { } type svc struct { + tracing.HttpMiddleware Conf *Config SharesHandler *sharesHandler NotificationsHandler *notificationsHandler @@ -63,7 +68,6 @@ type svc struct { // New returns a new ocmd object func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) { - conf := &Config{} if err := mapstructure.Decode(m, conf); err != nil { return nil, err @@ -104,6 +108,8 @@ func (s *svc) Unprotected() []string { func (s *svc) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Ocmd Service HTTP Handler") + defer span.End() ctx := r.Context() log := appctx.GetLogger(ctx) diff --git a/internal/http/services/ocmd/reqres.go b/internal/http/services/ocmd/reqres.go index d37824a8fc..e13dee4b74 100644 --- a/internal/http/services/ocmd/reqres.go +++ b/internal/http/services/ocmd/reqres.go @@ -23,6 +23,7 @@ import ( "net/http" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/tracing" ) // APIErrorCode stores the type of error encountered @@ -58,6 +59,9 @@ type APIError struct { // WriteError handles writing error responses func WriteError(w http.ResponseWriter, r *http.Request, code APIErrorCode, message string, e error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "WriteError") + defer span.End() + if e != nil { appctx.GetLogger(r.Context()).Error().Err(e).Msg(message) } diff --git a/internal/http/services/ocmd/send.go b/internal/http/services/ocmd/send.go index d0106abed3..188a1f833b 100644 --- a/internal/http/services/ocmd/send.go +++ b/internal/http/services/ocmd/send.go @@ -35,6 +35,7 @@ import ( types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/appctx" ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/tracing" "google.golang.org/grpc/metadata" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -50,7 +51,11 @@ func (h *sendHandler) init(c *Config) { func (h *sendHandler) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - log := appctx.GetLogger(r.Context()) + r, span := tracing.SpanStartFromRequest(r, tracerName, "Send HTTP Handler") + defer span.End() + + ctx := r.Context() + log := appctx.GetLogger(ctx) defer r.Body.Close() reqBody, err := io.ReadAll(r.Body) if err != nil { @@ -80,7 +85,7 @@ func (h *sendHandler) Handler() http.Handler { // "loginPassword": "Ny4Nv6WLoC1o70kVgrVOZLZ2vRgPjuej" gatewayAddr := h.GatewaySvc - gatewayClient, err := pool.GetGatewayServiceClient(pool.Endpoint(gatewayAddr)) + gatewayClient, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(gatewayAddr)) if err != nil { log.Error().Msg("cannot get grpc client!") w.WriteHeader(http.StatusInternalServerError) diff --git a/internal/http/services/ocmd/shares.go b/internal/http/services/ocmd/shares.go index d4435d3b08..a2404f8d47 100644 --- a/internal/http/services/ocmd/shares.go +++ b/internal/http/services/ocmd/shares.go @@ -38,6 +38,7 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" ) @@ -51,6 +52,8 @@ func (h *sharesHandler) init(c *Config) { func (h *sharesHandler) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Shares HTTP Handler") + defer span.End() switch r.Method { case http.MethodPost: @@ -62,6 +65,9 @@ func (h *sharesHandler) Handler() http.Handler { } func (h *sharesHandler) createShare(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "createShare") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) contentType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) @@ -109,7 +115,7 @@ func (h *sharesHandler) createShare(w http.ResponseWriter, r *http.Request) { return } - gatewayClient, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + gatewayClient, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { WriteError(w, r, APIErrorServerError, "error getting storage grpc client", err) return diff --git a/internal/http/services/owncloud/ocdav/avatars.go b/internal/http/services/owncloud/ocdav/avatars.go index 2271d2901b..cd0d108292 100644 --- a/internal/http/services/owncloud/ocdav/avatars.go +++ b/internal/http/services/owncloud/ocdav/avatars.go @@ -24,6 +24,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/router" + "github.com/cs3org/reva/pkg/tracing" ) // AvatarsHandler handles avatar requests @@ -37,6 +38,9 @@ func (h *AvatarsHandler) init(c *Config) error { // Handler handles requests func (h *AvatarsHandler) Handler(s *svc) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Avatars HTTP Handler") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) diff --git a/internal/http/services/owncloud/ocdav/copy.go b/internal/http/services/owncloud/ocdav/copy.go index 55a6ea6fc0..92252be0e5 100644 --- a/internal/http/services/owncloud/ocdav/copy.go +++ b/internal/http/services/owncloud/ocdav/copy.go @@ -19,7 +19,6 @@ package ocdav import ( - "context" "fmt" "net/http" "path" @@ -34,7 +33,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/rhttp/router" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/rs/zerolog" ) @@ -49,17 +48,18 @@ type copy struct { type intermediateDirRefFunc func() (*provider.Reference, *rpc.Status, error) func (s *svc) handlePathCopy(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "copy") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePathCopy") defer span.End() + ctx := r.Context() if s.c.EnableHTTPTpc { if r.Header.Get("Source") != "" { // HTTP Third-Party Copy Pull mode - s.handleTPCPull(ctx, w, r, ns) + s.handleTPCPull(w, r, ns) return } else if r.Header.Get("Destination") != "" { // HTTP Third-Party Copy Push mode - s.handleTPCPush(ctx, w, r, ns) + s.handleTPCPush(w, r, ns) return } } @@ -96,26 +96,30 @@ func (s *svc) handlePathCopy(w http.ResponseWriter, r *http.Request, ns string) return ref, &rpc.Status{Code: rpc.Code_CODE_OK}, nil } - cp := s.prepareCopy(ctx, w, r, srcRef, dstRef, intermediateDirRefFunc, &sublog) + cp := s.prepareCopy(w, r, srcRef, dstRef, intermediateDirRefFunc, &sublog) if cp == nil { return } - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) return } - if err := s.executePathCopy(ctx, client, w, r, cp); err != nil { + if err := s.executePathCopy(client, w, r, cp); err != nil { sublog.Error().Err(err).Str("depth", cp.depth).Msg("error executing path copy") w.WriteHeader(http.StatusInternalServerError) } w.WriteHeader(cp.successCode) } -func (s *svc) executePathCopy(ctx context.Context, client gateway.GatewayAPIClient, w http.ResponseWriter, r *http.Request, cp *copy) error { +func (s *svc) executePathCopy(client gateway.GatewayAPIClient, w http.ResponseWriter, r *http.Request, cp *copy) error { + r, span := tracing.SpanStartFromRequest(r, tracerName, "executePathCopy") + defer span.End() + + ctx := r.Context() log := appctx.GetLogger(ctx) log.Debug().Str("src", cp.sourceInfo.Path).Str("dst", cp.destination.Path).Msg("descending") if cp.sourceInfo.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER { @@ -136,7 +140,7 @@ func (s *svc) executePathCopy(ctx context.Context, client gateway.GatewayAPIClie code: SabredavPermissionDenied, message: m, }) - HandleWebdavError(log, w, b, err) + HandleWebdavError(ctx, log, w, b, err) } return nil } @@ -162,7 +166,7 @@ func (s *svc) executePathCopy(ctx context.Context, client gateway.GatewayAPIClie for i := range res.Infos { childDst := &provider.Reference{Path: path.Join(cp.destination.Path, path.Base(res.Infos[i].Path))} - err := s.executePathCopy(ctx, client, w, r, ©{sourceInfo: res.Infos[i], destination: childDst, depth: cp.depth, successCode: cp.successCode}) + err := s.executePathCopy(client, w, r, ©{sourceInfo: res.Infos[i], destination: childDst, depth: cp.depth, successCode: cp.successCode}) if err != nil { return err } @@ -221,10 +225,10 @@ func (s *svc) executePathCopy(ctx context.Context, client gateway.GatewayAPIClie code: SabredavPermissionDenied, message: m, }) - HandleWebdavError(log, w, b, err) + HandleWebdavError(ctx, log, w, b, err) return nil } - HandleErrorStatus(log, w, uRes.Status) + HandleErrorStatus(ctx, log, w, uRes.Status) return nil } @@ -274,9 +278,10 @@ func (s *svc) executePathCopy(ctx context.Context, client gateway.GatewayAPIClie } func (s *svc) handleSpacesCopy(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "spaces_copy") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleSpacesCopy") defer span.End() + ctx := r.Context() dst, err := extractDestination(r) if err != nil { w.WriteHeader(http.StatusBadRequest) @@ -294,7 +299,7 @@ func (s *svc) handleSpacesCopy(w http.ResponseWriter, r *http.Request, spaceID s } if status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, status) + HandleErrorStatus(ctx, &sublog, w, status) return } @@ -309,7 +314,7 @@ func (s *svc) handleSpacesCopy(w http.ResponseWriter, r *http.Request, spaceID s } if status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, status) + HandleErrorStatus(ctx, &sublog, w, status) return } @@ -318,18 +323,18 @@ func (s *svc) handleSpacesCopy(w http.ResponseWriter, r *http.Request, spaceID s return s.lookUpStorageSpaceReference(ctx, dstSpaceID, intermediateDir) } - cp := s.prepareCopy(ctx, w, r, srcRef, dstRef, intermediateDirRefFunc, &sublog) + cp := s.prepareCopy(w, r, srcRef, dstRef, intermediateDirRefFunc, &sublog) if cp == nil { return } - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) return } - err = s.executeSpacesCopy(ctx, w, client, cp) + err = s.executeSpacesCopy(w, r, client, cp) if err != nil { sublog.Error().Err(err).Str("depth", cp.depth).Msg("error descending directory") w.WriteHeader(http.StatusInternalServerError) @@ -337,7 +342,11 @@ func (s *svc) handleSpacesCopy(w http.ResponseWriter, r *http.Request, spaceID s w.WriteHeader(cp.successCode) } -func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, client gateway.GatewayAPIClient, cp *copy) error { +func (s *svc) executeSpacesCopy(w http.ResponseWriter, r *http.Request, client gateway.GatewayAPIClient, cp *copy) error { + r, span := tracing.SpanStartFromRequest(r, tracerName, "executeSpacesCopy") + defer span.End() + + ctx := r.Context() log := appctx.GetLogger(ctx) log.Debug().Interface("src", cp.sourceInfo).Interface("dst", cp.destination).Msg("descending") @@ -360,7 +369,7 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, clie code: SabredavPermissionDenied, message: m, }) - HandleWebdavError(log, w, b, err) + HandleWebdavError(ctx, log, w, b, err) } return nil } @@ -387,7 +396,7 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, clie ResourceId: cp.destination.ResourceId, Path: utils.MakeRelativePath(path.Join(cp.destination.Path, res.Infos[i].Path)), } - err := s.executeSpacesCopy(ctx, w, client, ©{sourceInfo: res.Infos[i], destination: childRef, depth: cp.depth, successCode: cp.successCode}) + err := s.executeSpacesCopy(w, r, client, ©{sourceInfo: res.Infos[i], destination: childRef, depth: cp.depth, successCode: cp.successCode}) if err != nil { return err } @@ -439,10 +448,10 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, clie code: SabredavPermissionDenied, message: m, }) - HandleWebdavError(log, w, b, err) + HandleWebdavError(ctx, log, w, b, err) return nil } - HandleErrorStatus(log, w, uRes.Status) + HandleErrorStatus(ctx, log, w, uRes.Status) return nil } @@ -491,7 +500,11 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, clie return nil } -func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, srcRef, dstRef *provider.Reference, intermediateDirRef intermediateDirRefFunc, log *zerolog.Logger) *copy { +func (s *svc) prepareCopy(w http.ResponseWriter, r *http.Request, srcRef, dstRef *provider.Reference, intermediateDirRef intermediateDirRefFunc, log *zerolog.Logger) *copy { + r, span := tracing.SpanStartFromRequest(r, tracerName, "prepareCopy") + defer span.End() + + ctx := r.Context() overwrite, err := extractOverwrite(w, r) if err != nil { w.WriteHeader(http.StatusBadRequest) @@ -500,7 +513,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re code: SabredavBadRequest, message: m, }) - HandleWebdavError(log, w, b, err) + HandleWebdavError(ctx, log, w, b, err) return nil } depth, err := extractDepth(w, r) @@ -511,13 +524,13 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re code: SabredavBadRequest, message: m, }) - HandleWebdavError(log, w, b, err) + HandleWebdavError(ctx, log, w, b, err) return nil } log.Debug().Str("overwrite", overwrite).Str("depth", depth).Msg("copy") - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -540,9 +553,9 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re code: SabredavNotFound, message: m, }) - HandleWebdavError(log, w, b, err) + HandleWebdavError(ctx, log, w, b, err) } - HandleErrorStatus(log, w, srcStatRes.Status) + HandleErrorStatus(ctx, log, w, srcStatRes.Status) return nil } @@ -554,7 +567,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re return nil } if dstStatRes.Status.Code != rpc.Code_CODE_OK && dstStatRes.Status.Code != rpc.Code_CODE_NOT_FOUND { - HandleErrorStatus(log, w, srcStatRes.Status) + HandleErrorStatus(ctx, log, w, srcStatRes.Status) return nil } @@ -570,7 +583,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re code: SabredavPreconditionFailed, message: m, }) - HandleWebdavError(log, w, b, err) // 412, see https://tools.ietf.org/html/rfc4918#section-9.8.5 + HandleWebdavError(ctx, log, w, b, err) // 412, see https://tools.ietf.org/html/rfc4918#section-9.8.5 return nil } @@ -584,7 +597,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re } if delRes.Status.Code != rpc.Code_CODE_OK && delRes.Status.Code != rpc.Code_CODE_NOT_FOUND { - HandleErrorStatus(log, w, delRes.Status) + HandleErrorStatus(ctx, log, w, delRes.Status) return nil } } else { @@ -597,7 +610,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re } if status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(log, w, status) + HandleErrorStatus(ctx, log, w, status) return nil } intStatReq := &provider.StatRequest{Ref: intermediateRef} @@ -613,7 +626,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re log.Debug().Interface("parent", intermediateRef).Interface("status", intStatRes.Status).Msg("conflict") w.WriteHeader(http.StatusConflict) } else { - HandleErrorStatus(log, w, srcStatRes.Status) + HandleErrorStatus(ctx, log, w, srcStatRes.Status) } return nil } @@ -624,6 +637,9 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re } func extractOverwrite(w http.ResponseWriter, r *http.Request) (string, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "extractOverwrite") + defer span.End() + overwrite := r.Header.Get(HeaderOverwrite) overwrite = strings.ToUpper(overwrite) if overwrite == "" { @@ -638,6 +654,9 @@ func extractOverwrite(w http.ResponseWriter, r *http.Request) (string, error) { } func extractDepth(w http.ResponseWriter, r *http.Request) (string, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "extractDepth") + defer span.End() + depth := r.Header.Get(HeaderDepth) if depth == "" { depth = "infinity" diff --git a/internal/http/services/owncloud/ocdav/dav.go b/internal/http/services/owncloud/ocdav/dav.go index 1e07c570ce..21a1423454 100644 --- a/internal/http/services/owncloud/ocdav/dav.go +++ b/internal/http/services/owncloud/ocdav/dav.go @@ -33,6 +33,7 @@ import ( ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/router" + "github.com/cs3org/reva/pkg/tracing" "google.golang.org/grpc/metadata" ) @@ -94,6 +95,9 @@ func isOwner(userIDorName string, user *userv1beta1.User) bool { // Handler handles requests func (h *DavHandler) Handler(s *svc) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Dav HTTP Handler") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) @@ -175,7 +179,7 @@ func (h *DavHandler) Handler(s *svc) http.Handler { case "public-files": base := path.Join(ctx.Value(ctxKeyBaseURI).(string), "public-files") ctx = context.WithValue(ctx, ctxKeyBaseURI, base) - c, err := pool.GetGatewayServiceClient(pool.Endpoint(s.c.GatewaySvc)) + c, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(s.c.GatewaySvc)) if err != nil { w.WriteHeader(http.StatusNotFound) } @@ -257,16 +261,22 @@ func (h *DavHandler) Handler(s *svc) http.Handler { code: SabredavNotFound, message: "File not found in root", }) - HandleWebdavError(log, w, b, err) + HandleWebdavError(ctx, log, w, b, err) } }) } func getTokenStatInfo(ctx context.Context, client gatewayv1beta1.GatewayAPIClient, token string) (*provider.StatResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getTokenStatInfo") + defer span.End() + return client.Stat(ctx, &provider.StatRequest{Ref: &provider.Reference{Path: path.Join("/public", token)}}) } func handleBasicAuth(ctx context.Context, c gatewayv1beta1.GatewayAPIClient, token, pw string) (*gatewayv1beta1.AuthenticateResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "handleBasicAuth") + defer span.End() + authenticateRequest := gatewayv1beta1.AuthenticateRequest{ Type: "publicshares", ClientId: token, @@ -277,6 +287,9 @@ func handleBasicAuth(ctx context.Context, c gatewayv1beta1.GatewayAPIClient, tok } func handleSignatureAuth(ctx context.Context, c gatewayv1beta1.GatewayAPIClient, token, sig, expiration string) (*gatewayv1beta1.AuthenticateResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "handleSignatureAuth") + defer span.End() + authenticateRequest := gatewayv1beta1.AuthenticateRequest{ Type: "publicshares", ClientId: token, diff --git a/internal/http/services/owncloud/ocdav/delete.go b/internal/http/services/owncloud/ocdav/delete.go index ed8f365539..39d8567a49 100644 --- a/internal/http/services/owncloud/ocdav/delete.go +++ b/internal/http/services/owncloud/ocdav/delete.go @@ -19,7 +19,6 @@ package ocdav import ( - "context" "fmt" "net/http" "path" @@ -27,33 +26,36 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/rs/zerolog" ) func (s *svc) handlePathDelete(w http.ResponseWriter, r *http.Request, ns string) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePathDelete") + defer span.End() + fn := path.Join(ns, r.URL.Path) sublog := appctx.GetLogger(r.Context()).With().Str("path", fn).Logger() ref := &provider.Reference{Path: fn} - s.handleDelete(r.Context(), w, r, ref, sublog) + s.handleDelete(w, r, ref, sublog) } -func (s *svc) handleDelete(ctx context.Context, w http.ResponseWriter, r *http.Request, ref *provider.Reference, log zerolog.Logger) { - client, err := s.getClient() +func (s *svc) handleDelete(w http.ResponseWriter, r *http.Request, ref *provider.Reference, log zerolog.Logger) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleDelete") + defer span.End() + + ctx := r.Context() + client, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) return } - ctx, span := rtrace.Provider.Tracer("reva").Start(ctx, "delete") - defer span.End() - req := &provider.DeleteRequest{Ref: ref} res, err := client.Delete(ctx, req) if err != nil { - span.RecordError(err) log.Error().Err(err).Msg("error performing delete grpc request") w.WriteHeader(http.StatusInternalServerError) return @@ -66,7 +68,7 @@ func (s *svc) handleDelete(ctx context.Context, w http.ResponseWriter, r *http.R code: SabredavNotFound, message: m, }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) } if res.Status.Code == rpc.Code_CODE_PERMISSION_DENIED { w.WriteHeader(http.StatusForbidden) @@ -76,7 +78,7 @@ func (s *svc) handleDelete(ctx context.Context, w http.ResponseWriter, r *http.R code: SabredavPermissionDenied, message: m, }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) } if res.Status.Code == rpc.Code_CODE_INTERNAL && res.Status.Message == "can't delete mount path" { w.WriteHeader(http.StatusForbidden) @@ -84,10 +86,10 @@ func (s *svc) handleDelete(ctx context.Context, w http.ResponseWriter, r *http.R code: SabredavPermissionDenied, message: res.Status.Message, }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) } - HandleErrorStatus(&log, w, res.Status) + HandleErrorStatus(ctx, &log, w, res.Status) return } @@ -95,10 +97,10 @@ func (s *svc) handleDelete(ctx context.Context, w http.ResponseWriter, r *http.R } func (s *svc) handleSpacesDelete(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx := r.Context() - ctx, span := rtrace.Provider.Tracer("reva").Start(ctx, "spaces_delete") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleSpacesDelete") defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Logger() // retrieve a specific storage space ref, rpcStatus, err := s.lookUpStorageSpaceReference(ctx, spaceID, r.URL.Path) @@ -109,9 +111,9 @@ func (s *svc) handleSpacesDelete(w http.ResponseWriter, r *http.Request, spaceID } if rpcStatus.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, rpcStatus) + HandleErrorStatus(ctx, &sublog, w, rpcStatus) return } - s.handleDelete(ctx, w, r, ref, sublog) + s.handleDelete(w, r, ref, sublog) } diff --git a/internal/http/services/owncloud/ocdav/error.go b/internal/http/services/owncloud/ocdav/error.go index fec06430c5..12a1e873bb 100644 --- a/internal/http/services/owncloud/ocdav/error.go +++ b/internal/http/services/owncloud/ocdav/error.go @@ -19,10 +19,12 @@ package ocdav import ( + "context" "encoding/xml" "net/http" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" "github.com/rs/zerolog" ) @@ -96,7 +98,10 @@ var errInvalidPropfind = errors.New("webdav: invalid propfind") // HandleErrorStatus checks the status code, logs a Debug or Error level message // and writes an appropriate http status -func HandleErrorStatus(log *zerolog.Logger, w http.ResponseWriter, s *rpc.Status) { +func HandleErrorStatus(ctx context.Context, log *zerolog.Logger, w http.ResponseWriter, s *rpc.Status) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "HandleErrorStatus") + defer span.End() + switch s.Code { case rpc.Code_CODE_OK: log.Debug().Interface("status", s).Msg("ok") @@ -130,7 +135,10 @@ func HandleErrorStatus(log *zerolog.Logger, w http.ResponseWriter, s *rpc.Status // HandleWebdavError checks the status code, logs an error and creates a webdav response body // if needed -func HandleWebdavError(log *zerolog.Logger, w http.ResponseWriter, b []byte, err error) { +func HandleWebdavError(ctx context.Context, log *zerolog.Logger, w http.ResponseWriter, b []byte, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "HandleWebdavError") + defer span.End() + if err != nil { log.Error().Msgf("error marshaling xml response: %s", b) w.WriteHeader(http.StatusInternalServerError) diff --git a/internal/http/services/owncloud/ocdav/get.go b/internal/http/services/owncloud/ocdav/get.go index e5fead0c2a..948fc5598d 100644 --- a/internal/http/services/owncloud/ocdav/get.go +++ b/internal/http/services/owncloud/ocdav/get.go @@ -19,7 +19,6 @@ package ocdav import ( - "context" "fmt" "io" "net/http" @@ -33,26 +32,31 @@ import ( "github.com/cs3org/reva/internal/http/services/datagateway" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" ) func (s *svc) handlePathGet(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "get") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePathGet") defer span.End() + ctx := r.Context() fn := path.Join(ns, r.URL.Path) sublog := appctx.GetLogger(ctx).With().Str("path", fn).Str("svc", "ocdav").Str("handler", "get").Logger() ref := &provider.Reference{Path: fn} - s.handleGet(ctx, w, r, ref, "simple", sublog) + s.handleGet(w, r, ref, "simple", sublog) } -func (s *svc) handleGet(ctx context.Context, w http.ResponseWriter, r *http.Request, ref *provider.Reference, dlProtocol string, log zerolog.Logger) { - client, err := s.getClient() +func (s *svc) handleGet(w http.ResponseWriter, r *http.Request, ref *provider.Reference, dlProtocol string, log zerolog.Logger) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleGet") + defer span.End() + + ctx := r.Context() + client, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -67,7 +71,7 @@ func (s *svc) handleGet(ctx context.Context, w http.ResponseWriter, r *http.Requ w.WriteHeader(http.StatusInternalServerError) return case sRes.Status.Code != rpc.Code_CODE_OK: - HandleErrorStatus(&log, w, sRes.Status) + HandleErrorStatus(ctx, &log, w, sRes.Status) return case sRes.Info.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER: log.Warn().Msg("resource is a folder and cannot be downloaded") @@ -82,7 +86,7 @@ func (s *svc) handleGet(ctx context.Context, w http.ResponseWriter, r *http.Requ w.WriteHeader(http.StatusInternalServerError) return } else if dRes.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&log, w, dRes.Status) + HandleErrorStatus(ctx, &log, w, dRes.Status) return } @@ -159,9 +163,10 @@ func (s *svc) handleGet(ctx context.Context, w http.ResponseWriter, r *http.Requ } func (s *svc) handleSpacesGet(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "spaces_get") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleSpacesGet") defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("path", r.URL.Path).Str("spaceid", spaceID).Str("handler", "get").Logger() // retrieve a specific storage space @@ -173,8 +178,8 @@ func (s *svc) handleSpacesGet(w http.ResponseWriter, r *http.Request, spaceID st } if rpcStatus.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, rpcStatus) + HandleErrorStatus(ctx, &sublog, w, rpcStatus) return } - s.handleGet(ctx, w, r, ref, "spaces", sublog) + s.handleGet(w, r, ref, "spaces", sublog) } diff --git a/internal/http/services/owncloud/ocdav/head.go b/internal/http/services/owncloud/ocdav/head.go index aee1b7a059..94125381fc 100644 --- a/internal/http/services/owncloud/ocdav/head.go +++ b/internal/http/services/owncloud/ocdav/head.go @@ -19,14 +19,13 @@ package ocdav import ( - "context" "fmt" "net/http" "path" "strconv" "time" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils/resourceid" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" @@ -38,19 +37,24 @@ import ( ) func (s *svc) handlePathHead(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "head") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePathHead") defer span.End() fn := path.Join(ns, r.URL.Path) + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger() ref := &provider.Reference{Path: fn} - s.handleHead(ctx, w, r, ref, sublog) + s.handleHead(w, r, ref, sublog) } -func (s *svc) handleHead(ctx context.Context, w http.ResponseWriter, r *http.Request, ref *provider.Reference, log zerolog.Logger) { - client, err := s.getClient() +func (s *svc) handleHead(w http.ResponseWriter, r *http.Request, ref *provider.Reference, log zerolog.Logger) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleHead") + defer span.End() + + ctx := r.Context() + client, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -66,7 +70,7 @@ func (s *svc) handleHead(ctx context.Context, w http.ResponseWriter, r *http.Req } if res.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&log, w, res.Status) + HandleErrorStatus(ctx, &log, w, res.Status) return } @@ -90,9 +94,10 @@ func (s *svc) handleHead(ctx context.Context, w http.ResponseWriter, r *http.Req } func (s *svc) handleSpacesHead(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "spaces_head") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleSpacesHead") defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("spaceid", spaceID).Str("path", r.URL.Path).Logger() spaceRef, status, err := s.lookUpStorageSpaceReference(ctx, spaceID, r.URL.Path) @@ -103,9 +108,9 @@ func (s *svc) handleSpacesHead(w http.ResponseWriter, r *http.Request, spaceID s } if status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, status) + HandleErrorStatus(ctx, &sublog, w, status) return } - s.handleHead(ctx, w, r, spaceRef, sublog) + s.handleHead(w, r, spaceRef, sublog) } diff --git a/internal/http/services/owncloud/ocdav/lock.go b/internal/http/services/owncloud/ocdav/lock.go index 65f43cf64c..63f726332d 100644 --- a/internal/http/services/owncloud/ocdav/lock.go +++ b/internal/http/services/owncloud/ocdav/lock.go @@ -22,11 +22,16 @@ import ( "net/http" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/tracing" ) // TODO(jfd) implement lock func (s *svc) handleLock(w http.ResponseWriter, r *http.Request, ns string) { - log := appctx.GetLogger(r.Context()) + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleLock") + defer span.End() + + ctx := r.Context() + log := appctx.GetLogger(ctx) xml := ` diff --git a/internal/http/services/owncloud/ocdav/meta.go b/internal/http/services/owncloud/ocdav/meta.go index 7aaffea142..18994b6598 100644 --- a/internal/http/services/owncloud/ocdav/meta.go +++ b/internal/http/services/owncloud/ocdav/meta.go @@ -22,6 +22,7 @@ import ( "net/http" "github.com/cs3org/reva/pkg/rhttp/router" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils/resourceid" ) @@ -38,6 +39,8 @@ func (h *MetaHandler) init(c *Config) error { // Handler handles requests func (h *MetaHandler) Handler(s *svc) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Meta HTTP Handler") + defer span.End() var id string id, r.URL.Path = router.ShiftPath(r.URL.Path) diff --git a/internal/http/services/owncloud/ocdav/mkcol.go b/internal/http/services/owncloud/ocdav/mkcol.go index 17cd6543fa..b259120cd8 100644 --- a/internal/http/services/owncloud/ocdav/mkcol.go +++ b/internal/http/services/owncloud/ocdav/mkcol.go @@ -19,7 +19,6 @@ package ocdav import ( - "context" "fmt" "net/http" "path" @@ -27,14 +26,15 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/rs/zerolog" ) func (s *svc) handlePathMkcol(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "mkcol") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePathMkcol") defer span.End() + ctx := r.Context() fn := path.Join(ns, r.URL.Path) for _, r := range nameRules { if !r.Test(fn) { @@ -47,13 +47,14 @@ func (s *svc) handlePathMkcol(w http.ResponseWriter, r *http.Request, ns string) parentRef := &provider.Reference{Path: path.Dir(fn)} childRef := &provider.Reference{Path: fn} - s.handleMkcol(ctx, w, r, parentRef, childRef, sublog) + s.handleMkcol(w, r, parentRef, childRef, sublog) } func (s *svc) handleSpacesMkCol(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "spaces_mkcol") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleSpacesMkCol") defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("path", r.URL.Path).Str("spaceid", spaceID).Str("handler", "mkcol").Logger() parentRef, rpcStatus, err := s.lookUpStorageSpaceReference(ctx, spaceID, path.Dir(r.URL.Path)) @@ -64,7 +65,7 @@ func (s *svc) handleSpacesMkCol(w http.ResponseWriter, r *http.Request, spaceID } if rpcStatus.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, rpcStatus) + HandleErrorStatus(ctx, &sublog, w, rpcStatus) return } @@ -76,21 +77,25 @@ func (s *svc) handleSpacesMkCol(w http.ResponseWriter, r *http.Request, spaceID } if rpcStatus.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, rpcStatus) + HandleErrorStatus(ctx, &sublog, w, rpcStatus) return } - s.handleMkcol(ctx, w, r, parentRef, childRef, sublog) + s.handleMkcol(w, r, parentRef, childRef, sublog) } -func (s *svc) handleMkcol(ctx context.Context, w http.ResponseWriter, r *http.Request, parentRef, childRef *provider.Reference, log zerolog.Logger) { +func (s *svc) handleMkcol(w http.ResponseWriter, r *http.Request, parentRef, childRef *provider.Reference, log zerolog.Logger) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleMkcol") + defer span.End() + + ctx := r.Context() if r.Body != http.NoBody { w.WriteHeader(http.StatusUnsupportedMediaType) return } - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -117,9 +122,9 @@ func (s *svc) handleMkcol(ctx context.Context, w http.ResponseWriter, r *http.Re code: SabredavNotFound, message: "Parent node does not exist", }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) } else { - HandleErrorStatus(&log, w, parentStatRes.Status) + HandleErrorStatus(ctx, &log, w, parentStatRes.Status) } return } @@ -140,9 +145,9 @@ func (s *svc) handleMkcol(ctx context.Context, w http.ResponseWriter, r *http.Re code: SabredavMethodNotAllowed, message: "The resource you tried to create already exists", }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) } else { - HandleErrorStatus(&log, w, statRes.Status) + HandleErrorStatus(ctx, &log, w, statRes.Status) } return } @@ -168,8 +173,8 @@ func (s *svc) handleMkcol(ctx context.Context, w http.ResponseWriter, r *http.Re code: SabredavPermissionDenied, message: m, }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) default: - HandleErrorStatus(&log, w, res.Status) + HandleErrorStatus(ctx, &log, w, res.Status) } } diff --git a/internal/http/services/owncloud/ocdav/move.go b/internal/http/services/owncloud/ocdav/move.go index 53d3852f8c..0c5daaefa2 100644 --- a/internal/http/services/owncloud/ocdav/move.go +++ b/internal/http/services/owncloud/ocdav/move.go @@ -19,7 +19,6 @@ package ocdav import ( - "context" "fmt" "net/http" "path" @@ -29,15 +28,16 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/router" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" ) func (s *svc) handlePathMove(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "move") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePathMove") defer span.End() + ctx := r.Context() srcPath := path.Join(ns, r.URL.Path) dstPath, err := extractDestination(r) if err != nil { @@ -63,13 +63,14 @@ func (s *svc) handlePathMove(w http.ResponseWriter, r *http.Request, ns string) ref := &provider.Reference{Path: intermediateDir} return ref, &rpc.Status{Code: rpc.Code_CODE_OK}, nil } - s.handleMove(ctx, w, r, src, dst, intermediateDirRefFunc, sublog) + s.handleMove(w, r, src, dst, intermediateDirRefFunc, sublog) } func (s *svc) handleSpacesMove(w http.ResponseWriter, r *http.Request, srcSpaceID string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "spaces_move") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleSpacesMove") defer span.End() + ctx := r.Context() dst, err := extractDestination(r) if err != nil { w.WriteHeader(http.StatusBadRequest) @@ -86,7 +87,7 @@ func (s *svc) handleSpacesMove(w http.ResponseWriter, r *http.Request, srcSpaceI } if status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, status) + HandleErrorStatus(ctx, &sublog, w, status) return } @@ -101,7 +102,7 @@ func (s *svc) handleSpacesMove(w http.ResponseWriter, r *http.Request, srcSpaceI } if status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, status) + HandleErrorStatus(ctx, &sublog, w, status) return } @@ -109,10 +110,14 @@ func (s *svc) handleSpacesMove(w http.ResponseWriter, r *http.Request, srcSpaceI intermediateDir := path.Dir(dstRelPath) return s.lookUpStorageSpaceReference(ctx, dstSpaceID, intermediateDir) } - s.handleMove(ctx, w, r, srcRef, dstRef, intermediateDirRefFunc, sublog) + s.handleMove(w, r, srcRef, dstRef, intermediateDirRefFunc, sublog) } -func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Request, src, dst *provider.Reference, intermediateDirRef intermediateDirRefFunc, log zerolog.Logger) { +func (s *svc) handleMove(w http.ResponseWriter, r *http.Request, src, dst *provider.Reference, intermediateDirRef intermediateDirRefFunc, log zerolog.Logger) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleMove") + defer span.End() + + ctx := r.Context() overwrite := r.Header.Get(HeaderOverwrite) log.Debug().Str("overwrite", overwrite).Msg("move") @@ -126,7 +131,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req return } - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -149,9 +154,9 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req code: SabredavNotFound, message: m, }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) } - HandleErrorStatus(&log, w, srcStatRes.Status) + HandleErrorStatus(ctx, &log, w, srcStatRes.Status) return } @@ -164,7 +169,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req return } if dstStatRes.Status.Code != rpc.Code_CODE_OK && dstStatRes.Status.Code != rpc.Code_CODE_NOT_FOUND { - HandleErrorStatus(&log, w, srcStatRes.Status) + HandleErrorStatus(ctx, &log, w, srcStatRes.Status) return } @@ -188,7 +193,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req } if delRes.Status.Code != rpc.Code_CODE_OK && delRes.Status.Code != rpc.Code_CODE_NOT_FOUND { - HandleErrorStatus(&log, w, delRes.Status) + HandleErrorStatus(ctx, &log, w, delRes.Status) return } } else { @@ -199,7 +204,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req w.WriteHeader(http.StatusInternalServerError) return } else if status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&log, w, status) + HandleErrorStatus(ctx, &log, w, status) return } @@ -216,7 +221,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req log.Debug().Interface("parent", dst).Interface("status", intStatRes.Status).Msg("conflict") w.WriteHeader(http.StatusConflict) } else { - HandleErrorStatus(&log, w, intStatRes.Status) + HandleErrorStatus(ctx, &log, w, intStatRes.Status) } return } @@ -239,9 +244,9 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req code: SabredavPermissionDenied, message: m, }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) } - HandleErrorStatus(&log, w, mRes.Status) + HandleErrorStatus(ctx, &log, w, mRes.Status) return } @@ -253,7 +258,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req } if dstStatRes.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&log, w, dstStatRes.Status) + HandleErrorStatus(ctx, &log, w, dstStatRes.Status) return } diff --git a/internal/http/services/owncloud/ocdav/ocdav.go b/internal/http/services/owncloud/ocdav/ocdav.go index 33020ddde2..da10533a6e 100644 --- a/internal/http/services/owncloud/ocdav/ocdav.go +++ b/internal/http/services/owncloud/ocdav/ocdav.go @@ -41,11 +41,15 @@ import ( "github.com/cs3org/reva/pkg/storage/favorite" "github.com/cs3org/reva/pkg/storage/favorite/registry" "github.com/cs3org/reva/pkg/storage/utils/templates" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/rs/zerolog" ) +const serviceName = "ocdav" +const tracerName = "ocdav" + type ctxKey int const ( @@ -116,6 +120,7 @@ func (c *Config) init() { } type svc struct { + tracing.HttpMiddleware c *Config webDavHandler *WebDavHandler davHandler *DavHandler @@ -178,9 +183,11 @@ func (s *svc) Unprotected() []string { func (s *svc) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Ocdav Service HTTP Handler") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) - addAccessHeaders(w, r) // TODO(jfd): do we need this? @@ -249,11 +256,16 @@ func (s *svc) Handler() http.Handler { }) } -func (s *svc) getClient() (gateway.GatewayAPIClient, error) { - return pool.GetGatewayServiceClient(pool.Endpoint(s.c.GatewaySvc)) +func (s *svc) getClient(ctx context.Context) (gateway.GatewayAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getClient") + defer span.End() + return pool.GetGatewayServiceClient(ctx, pool.Endpoint(s.c.GatewaySvc)) } func applyLayout(ctx context.Context, ns string, useLoggedInUserNS bool, requestPath string) string { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "applyLayout") + defer span.End() + // If useLoggedInUserNS is false, that implies that the request is coming from // the FilesHandler method invoked by a /dav/files/fileOwner where fileOwner // is not the same as the logged in user. In that case, we'll treat fileOwner @@ -270,6 +282,9 @@ func applyLayout(ctx context.Context, ns string, useLoggedInUserNS bool, request } func addAccessHeaders(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "addAccessHeaders") + defer span.End() + headers := w.Header() // the webdav api is accessible from anywhere headers.Set("Access-Control-Allow-Origin", "*") @@ -294,6 +309,9 @@ func addAccessHeaders(w http.ResponseWriter, r *http.Request) { } func extractDestination(r *http.Request) (string, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "extractDestination") + defer span.End() + dstHeader := r.Header.Get(HeaderDestination) if dstHeader == "" { return "", errors.Wrap(errInvalidValue, "destination header is empty") @@ -316,7 +334,10 @@ func extractDestination(r *http.Request) (string, error) { // replaceAllStringSubmatchFunc is taken from 'Go: Replace String with Regular Expression Callback' // see: https://elliotchance.medium.com/go-replace-string-with-regular-expression-callback-f89948bad0bb -func replaceAllStringSubmatchFunc(re *regexp.Regexp, str string, repl func([]string) string) string { +func replaceAllStringSubmatchFunc(ctx context.Context, re *regexp.Regexp, str string, repl func([]string) string) string { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "replaceAllStringSubmatchFunc") + defer span.End() + result := "" lastIndex := 0 for _, v := range re.FindAllSubmatchIndex([]byte(str), -1) { @@ -336,8 +357,11 @@ var hrefre = regexp.MustCompile(`([^A-Za-z0-9_\-.~()/:@!$])`) // // slashes (/) are treated as path-separators. // ported from https://github.com/sabre-io/http/blob/bb27d1a8c92217b34e778ee09dcf79d9a2936e84/lib/functions.php#L369-L379 -func encodePath(path string) string { - return replaceAllStringSubmatchFunc(hrefre, path, func(groups []string) string { +func encodePath(ctx context.Context, path string) string { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "encodePath") + defer span.End() + + return replaceAllStringSubmatchFunc(ctx, hrefre, path, func(groups []string) string { b := groups[1] var sb strings.Builder for i := 0; i < len(b); i++ { diff --git a/internal/http/services/owncloud/ocdav/ocdav_test.go b/internal/http/services/owncloud/ocdav/ocdav_test.go index 9cfd2b060c..b98c1468eb 100644 --- a/internal/http/services/owncloud/ocdav/ocdav_test.go +++ b/internal/http/services/owncloud/ocdav/ocdav_test.go @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -37,7 +37,7 @@ then this method alone will cost a huge amount of time. */ func BenchmarkEncodePath(b *testing.B) { for i := 0; i < b.N; i++ { - _ = encodePath("/some/path/Folder %^*(#1)") + _ = encodePath(context.Background(), "/some/path/Folder %^*(#1)") } } diff --git a/internal/http/services/owncloud/ocdav/options.go b/internal/http/services/owncloud/ocdav/options.go index e2db6fe9ae..ddb387c805 100644 --- a/internal/http/services/owncloud/ocdav/options.go +++ b/internal/http/services/owncloud/ocdav/options.go @@ -21,9 +21,14 @@ package ocdav import ( "net/http" "strings" + + "github.com/cs3org/reva/pkg/tracing" ) func (s *svc) handleOptions(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleOptions") + defer span.End() + allow := "OPTIONS, LOCK, GET, HEAD, POST, DELETE, PROPPATCH, COPY," allow += " MOVE, UNLOCK, PROPFIND, MKCOL, REPORT, SEARCH," allow += " PUT" // TODO(jfd): only for files ... but we cannot create the full path without a user ... which we only have when credentials are sent diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go index 72df362a8d..97b72f96da 100644 --- a/internal/http/services/owncloud/ocdav/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind.go @@ -45,12 +45,10 @@ import ( ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/publicshare" "github.com/cs3org/reva/pkg/share" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/codes" ) const ( @@ -70,11 +68,10 @@ const ( // ns is the namespace that is prefixed to the path in the cs3 namespace func (s *svc) handlePathPropfind(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), fmt.Sprintf("%s %v", r.Method, r.URL.Path)) + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePathPropfind") defer span.End() - span.SetAttributes(attribute.String("component", "ocdav")) - + ctx := r.Context() fn := path.Join(ns, r.URL.Path) sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger() @@ -88,18 +85,19 @@ func (s *svc) handlePathPropfind(w http.ResponseWriter, r *http.Request, ns stri ref := &provider.Reference{Path: fn} - parentInfo, resourceInfos, ok := s.getResourceInfos(ctx, w, r, pf, ref, false, sublog) + parentInfo, resourceInfos, ok := s.getResourceInfos(w, r, pf, ref, false, sublog) if !ok { // getResourceInfos handles responses in case of an error so we can just return here. return } - s.propfindResponse(ctx, w, r, ns, pf, parentInfo, resourceInfos, sublog) + s.propfindResponse(w, r, ns, pf, parentInfo, resourceInfos, sublog) } func (s *svc) handleSpacesPropfind(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "spaces_propfind") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleSpacesPropfind") defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("path", r.URL.Path).Str("spaceid", spaceID).Logger() pf, status, err := readPropfind(r.Body) @@ -118,11 +116,11 @@ func (s *svc) handleSpacesPropfind(w http.ResponseWriter, r *http.Request, space } if rpcStatus.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, rpcStatus) + HandleErrorStatus(ctx, &sublog, w, rpcStatus) return } - parentInfo, resourceInfos, ok := s.getResourceInfos(ctx, w, r, pf, ref, true, sublog) + parentInfo, resourceInfos, ok := s.getResourceInfos(w, r, pf, ref, true, sublog) if !ok { // getResourceInfos handles responses in case of an error so we can just return here. return @@ -140,14 +138,15 @@ func (s *svc) handleSpacesPropfind(w http.ResponseWriter, r *http.Request, space resourceInfos[i].Path = path.Join("/", spaceID, resourceInfos[i].Path) } - s.propfindResponse(ctx, w, r, "", pf, parentInfo, resourceInfos, sublog) + s.propfindResponse(w, r, "", pf, parentInfo, resourceInfos, sublog) } -func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *http.Request, namespace string, pf propfindXML, parentInfo *provider.ResourceInfo, resourceInfos []*provider.ResourceInfo, log zerolog.Logger) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(ctx, "propfind_response") +func (s *svc) propfindResponse(w http.ResponseWriter, r *http.Request, namespace string, pf propfindXML, parentInfo *provider.ResourceInfo, resourceInfos []*provider.ResourceInfo, log zerolog.Logger) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "propfindResponse") defer span.End() + ctx := r.Context() linkFilters := make([]*link.ListPublicSharesRequest_Filter, 0, len(resourceInfos)) shareFilters := make([]*collaboration.Filter, 0, len(resourceInfos)) for i := range resourceInfos { @@ -155,7 +154,7 @@ func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *ht shareFilters = append(shareFilters, share.ResourceIDFilter(resourceInfos[i].Id)) } - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -178,7 +177,6 @@ func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *ht } } else { log.Error().Err(err).Msg("propfindResponse: couldn't list public shares") - span.SetStatus(codes.Error, err.Error()) } var usershares map[string]struct{} @@ -197,7 +195,6 @@ func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *ht } } else { log.Error().Err(err).Msg("propfindResponse: couldn't list user shares") - span.SetStatus(codes.Error, err.Error()) } propRes, err := s.multistatusResponse(ctx, &pf, resourceInfos, namespace, usershares, linkshares) @@ -228,7 +225,11 @@ func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *ht } } -func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *http.Request, pf propfindXML, ref *provider.Reference, spacesPropfind bool, log zerolog.Logger) (*provider.ResourceInfo, []*provider.ResourceInfo, bool) { +func (s *svc) getResourceInfos(w http.ResponseWriter, r *http.Request, pf propfindXML, ref *provider.Reference, spacesPropfind bool, log zerolog.Logger) (*provider.ResourceInfo, []*provider.ResourceInfo, bool) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "getResourceInfos") + defer span.End() + + ctx := r.Context() depth := r.Header.Get(HeaderDepth) if depth == "" { depth = "1" @@ -242,11 +243,11 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht code: SabredavBadRequest, message: m, }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) return nil, nil, false } - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -286,10 +287,10 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht code: SabredavNotFound, message: m, }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) return nil, nil, false } - HandleErrorStatus(&log, w, res.Status) + HandleErrorStatus(ctx, &log, w, res.Status) return nil, nil, false } @@ -322,10 +323,10 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht code: SabredavNotFound, message: m, }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) return nil, nil, false } - HandleErrorStatus(&log, w, parentRes.Status) + HandleErrorStatus(ctx, &log, w, parentRes.Status) return nil, nil, false } parentInfo = parentRes.Info @@ -343,7 +344,7 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht } if res.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&log, w, res.Status) + HandleErrorStatus(ctx, &log, w, res.Status) return nil, nil, false } resourceInfos = append(resourceInfos, res.Infos...) @@ -376,7 +377,7 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht return nil, nil, false } if res.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&log, w, res.Status) + HandleErrorStatus(ctx, &log, w, res.Status) return nil, nil, false } @@ -462,6 +463,9 @@ func readPropfind(r io.Reader) (pf propfindXML, status int, err error) { } func (s *svc) multistatusResponse(ctx context.Context, pf *propfindXML, mds []*provider.ResourceInfo, ns string, usershares, linkshares map[string]struct{}) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "multistatusResponse") + defer span.End() + responses := make([]*responseXML, 0, len(mds)) for i := range mds { res, err := s.mdToPropResponse(ctx, pf, mds[i], ns, usershares, linkshares) @@ -517,6 +521,9 @@ func (s *svc) newPropRaw(key, val string) *propertyXML { // ns is the CS3 namespace that needs to be removed from the CS3 path before // prefixing it with the baseURI func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provider.ResourceInfo, ns string, usershares, linkshares map[string]struct{}) (*responseXML, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "mdToPropResponse") + defer span.End() + sublog := appctx.GetLogger(ctx).With().Str("ns", ns).Logger() md.Path = strings.TrimPrefix(md.Path, ns) @@ -528,7 +535,7 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide } response := responseXML{ - Href: encodePath(ref), + Href: encodePath(ctx, ref), Propstat: []propstatXML{}, } @@ -1034,6 +1041,9 @@ func quoteEtag(etag string) string { // a file is only yours if you are the owner func isCurrentUserOwner(ctx context.Context, owner *userv1beta1.UserId) bool { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "isCurrentUserOwner") + defer span.End() + contextUser, ok := ctxpkg.ContextGetUser(ctx) if ok && contextUser.Id != nil && owner != nil && contextUser.Id.Idp == owner.Idp && diff --git a/internal/http/services/owncloud/ocdav/proppatch.go b/internal/http/services/owncloud/ocdav/proppatch.go index 77c39673f7..ea2bd03d6e 100644 --- a/internal/http/services/owncloud/ocdav/proppatch.go +++ b/internal/http/services/owncloud/ocdav/proppatch.go @@ -31,15 +31,16 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" ctxpkg "github.com/cs3org/reva/pkg/ctx" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" "github.com/rs/zerolog" ) func (s *svc) handlePathProppatch(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "proppatch") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePathProppatch") defer span.End() + ctx := r.Context() fn := path.Join(ns, r.URL.Path) sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger() @@ -53,11 +54,11 @@ func (s *svc) handlePathProppatch(w http.ResponseWriter, r *http.Request, ns str code: SabredavBadRequest, message: m, }) - HandleWebdavError(&sublog, w, b, err) + HandleWebdavError(ctx, &sublog, w, b, err) return } - c, err := s.getClient() + c, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -82,13 +83,13 @@ func (s *svc) handlePathProppatch(w http.ResponseWriter, r *http.Request, ns str code: SabredavNotFound, message: m, }) - HandleWebdavError(&sublog, w, b, err) + HandleWebdavError(ctx, &sublog, w, b, err) } - HandleErrorStatus(&sublog, w, statRes.Status) + HandleErrorStatus(ctx, &sublog, w, statRes.Status) return } - acceptedProps, removedProps, ok := s.handleProppatch(ctx, w, r, ref, pp, sublog) + acceptedProps, removedProps, ok := s.handleProppatch(w, r, ref, pp, sublog) if !ok { // handleProppatch handles responses in error cases so we can just return return @@ -100,13 +101,14 @@ func (s *svc) handlePathProppatch(w http.ResponseWriter, r *http.Request, ns str nRef += "/" } - s.handleProppatchResponse(ctx, w, r, acceptedProps, removedProps, nRef, sublog) + s.handleProppatchResponse(w, r, acceptedProps, removedProps, nRef, sublog) } func (s *svc) handleSpacesProppatch(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "spaces_proppatch") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleSpacesProppatch") defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("path", r.URL.Path).Str("spaceid", spaceID).Logger() pp, status, err := readProppatch(r.Body) @@ -125,11 +127,11 @@ func (s *svc) handleSpacesProppatch(w http.ResponseWriter, r *http.Request, spac } if rpcStatus.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, rpcStatus) + HandleErrorStatus(ctx, &sublog, w, rpcStatus) return } - c, err := s.getClient() + c, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -147,11 +149,11 @@ func (s *svc) handleSpacesProppatch(w http.ResponseWriter, r *http.Request, spac } if statRes.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, statRes.Status) + HandleErrorStatus(ctx, &sublog, w, statRes.Status) return } - acceptedProps, removedProps, ok := s.handleProppatch(ctx, w, r, ref, pp, sublog) + acceptedProps, removedProps, ok := s.handleProppatch(w, r, ref, pp, sublog) if !ok { // handleProppatch handles responses in error cases so we can just return return @@ -163,11 +165,15 @@ func (s *svc) handleSpacesProppatch(w http.ResponseWriter, r *http.Request, spac nRef += "/" } - s.handleProppatchResponse(ctx, w, r, acceptedProps, removedProps, nRef, sublog) + s.handleProppatchResponse(w, r, acceptedProps, removedProps, nRef, sublog) } -func (s *svc) handleProppatch(ctx context.Context, w http.ResponseWriter, r *http.Request, ref *provider.Reference, patches []Proppatch, log zerolog.Logger) ([]xml.Name, []xml.Name, bool) { - c, err := s.getClient() +func (s *svc) handleProppatch(w http.ResponseWriter, r *http.Request, ref *provider.Reference, patches []Proppatch, log zerolog.Logger) ([]xml.Name, []xml.Name, bool) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleProppatch") + defer span.End() + + ctx := r.Context() + c, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -227,10 +233,10 @@ func (s *svc) handleProppatch(ctx context.Context, w http.ResponseWriter, r *htt code: SabredavPermissionDenied, message: m, }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) return nil, nil, false } - HandleErrorStatus(&log, w, res.Status) + HandleErrorStatus(ctx, &log, w, res.Status) return nil, nil, false } if key == "http://owncloud.org/ns/favorite" { @@ -264,10 +270,10 @@ func (s *svc) handleProppatch(ctx context.Context, w http.ResponseWriter, r *htt code: SabredavPermissionDenied, message: m, }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) return nil, nil, false } - HandleErrorStatus(&log, w, res.Status) + HandleErrorStatus(ctx, &log, w, res.Status) return nil, nil, false } @@ -297,7 +303,11 @@ func (s *svc) handleProppatch(ctx context.Context, w http.ResponseWriter, r *htt return acceptedProps, removedProps, true } -func (s *svc) handleProppatchResponse(ctx context.Context, w http.ResponseWriter, r *http.Request, acceptedProps, removedProps []xml.Name, path string, log zerolog.Logger) { +func (s *svc) handleProppatchResponse(w http.ResponseWriter, r *http.Request, acceptedProps, removedProps []xml.Name, path string, log zerolog.Logger) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleProppatchResponse") + defer span.End() + + ctx := r.Context() propRes, err := s.formatProppatchResponse(ctx, acceptedProps, removedProps, path) if err != nil { log.Error().Err(err).Msg("error formatting proppatch response") @@ -313,9 +323,12 @@ func (s *svc) handleProppatchResponse(ctx context.Context, w http.ResponseWriter } func (s *svc) formatProppatchResponse(ctx context.Context, acceptedProps []xml.Name, removedProps []xml.Name, ref string) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "formatProppatchResponse") + defer span.End() + responses := make([]responseXML, 0, 1) response := responseXML{ - Href: encodePath(ref), + Href: encodePath(ctx, ref), Propstat: []propstatXML{}, } diff --git a/internal/http/services/owncloud/ocdav/publicfile.go b/internal/http/services/owncloud/ocdav/publicfile.go index d5b6c54c9a..83a32d5d41 100644 --- a/internal/http/services/owncloud/ocdav/publicfile.go +++ b/internal/http/services/owncloud/ocdav/publicfile.go @@ -27,7 +27,7 @@ import ( typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/router" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" ) // PublicFileHandler handles requests on a shared file. it needs to be wrapped in a collection @@ -43,7 +43,11 @@ func (h *PublicFileHandler) init(ns string) error { // Handler handles requests func (h *PublicFileHandler) Handler(s *svc) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - log := appctx.GetLogger(r.Context()) + r, span := tracing.SpanStartFromRequest(r, tracerName, "PublicFile HTTP Handler") + defer span.End() + + ctx := r.Context() + log := appctx.GetLogger(ctx) _, relativePath := router.ShiftPath(r.URL.Path) log.Debug().Str("relativePath", relativePath).Msg("PublicFileHandler func") @@ -86,14 +90,15 @@ func (h *PublicFileHandler) Handler(s *svc) http.Handler { } func (s *svc) adjustResourcePathInURL(w http.ResponseWriter, r *http.Request) bool { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "adjustResourcePathInURL") + r, span := tracing.SpanStartFromRequest(r, tracerName, "adjustResourcePathInURL") defer span.End() + ctx := r.Context() // find actual file name tokenStatInfo := ctx.Value(tokenStatInfoKey{}).(*provider.ResourceInfo) sublog := appctx.GetLogger(ctx).With().Interface("tokenStatInfo", tokenStatInfo).Logger() - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -108,7 +113,7 @@ func (s *svc) adjustResourcePathInURL(w http.ResponseWriter, r *http.Request) bo return false } if pathRes.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, pathRes.Status) + HandleErrorStatus(ctx, &sublog, w, pathRes.Status) return false } if path.Base(r.URL.Path) != path.Base(pathRes.Path) { @@ -125,9 +130,10 @@ func (s *svc) adjustResourcePathInURL(w http.ResponseWriter, r *http.Request) bo // ns is the namespace that is prefixed to the path in the cs3 namespace func (s *svc) handlePropfindOnToken(w http.ResponseWriter, r *http.Request, ns string, onContainer bool) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "token_propfind") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePropfindOnToken") defer span.End() + ctx := r.Context() tokenStatInfo := ctx.Value(tokenStatInfoKey{}).(*provider.ResourceInfo) sublog := appctx.GetLogger(ctx).With().Interface("tokenStatInfo", tokenStatInfo).Logger() sublog.Debug().Msg("handlePropfindOnToken") @@ -151,7 +157,7 @@ func (s *svc) handlePropfindOnToken(w http.ResponseWriter, r *http.Request, ns s return } - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -168,7 +174,7 @@ func (s *svc) handlePropfindOnToken(w http.ResponseWriter, r *http.Request, ns s return } if pathRes.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, pathRes.Status) + HandleErrorStatus(ctx, &sublog, w, pathRes.Status) return } diff --git a/internal/http/services/owncloud/ocdav/put.go b/internal/http/services/owncloud/ocdav/put.go index 1114d604f6..3414bd0a78 100644 --- a/internal/http/services/owncloud/ocdav/put.go +++ b/internal/http/services/owncloud/ocdav/put.go @@ -19,7 +19,6 @@ package ocdav import ( - "context" "net/http" "path" "strconv" @@ -34,13 +33,16 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/storage/utils/chunking" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" ) func sufferMacOSFinder(r *http.Request) bool { + r, span := tracing.SpanStartFromRequest(r, tracerName, "sufferMacOSFinder") + defer span.End() + return r.Header.Get(HeaderExpectedEntityLength) != "" } @@ -61,8 +63,11 @@ func handleMacOSFinder(w http.ResponseWriter, r *http.Request) error { but we don't get a request body we will fail the request to protect the end-user. */ + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleMacOSFinder") + defer span.End() - log := appctx.GetLogger(r.Context()) + ctx := r.Context() + log := appctx.GetLogger(ctx) content := r.Header.Get(HeaderContentLength) expected := r.Header.Get(HeaderExpectedEntityLength) log.Warn().Str("content-length", content).Str("x-expected-entity-length", expected).Msg("Mac OS Finder corner-case detected") @@ -102,23 +107,30 @@ func isContentRange(r *http.Request) bool { in unexpected behaviour (cf PEAR::HTTP_WebDAV_Client 1.0.1), we reject all PUT requests with a Content-Range for now. */ + r, span := tracing.SpanStartFromRequest(r, tracerName, "isContentRange") + defer span.End() return r.Header.Get(HeaderContentRange) != "" } func (s *svc) handlePathPut(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "put") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePathPut") defer span.End() + ctx := r.Context() fn := path.Join(ns, r.URL.Path) sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger() ref := &provider.Reference{Path: fn} - s.handlePut(ctx, w, r, ref, sublog) + s.handlePut(w, r, ref, sublog) } -func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Request, ref *provider.Reference, log zerolog.Logger) { +func (s *svc) handlePut(w http.ResponseWriter, r *http.Request, ref *provider.Reference, log zerolog.Logger) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePut") + defer span.End() + + ctx := r.Context() if !checkPreconditions(w, r, log) { // checkPreconditions handles error returns return @@ -130,7 +142,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ return } - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -145,7 +157,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ return } if sRes.Status.Code != rpc.Code_CODE_OK && sRes.Status.Code != rpc.Code_CODE_NOT_FOUND { - HandleErrorStatus(&log, w, sRes.Status) + HandleErrorStatus(ctx, &log, w, sRes.Status) return } @@ -235,11 +247,11 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ code: SabredavPermissionDenied, message: "permission denied: you have no permission to upload content", }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) case rpc.Code_CODE_NOT_FOUND: w.WriteHeader(http.StatusConflict) default: - HandleErrorStatus(&log, w, uRes.Status) + HandleErrorStatus(ctx, &log, w, uRes.Status) } return } @@ -276,7 +288,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ code: SabredavBadRequest, message: "The computed checksum does not match the one received from the client.", }) - HandleWebdavError(&log, w, b, err) + HandleWebdavError(ctx, &log, w, b, err) return } log.Error().Err(err).Msg("PUT request to data server failed") @@ -307,7 +319,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ } if sRes.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&log, w, sRes.Status) + HandleErrorStatus(ctx, &log, w, sRes.Status) return } @@ -332,9 +344,10 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ } func (s *svc) handleSpacesPut(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "spaces_put") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleSpacesPut") defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("spaceid", spaceID).Str("path", r.URL.Path).Logger() spaceRef, status, err := s.lookUpStorageSpaceReference(ctx, spaceID, r.URL.Path) @@ -345,14 +358,17 @@ func (s *svc) handleSpacesPut(w http.ResponseWriter, r *http.Request, spaceID st } if status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, status) + HandleErrorStatus(ctx, &sublog, w, status) return } - s.handlePut(ctx, w, r, spaceRef, sublog) + s.handlePut(w, r, spaceRef, sublog) } func checkPreconditions(w http.ResponseWriter, r *http.Request, log zerolog.Logger) bool { + r, span := tracing.SpanStartFromRequest(r, tracerName, "checkPreconditions") + defer span.End() + if isContentRange(r) { log.Debug().Msg("Content-Range not supported for PUT") w.WriteHeader(http.StatusNotImplemented) @@ -371,6 +387,9 @@ func checkPreconditions(w http.ResponseWriter, r *http.Request, log zerolog.Logg } func getContentLength(w http.ResponseWriter, r *http.Request) (int64, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "getContentLength") + defer span.End() + length, err := strconv.ParseInt(r.Header.Get(HeaderContentLength), 10, 64) if err != nil { // Fallback to Upload-Length diff --git a/internal/http/services/owncloud/ocdav/redirect.go b/internal/http/services/owncloud/ocdav/redirect.go index 0e3d0bc9c3..04754d5a4b 100644 --- a/internal/http/services/owncloud/ocdav/redirect.go +++ b/internal/http/services/owncloud/ocdav/redirect.go @@ -22,9 +22,14 @@ import ( "net/http" "net/url" "path" + + "github.com/cs3org/reva/pkg/tracing" ) func (s *svc) handleLegacyPath(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleLegacyPath") + defer span.End() + query := r.URL.Query() dir := query.Get("dir") url := s.c.PublicURL + path.Join("#", "/files/list/all", url.PathEscape(dir)) diff --git a/internal/http/services/owncloud/ocdav/report.go b/internal/http/services/owncloud/ocdav/report.go index da921905af..0b9d17c79e 100644 --- a/internal/http/services/owncloud/ocdav/report.go +++ b/internal/http/services/owncloud/ocdav/report.go @@ -29,6 +29,7 @@ import ( providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/tracing" ) const ( @@ -37,6 +38,9 @@ const ( ) func (s *svc) handleReport(w http.ResponseWriter, r *http.Request, ns string) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleReport") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) // fn := path.Join(ns, r.URL.Path) @@ -63,9 +67,12 @@ func (s *svc) handleReport(w http.ResponseWriter, r *http.Request, ns string) { } func (s *svc) doSearchFiles(w http.ResponseWriter, r *http.Request, sf *reportSearchFiles) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "doSearchFiles") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) - _, err := s.getClient() + _, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -75,6 +82,9 @@ func (s *svc) doSearchFiles(w http.ResponseWriter, r *http.Request, sf *reportSe } func (s *svc) doFilterFiles(w http.ResponseWriter, r *http.Request, ff *reportFilterFiles, namespace string) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "doFilterFiles") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) @@ -88,7 +98,7 @@ func (s *svc) doFilterFiles(w http.ResponseWriter, r *http.Request, ff *reportFi return } - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting gateway client") w.WriteHeader(http.StatusInternalServerError) diff --git a/internal/http/services/owncloud/ocdav/spaces.go b/internal/http/services/owncloud/ocdav/spaces.go index 36d31f5f57..220f543ff8 100644 --- a/internal/http/services/owncloud/ocdav/spaces.go +++ b/internal/http/services/owncloud/ocdav/spaces.go @@ -26,6 +26,7 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" storageProvider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/rhttp/router" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" ) @@ -44,6 +45,8 @@ func (h *SpacesHandler) Handler(s *svc) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // ctx := r.Context() // log := appctx.GetLogger(ctx) + r, span := tracing.SpanStartFromRequest(r, tracerName, "Spaces HTTP Handler") + defer span.End() if r.Method == http.MethodOptions { s.handleOptions(w, r) @@ -95,8 +98,11 @@ func (h *SpacesHandler) Handler(s *svc) http.Handler { } func (s *svc) lookUpStorageSpaceReference(ctx context.Context, spaceID string, relativePath string) (*storageProvider.Reference, *rpc.Status, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "lookUpStorageSpaceReference") + defer span.End() + // Get the getway client - gatewayClient, err := s.getClient() + gatewayClient, err := s.getClient(ctx) if err != nil { return nil, nil, err } diff --git a/internal/http/services/owncloud/ocdav/status.go b/internal/http/services/owncloud/ocdav/status.go index 54d8c387b8..d66cfe14eb 100644 --- a/internal/http/services/owncloud/ocdav/status.go +++ b/internal/http/services/owncloud/ocdav/status.go @@ -24,10 +24,15 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/data" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/tracing" ) func (s *svc) doStatus(w http.ResponseWriter, r *http.Request) { - log := appctx.GetLogger(r.Context()) + r, span := tracing.SpanStartFromRequest(r, tracerName, "doStatus") + defer span.End() + + ctx := r.Context() + log := appctx.GetLogger(ctx) status := &data.Status{ Installed: true, Maintenance: false, diff --git a/internal/http/services/owncloud/ocdav/tpc.go b/internal/http/services/owncloud/ocdav/tpc.go index c31b6066a4..debbd27462 100644 --- a/internal/http/services/owncloud/ocdav/tpc.go +++ b/internal/http/services/owncloud/ocdav/tpc.go @@ -19,7 +19,6 @@ package ocdav import ( - "context" "fmt" "io" "net/http" @@ -36,6 +35,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rhttp" + "github.com/cs3org/reva/pkg/tracing" ) const ( @@ -115,7 +115,11 @@ func (wc *WriteCounter) Write(p []byte) (int, error) { // handleTPCPull performs a GET request on the remote site and upload it // the requested reva endpoint. -func (s *svc) handleTPCPull(ctx context.Context, w http.ResponseWriter, r *http.Request, ns string) { +func (s *svc) handleTPCPull(w http.ResponseWriter, r *http.Request, ns string) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleTPCPull") + defer span.End() + + ctx := r.Context() src := r.Header.Get("Source") dst := path.Join(ns, r.URL.Path) sublog := appctx.GetLogger(ctx).With().Str("src", src).Str("dst", dst).Logger() @@ -129,13 +133,13 @@ func (s *svc) handleTPCPull(ctx context.Context, w http.ResponseWriter, r *http. code: SabredavBadRequest, message: m, }) - HandleWebdavError(&sublog, w, b, err) + HandleWebdavError(ctx, &sublog, w, b, err) return } sublog.Debug().Str("overwrite", overwrite).Msg("TPC Pull") // get Gateway client - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -152,7 +156,7 @@ func (s *svc) handleTPCPull(ctx context.Context, w http.ResponseWriter, r *http. return } if dstStatRes.Status.Code != rpc.Code_CODE_OK && dstStatRes.Status.Code != rpc.Code_CODE_NOT_FOUND { - HandleErrorStatus(&sublog, w, dstStatRes.Status) + HandleErrorStatus(ctx, &sublog, w, dstStatRes.Status) return } if dstStatRes.Status.Code == rpc.Code_CODE_OK && overwrite == "F" { @@ -161,7 +165,7 @@ func (s *svc) handleTPCPull(ctx context.Context, w http.ResponseWriter, r *http. return } - err = s.performHTTPPull(ctx, client, r, w, ns) + err = s.performHTTPPull(client, r, w, ns) if err != nil { sublog.Error().Err(err).Msg("error performing TPC Pull") return @@ -169,7 +173,11 @@ func (s *svc) handleTPCPull(ctx context.Context, w http.ResponseWriter, r *http. fmt.Fprintf(w, "success: Created") } -func (s *svc) performHTTPPull(ctx context.Context, client gateway.GatewayAPIClient, r *http.Request, w http.ResponseWriter, ns string) error { +func (s *svc) performHTTPPull(client gateway.GatewayAPIClient, r *http.Request, w http.ResponseWriter, ns string) error { + r, span := tracing.SpanStartFromRequest(r, tracerName, "performHTTPPull") + defer span.End() + + ctx := r.Context() src := r.Header.Get("Source") dst := path.Join(ns, r.URL.Path) sublog := appctx.GetLogger(ctx) @@ -277,7 +285,11 @@ func (s *svc) performHTTPPull(ctx context.Context, client gateway.GatewayAPIClie // handleTPCPush performs a PUT request on the remote site and while downloading // data from the requested reva endpoint. -func (s *svc) handleTPCPush(ctx context.Context, w http.ResponseWriter, r *http.Request, ns string) { +func (s *svc) handleTPCPush(w http.ResponseWriter, r *http.Request, ns string) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleTPCPush") + defer span.End() + + ctx := r.Context() src := path.Join(ns, r.URL.Path) dst := r.Header.Get("Destination") sublog := appctx.GetLogger(ctx).With().Str("src", src).Str("dst", dst).Logger() @@ -291,14 +303,14 @@ func (s *svc) handleTPCPush(ctx context.Context, w http.ResponseWriter, r *http. code: SabredavBadRequest, message: m, }) - HandleWebdavError(&sublog, w, b, err) + HandleWebdavError(ctx, &sublog, w, b, err) return } sublog.Debug().Str("overwrite", overwrite).Msg("TPC Push") // get Gateway client - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -314,7 +326,7 @@ func (s *svc) handleTPCPush(ctx context.Context, w http.ResponseWriter, r *http. return } if srcStatRes.Status.Code != rpc.Code_CODE_OK && srcStatRes.Status.Code != rpc.Code_CODE_NOT_FOUND { - HandleErrorStatus(&sublog, w, srcStatRes.Status) + HandleErrorStatus(ctx, &sublog, w, srcStatRes.Status) return } if srcStatRes.Info.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER { @@ -323,7 +335,7 @@ func (s *svc) handleTPCPush(ctx context.Context, w http.ResponseWriter, r *http. return } - err = s.performHTTPPush(ctx, client, r, w, srcStatRes.Info, ns) + err = s.performHTTPPush(client, r, w, srcStatRes.Info, ns) if err != nil { sublog.Error().Err(err).Msg("error performing TPC Push") return @@ -331,7 +343,11 @@ func (s *svc) handleTPCPush(ctx context.Context, w http.ResponseWriter, r *http. fmt.Fprintf(w, "success: Created") } -func (s *svc) performHTTPPush(ctx context.Context, client gateway.GatewayAPIClient, r *http.Request, w http.ResponseWriter, srcInfo *provider.ResourceInfo, ns string) error { +func (s *svc) performHTTPPush(client gateway.GatewayAPIClient, r *http.Request, w http.ResponseWriter, srcInfo *provider.ResourceInfo, ns string) error { + r, span := tracing.SpanStartFromRequest(r, tracerName, "performHTTPPush") + defer span.End() + + ctx := r.Context() src := path.Join(ns, r.URL.Path) dst := r.Header.Get("Destination") diff --git a/internal/http/services/owncloud/ocdav/trashbin.go b/internal/http/services/owncloud/ocdav/trashbin.go index 3cdd91a6ac..2b212e582f 100644 --- a/internal/http/services/owncloud/ocdav/trashbin.go +++ b/internal/http/services/owncloud/ocdav/trashbin.go @@ -29,7 +29,7 @@ import ( "strings" "time" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils/resourceid" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" @@ -55,6 +55,9 @@ func (h *TrashbinHandler) init(c *Config) error { // Handler handles requests func (h *TrashbinHandler) Handler(s *svc) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Trashbin HTTP Handler") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) @@ -106,7 +109,7 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler { // If not, we user the user home to route the request basePath := r.URL.Query().Get("base_path") if basePath == "" { - gc, err := pool.GetGatewayServiceClient(pool.Endpoint(s.c.GatewaySvc)) + gc, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(s.c.GatewaySvc)) if err != nil { // TODO(jfd) how do we make the user aware that some storages are not available? // opaque response property? Or a list of errors? @@ -123,7 +126,7 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler { return } if getHomeRes.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(log, w, getHomeRes.Status) + HandleErrorStatus(ctx, log, w, getHomeRes.Status) return } basePath = getHomeRes.Path @@ -164,9 +167,10 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler { } func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s *svc, u *userpb.User, basePath, key, itemPath string) { - ctx, span := rtrace.Provider.Tracer("trash-bin").Start(r.Context(), "list_trashbin") + r, span := tracing.SpanStartFromRequest(r, tracerName, "listTrashbin") defer span.End() + ctx := r.Context() depth := r.Header.Get(HeaderDepth) if depth == "" { depth = "1" @@ -206,7 +210,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s return } - gc, err := pool.GetGatewayServiceClient(pool.Endpoint(s.c.GatewaySvc)) + gc, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(s.c.GatewaySvc)) if err != nil { // TODO(jfd) how do we make the user aware that some storages are not available? // opaque response property? Or a list of errors? @@ -226,7 +230,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s } if getRecycleRes.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, getRecycleRes.Status) + HandleErrorStatus(ctx, &sublog, w, getRecycleRes.Status) return } @@ -253,7 +257,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s } if getRecycleRes.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, getRecycleRes.Status) + HandleErrorStatus(ctx, &sublog, w, getRecycleRes.Status) return } items = append(items, getRecycleRes.RecycleItems...) @@ -287,10 +291,13 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s } func (h *TrashbinHandler) formatTrashPropfind(ctx context.Context, s *svc, u *userpb.User, pf *propfindXML, items []*provider.RecycleItem, basePath string) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "formatTrashPropfind") + defer span.End() + responses := make([]*responseXML, 0, len(items)+1) // add trashbin dir . entry responses = append(responses, &responseXML{ - Href: encodePath(ctx.Value(ctxKeyBaseURI).(string) + "/"), // url encode response.Href TODO + Href: encodePath(ctx, ctx.Value(ctxKeyBaseURI).(string)+"/"), // url encode response.Href TODO Propstat: []propstatXML{ { Status: "HTTP/1.1 200 OK", @@ -332,6 +339,8 @@ func (h *TrashbinHandler) formatTrashPropfind(ctx context.Context, s *svc, u *us // the key is the name of an entry in the trash listing // for now we need to limit trash to the users home, so we can expect all trash keys to have the home storage as the opaque id func (h *TrashbinHandler) itemToPropResponse(ctx context.Context, s *svc, u *userpb.User, pf *propfindXML, item *provider.RecycleItem, basePath string) (*responseXML, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "itemToPropResponse") + defer span.End() baseURI := ctx.Value(ctxKeyBaseURI).(string) ref := path.Join(baseURI, u.Username, item.Key) @@ -340,7 +349,7 @@ func (h *TrashbinHandler) itemToPropResponse(ctx context.Context, s *svc, u *use } response := responseXML{ - Href: encodePath(ref), // url encode response.Href + Href: encodePath(ctx, ref), // url encode response.Href Propstat: []propstatXML{}, } @@ -442,9 +451,10 @@ func (h *TrashbinHandler) itemToPropResponse(ctx context.Context, s *svc, u *use } func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc, u *userpb.User, basePath, dst, key, itemPath string) { - ctx, span := rtrace.Provider.Tracer("trash-bin").Start(r.Context(), "restore") + r, span := tracing.SpanStartFromRequest(r, tracerName, "restore") defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Logger() overwrite := r.Header.Get(HeaderOverwrite) @@ -459,7 +469,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc return } - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -482,7 +492,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc } if dstStatRes.Status.Code != rpc.Code_CODE_OK && dstStatRes.Status.Code != rpc.Code_CODE_NOT_FOUND { - HandleErrorStatus(&sublog, w, dstStatRes.Status) + HandleErrorStatus(ctx, &sublog, w, dstStatRes.Status) return } @@ -501,7 +511,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc } if parentStatResponse.Status.Code == rpc.Code_CODE_NOT_FOUND { - HandleErrorStatus(&sublog, w, &rpc.Status{Code: rpc.Code_CODE_FAILED_PRECONDITION}) + HandleErrorStatus(ctx, &sublog, w, &rpc.Status{Code: rpc.Code_CODE_FAILED_PRECONDITION}) return } } @@ -518,7 +528,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc message: "The destination node already exists, and the overwrite header is set to false", header: HeaderOverwrite, }) - HandleWebdavError(&sublog, w, b, err) + HandleWebdavError(ctx, &sublog, w, b, err) return } // delete existing tree @@ -531,7 +541,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc } if delRes.Status.Code != rpc.Code_CODE_OK && delRes.Status.Code != rpc.Code_CODE_NOT_FOUND { - HandleErrorStatus(&sublog, w, delRes.Status) + HandleErrorStatus(ctx, &sublog, w, delRes.Status) return } } @@ -562,9 +572,9 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc code: SabredavPermissionDenied, message: "Permission denied to restore", }) - HandleWebdavError(&sublog, w, b, err) + HandleWebdavError(ctx, &sublog, w, b, err) } - HandleErrorStatus(&sublog, w, res.Status) + HandleErrorStatus(ctx, &sublog, w, res.Status) return } @@ -575,7 +585,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc return } if dstStatRes.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, dstStatRes.Status) + HandleErrorStatus(ctx, &sublog, w, dstStatRes.Status) return } @@ -590,12 +600,13 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc // delete has only a key func (h *TrashbinHandler) delete(w http.ResponseWriter, r *http.Request, s *svc, u *userpb.User, basePath, key, itemPath string) { - ctx, span := rtrace.Provider.Tracer("trash-bin").Start(r.Context(), "erase") + r, span := tracing.SpanStartFromRequest(r, tracerName, "delete") defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("key", key).Logger() - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -629,7 +640,7 @@ func (h *TrashbinHandler) delete(w http.ResponseWriter, r *http.Request, s *svc, code: SabredavConflict, message: m, }) - HandleWebdavError(&sublog, w, b, err) + HandleWebdavError(ctx, &sublog, w, b, err) case rpc.Code_CODE_PERMISSION_DENIED: w.WriteHeader(http.StatusForbidden) var m string @@ -642,9 +653,9 @@ func (h *TrashbinHandler) delete(w http.ResponseWriter, r *http.Request, s *svc, code: SabredavPermissionDenied, message: m, }) - HandleWebdavError(&sublog, w, b, err) + HandleWebdavError(ctx, &sublog, w, b, err) default: - HandleErrorStatus(&sublog, w, res.Status) + HandleErrorStatus(ctx, &sublog, w, res.Status) } } diff --git a/internal/http/services/owncloud/ocdav/tus.go b/internal/http/services/owncloud/ocdav/tus.go index 5a57032050..aeeafd1b5e 100644 --- a/internal/http/services/owncloud/ocdav/tus.go +++ b/internal/http/services/owncloud/ocdav/tus.go @@ -19,7 +19,6 @@ package ocdav import ( - "context" "encoding/json" "net/http" "path" @@ -34,7 +33,7 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" @@ -42,9 +41,10 @@ import ( ) func (s *svc) handlePathTusPost(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "tus-post") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePathTusPost") defer span.End() + ctx := r.Context() // read filename from metadata meta := tusd.ParseMetadataHeader(r.Header.Get(HeaderUploadMetadata)) for _, r := range nameRules { @@ -61,13 +61,14 @@ func (s *svc) handlePathTusPost(w http.ResponseWriter, r *http.Request, ns strin // check tus headers? ref := &provider.Reference{Path: fn} - s.handleTusPost(ctx, w, r, meta, ref, sublog) + s.handleTusPost(w, r, meta, ref, sublog) } func (s *svc) handleSpacesTusPost(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "spaces-tus-post") + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleSpacesTusPost") defer span.End() + ctx := r.Context() // read filename from metadata meta := tusd.ParseMetadataHeader(r.Header.Get(HeaderUploadMetadata)) if meta["filename"] == "" { @@ -84,14 +85,18 @@ func (s *svc) handleSpacesTusPost(w http.ResponseWriter, r *http.Request, spaceI return } if status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, status) + HandleErrorStatus(ctx, &sublog, w, status) return } - s.handleTusPost(ctx, w, r, meta, spaceRef, sublog) + s.handleTusPost(w, r, meta, spaceRef, sublog) } -func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http.Request, meta map[string]string, ref *provider.Reference, log zerolog.Logger) { +func (s *svc) handleTusPost(w http.ResponseWriter, r *http.Request, meta map[string]string, ref *provider.Reference, log zerolog.Logger) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleTusPost") + defer span.End() + + ctx := r.Context() w.Header().Add(HeaderAccessControlAllowHeaders, strings.Join([]string{HeaderTusResumable, HeaderUploadLength, HeaderUploadMetadata, HeaderIfMatch}, ", ")) w.Header().Add(HeaderAccessControlExposeHeaders, strings.Join([]string{HeaderTusResumable, HeaderLocation}, ", ")) w.Header().Set(HeaderTusExtension, "creation,creation-with-upload,checksum,expiration") @@ -115,7 +120,7 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. // TODO check Expect: 100-continue // check if destination exists or is a file - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { log.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -133,7 +138,7 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. } if sRes.Status.Code != rpc.Code_CODE_OK && sRes.Status.Code != rpc.Code_CODE_NOT_FOUND { - HandleErrorStatus(&log, w, sRes.Status) + HandleErrorStatus(ctx, &log, w, sRes.Status) return } @@ -191,7 +196,7 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. w.WriteHeader(http.StatusPreconditionFailed) return } - HandleErrorStatus(&log, w, uRes.Status) + HandleErrorStatus(ctx, &log, w, uRes.Status) return } @@ -279,7 +284,7 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. return } - HandleErrorStatus(&log, w, sRes.Status) + HandleErrorStatus(ctx, &log, w, sRes.Status) return } diff --git a/internal/http/services/owncloud/ocdav/unlock.go b/internal/http/services/owncloud/ocdav/unlock.go index 3b20189c38..b390cce46e 100644 --- a/internal/http/services/owncloud/ocdav/unlock.go +++ b/internal/http/services/owncloud/ocdav/unlock.go @@ -20,9 +20,14 @@ package ocdav import ( "net/http" + + "github.com/cs3org/reva/pkg/tracing" ) // TODO(jfd): implement unlock func (s *svc) handleUnlock(w http.ResponseWriter, r *http.Request, ns string) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleUnlock") + defer span.End() + w.WriteHeader(http.StatusNotImplemented) } diff --git a/internal/http/services/owncloud/ocdav/versions.go b/internal/http/services/owncloud/ocdav/versions.go index 56837e2be1..bcb0720966 100644 --- a/internal/http/services/owncloud/ocdav/versions.go +++ b/internal/http/services/owncloud/ocdav/versions.go @@ -28,7 +28,7 @@ import ( "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/storage/utils/downloader" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils/resourceid" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" @@ -51,8 +51,10 @@ func (h *VersionsHandler) init(c *Config) error { // a version is identified by a timestamp, eg. /remote.php/dav/meta//v/1561410426 func (h *VersionsHandler) Handler(s *svc, rid *provider.ResourceId) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() + r, span := tracing.SpanStartFromRequest(r, tracerName, "Versions HTTP Handler") + defer span.End() + ctx := r.Context() if rid == nil { http.Error(w, "404 Not Found", http.StatusNotFound) return @@ -90,9 +92,10 @@ func (h *VersionsHandler) Handler(s *svc, rid *provider.ResourceId) http.Handler } func (h *VersionsHandler) doListVersions(w http.ResponseWriter, r *http.Request, s *svc, rid *provider.ResourceId) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "listVersions") + r, span := tracing.SpanStartFromRequest(r, tracerName, "doListVersions") defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Interface("resourceid", rid).Logger() pf, status, err := readPropfind(r.Body) @@ -102,7 +105,7 @@ func (h *VersionsHandler) doListVersions(w http.ResponseWriter, r *http.Request, return } - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -123,10 +126,10 @@ func (h *VersionsHandler) doListVersions(w http.ResponseWriter, r *http.Request, code: SabredavNotFound, message: "Resource not found", }) - HandleWebdavError(&sublog, w, b, err) + HandleWebdavError(ctx, &sublog, w, b, err) return } - HandleErrorStatus(&sublog, w, res.Status) + HandleErrorStatus(ctx, &sublog, w, res.Status) return } @@ -139,7 +142,7 @@ func (h *VersionsHandler) doListVersions(w http.ResponseWriter, r *http.Request, return } if lvRes.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, lvRes.Status) + HandleErrorStatus(ctx, &sublog, w, lvRes.Status) return } @@ -192,12 +195,13 @@ func (h *VersionsHandler) doListVersions(w http.ResponseWriter, r *http.Request, } func (h *VersionsHandler) doRestore(w http.ResponseWriter, r *http.Request, s *svc, rid *provider.ResourceId, key string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "restore") + r, span := tracing.SpanStartFromRequest(r, tracerName, "doRestore") defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Interface("resourceid", rid).Str("key", key).Logger() - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -216,19 +220,18 @@ func (h *VersionsHandler) doRestore(w http.ResponseWriter, r *http.Request, s *s return } if res.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, res.Status) + HandleErrorStatus(ctx, &sublog, w, res.Status) return } w.WriteHeader(http.StatusNoContent) } func (h *VersionsHandler) doDownload(w http.ResponseWriter, r *http.Request, s *svc, rid *provider.ResourceId, key string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "restore") - defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Interface("resourceid", rid).Str("key", key).Logger() - client, err := s.getClient() + client, err := s.getClient(ctx) if err != nil { sublog.Error().Err(err).Msg("error getting grpc client") w.WriteHeader(http.StatusInternalServerError) @@ -247,7 +250,7 @@ func (h *VersionsHandler) doDownload(w http.ResponseWriter, r *http.Request, s * } if resStat.Status.Code != rpc.Code_CODE_OK { - HandleErrorStatus(&sublog, w, resStat.Status) + HandleErrorStatus(ctx, &sublog, w, resStat.Status) return } diff --git a/internal/http/services/owncloud/ocdav/webdav.go b/internal/http/services/owncloud/ocdav/webdav.go index 8ad8f1333d..23632d1691 100644 --- a/internal/http/services/owncloud/ocdav/webdav.go +++ b/internal/http/services/owncloud/ocdav/webdav.go @@ -21,6 +21,8 @@ package ocdav import ( "net/http" "path" + + "github.com/cs3org/reva/pkg/tracing" ) // Common Webdav methods. @@ -93,7 +95,11 @@ func (h *WebDavHandler) init(ns string, useLoggedInUserNS bool) error { // Handler handles requests func (h *WebDavHandler) Handler(s *svc) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ns := applyLayout(r.Context(), h.namespace, h.useLoggedInUserNS, r.URL.Path) + r, span := tracing.SpanStartFromRequest(r, tracerName, "WebDav HTTP Handler") + defer span.End() + + ctx := r.Context() + ns := applyLayout(ctx, h.namespace, h.useLoggedInUserNS, r.URL.Path) switch r.Method { case MethodPropfind: s.handlePathPropfind(w, r, ns) diff --git a/internal/http/services/owncloud/ocs/cache.go b/internal/http/services/owncloud/ocs/cache.go index 8ab887d4c6..ee900f35f6 100644 --- a/internal/http/services/owncloud/ocs/cache.go +++ b/internal/http/services/owncloud/ocs/cache.go @@ -25,10 +25,15 @@ import ( "github.com/cs3org/reva/pkg/appctx" ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/tracing" + "go.opentelemetry.io/otel/trace" "google.golang.org/grpc/metadata" ) func (s *svc) cacheWarmup(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "cacheWarmup") + defer span.End() + if s.warmupCacheTracker != nil { u, ok1 := ctxpkg.ContextGetUser(r.Context()) tkn, ok2 := ctxpkg.ContextGetToken(r.Context()) @@ -43,6 +48,7 @@ func (s *svc) cacheWarmup(w http.ResponseWriter, r *http.Request) { // And in most of the cases, the warmup takes a longer amount of time to complete than the original request. // TODO: Check if we can come up with a better solution, eg, https://stackoverflow.com/a/54132324 ctx := context.Background() + ctx = trace.ContextWithSpan(ctx, span) ctx = appctx.WithLogger(ctx, log) ctx = ctxpkg.ContextSetUser(ctx, u) ctx = ctxpkg.ContextSetToken(ctx, tkn) diff --git a/internal/http/services/owncloud/ocs/conversions/main.go b/internal/http/services/owncloud/ocs/conversions/main.go index f240152bcd..27c15a42df 100644 --- a/internal/http/services/owncloud/ocs/conversions/main.go +++ b/internal/http/services/owncloud/ocs/conversions/main.go @@ -27,6 +27,7 @@ import ( "time" "github.com/cs3org/reva/pkg/publicshare" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/user" grouppb "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1" @@ -39,6 +40,8 @@ import ( usermgr "github.com/cs3org/reva/pkg/user/manager/registry" ) +const tracerName = "conversions" + const ( // ShareTypeUser refers to user shares ShareTypeUser ShareType = 0 @@ -179,6 +182,9 @@ type MatchValueData struct { // CS3Share2ShareData converts a cs3api user share into shareData data model func CS3Share2ShareData(ctx context.Context, share *collaboration.Share) (*ShareData, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CS3Share2ShareData") + defer span.End() + sd := &ShareData{ // share.permissions are mapped below // Displaynames are added later @@ -208,6 +214,9 @@ func CS3Share2ShareData(ctx context.Context, share *collaboration.Share) (*Share // PublicShare2ShareData converts a cs3api public share into shareData data model func PublicShare2ShareData(share *link.PublicShare, r *http.Request, publicURL string) *ShareData { + r, span := tracing.SpanStartFromRequest(r, tracerName, "PublicShare2ShareData") + defer span.End() + sd := &ShareData{ // share.permissions are mapped below // Displaynames are added later diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/sharees/sharees.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/sharees/sharees.go index 9966927fa9..a50b4387b6 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/sharees/sharees.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/sharees/sharees.go @@ -30,8 +30,11 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/storage/utils/templates" + "github.com/cs3org/reva/pkg/tracing" ) +const tracerName = "sharees" + // Handler implements the ownCloud sharing API type Handler struct { gatewayAddr string @@ -46,7 +49,11 @@ func (h *Handler) Init(c *config.Config) { // FindSharees implements the /apps/files_sharing/api/v1/sharees endpoint func (h *Handler) FindSharees(w http.ResponseWriter, r *http.Request) { - log := appctx.GetLogger(r.Context()) + r, span := tracing.SpanStartFromRequest(r, tracerName, "FindSharees") + defer span.End() + + ctx := r.Context() + log := appctx.GetLogger(ctx) term := r.URL.Query().Get("search") if term == "" { @@ -54,7 +61,7 @@ func (h *Handler) FindSharees(w http.ResponseWriter, r *http.Request) { return } - gwc, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + gwc, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting gateway grpc client", err) return diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/group.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/group.go index ef979783fb..f475a1fbd7 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/group.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/group.go @@ -30,11 +30,15 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" ) func (h *Handler) createGroupShare(w http.ResponseWriter, r *http.Request, statInfo *provider.ResourceInfo, role *conversions.Role, roleVal []byte) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "createGroupShare") + defer span.End() + ctx := r.Context() - c, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + c, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return @@ -81,5 +85,5 @@ func (h *Handler) createGroupShare(w http.ResponseWriter, r *http.Request, statI }, } - h.createCs3Share(ctx, w, r, c, createShareReq, statInfo) + h.createCs3Share(w, r, c, createShareReq, statInfo) } diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go index d87e257dcb..c721fcb9a1 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go @@ -28,6 +28,7 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/go-chi/chi/v5" "github.com/pkg/errors" "google.golang.org/protobuf/types/known/fieldmaskpb" @@ -35,21 +36,30 @@ import ( // AcceptReceivedShare handles Post Requests on /apps/files_sharing/api/v1/shares/{shareid} func (h *Handler) AcceptReceivedShare(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "AcceptReceivedShare") + defer span.End() + shareID := chi.URLParam(r, "shareid") h.updateReceivedShare(w, r, shareID, false) } // RejectReceivedShare handles DELETE Requests on /apps/files_sharing/api/v1/shares/{shareid} func (h *Handler) RejectReceivedShare(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "RejectReceivedShare") + defer span.End() + shareID := chi.URLParam(r, "shareid") h.updateReceivedShare(w, r, shareID, true) } func (h *Handler) updateReceivedShare(w http.ResponseWriter, r *http.Request, shareID string, rejectShare bool) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "updateReceivedShare") + defer span.End() + ctx := r.Context() logger := appctx.GetLogger(ctx) - client, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go index 772184e4d6..3dd7e7b1e0 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go @@ -38,14 +38,18 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/publicshare" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) func (h *Handler) createPublicLinkShare(w http.ResponseWriter, r *http.Request, statInfo *provider.ResourceInfo) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "createPublicLinkShare") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) - c, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + c, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return @@ -175,11 +179,14 @@ func (h *Handler) createPublicLinkShare(w http.ResponseWriter, r *http.Request, } func (h *Handler) listPublicShares(r *http.Request, filters []*link.ListPublicSharesRequest_Filter) ([]*conversions.ShareData, *rpc.Status, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "listPublicShares") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) ocsDataPayload := make([]*conversions.ShareData, 0) - client, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { return ocsDataPayload, nil, err } @@ -245,8 +252,12 @@ func (h *Handler) listPublicShares(r *http.Request, filters []*link.ListPublicSh } func (h *Handler) isPublicShare(r *http.Request, oid string) bool { - logger := appctx.GetLogger(r.Context()) - client, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + r, span := tracing.SpanStartFromRequest(r, tracerName, "isPublicShare") + defer span.End() + + ctx := r.Context() + logger := appctx.GetLogger(ctx) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { logger.Err(err) } @@ -269,10 +280,14 @@ func (h *Handler) isPublicShare(r *http.Request, oid string) bool { } func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shareID string) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "updatePublicShare") + defer span.End() + updates := []*link.UpdatePublicShareRequest_Update{} logger := appctx.GetLogger(r.Context()) - gwC, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + ctx := r.Context() + gwC, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { log.Err(err).Str("shareID", shareID).Msg("updatePublicShare") response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "error getting a connection to the gateway service", nil) @@ -443,9 +458,11 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar } func (h *Handler) removePublicShare(w http.ResponseWriter, r *http.Request, shareID string) { - ctx := r.Context() + r, span := tracing.SpanStartFromRequest(r, tracerName, "removePublicShare") + defer span.End() - c, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + ctx := r.Context() + c, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return @@ -496,6 +513,9 @@ func ocPublicPermToCs3(permKey int, h *Handler) (*provider.ResourcePermissions, } func permissionFromRequest(r *http.Request, h *Handler) (*provider.ResourcePermissions, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "permissionFromRequest") + defer span.End() + var err error // phoenix sends: {"permissions": 15}. See ocPublicPermToRole struct for mapping diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/remote.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/remote.go index 038a8e6ca2..4920a7c313 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/remote.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/remote.go @@ -34,12 +34,15 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" ) func (h *Handler) createFederatedCloudShare(w http.ResponseWriter, r *http.Request, statInfo *provider.ResourceInfo, role *conversions.Role, roleVal []byte) { - ctx := r.Context() + r, span := tracing.SpanStartFromRequest(r, tracerName, "createFederatedCloudShare") + defer span.End() - c, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + ctx := r.Context() + c, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return @@ -122,12 +125,14 @@ func (h *Handler) createFederatedCloudShare(w http.ResponseWriter, r *http.Reque // GetFederatedShare handles GET requests on /apps/files_sharing/api/v1/shares/remote_shares/{shareid} func (h *Handler) GetFederatedShare(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "GetFederatedShare") + defer span.End() // TODO: Implement response with HAL schemating ctx := r.Context() shareID := chi.URLParam(r, "shareid") - gatewayClient, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + gatewayClient, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return @@ -158,12 +163,14 @@ func (h *Handler) GetFederatedShare(w http.ResponseWriter, r *http.Request) { // ListFederatedShares handles GET requests on /apps/files_sharing/api/v1/shares/remote_shares func (h *Handler) ListFederatedShares(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "ListFederatedShares") + defer span.End() // TODO Implement pagination. // TODO Implement response with HAL schemating ctx := r.Context() - gatewayClient, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + gatewayClient, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index 010ff9b3a6..4190801196 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -54,11 +54,14 @@ import ( "github.com/cs3org/reva/pkg/share/cache" cachereg "github.com/cs3org/reva/pkg/share/cache/registry" warmupreg "github.com/cs3org/reva/pkg/share/cache/warmup/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/pkg/errors" ) +const tracerName = "shares" + const ( storageIDPrefix string = "shared::" ) @@ -137,6 +140,9 @@ func (h *Handler) startCacheWarmup(c cache.Warmup) { } func (h *Handler) extractReference(r *http.Request) (provider.Reference, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "extractReference") + defer span.End() + var ref provider.Reference if p := r.FormValue("path"); p != "" { ref = provider.Reference{Path: path.Join(h.homeNamespace, p)} @@ -152,7 +158,9 @@ func (h *Handler) extractReference(r *http.Request) (provider.Reference, error) // CreateShare handles POST requests on /apps/files_sharing/api/v1/shares func (h *Handler) CreateShare(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() + r, span := tracing.SpanStartFromRequest(r, tracerName, "CreateShare") + defer span.End() + shareType, err := strconv.Atoi(r.FormValue("shareType")) if err != nil { response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "shareType must be an integer", nil) @@ -160,7 +168,8 @@ func (h *Handler) CreateShare(w http.ResponseWriter, r *http.Request) { } // get user permissions on the shared file - client, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + ctx := r.Context() + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return @@ -186,7 +195,7 @@ func (h *Handler) CreateShare(w http.ResponseWriter, r *http.Request) { } if statRes.Status.Code != rpc.Code_CODE_OK { - ocdav.HandleErrorStatus(&sublog, w, statRes.Status) + ocdav.HandleErrorStatus(ctx, &sublog, w, statRes.Status) return } @@ -233,6 +242,9 @@ func (h *Handler) CreateShare(w http.ResponseWriter, r *http.Request) { } func (h *Handler) extractPermissions(w http.ResponseWriter, r *http.Request, ri *provider.ResourceInfo, defaultPermissions *conversions.Role) (*conversions.Role, []byte, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "extractPermissions") + defer span.End() + reqRole, reqPermissions := r.FormValue("role"), r.FormValue("permissions") var role *conversions.Role @@ -303,13 +315,16 @@ type PublicShareContextName string // GetShare handles GET requests on /apps/files_sharing/api/v1/shares/(shareid) func (h *Handler) GetShare(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "GetShare") + defer span.End() + var share *conversions.ShareData var resourceID *provider.ResourceId shareID := chi.URLParam(r, "shareid") ctx := r.Context() logger := appctx.GetLogger(r.Context()) logger.Debug().Str("shareID", shareID).Msg("get share by id") - client, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return @@ -418,6 +433,9 @@ func (h *Handler) GetShare(w http.ResponseWriter, r *http.Request) { // UpdateShare handles PUT requests on /apps/files_sharing/api/v1/shares/(shareid) func (h *Handler) UpdateShare(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "UpdateShare") + defer span.End() + shareID := chi.URLParam(r, "shareid") // FIXME: isPublicShare is already doing a GetShare and GetPublicShare, // we should just reuse that object when doing updates @@ -429,7 +447,8 @@ func (h *Handler) UpdateShare(w http.ResponseWriter, r *http.Request) { } func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID string) { - ctx := r.Context() + r, span := tracing.SpanStartFromRequest(r, tracerName, "updateShare") + defer span.End() pval := r.FormValue("permissions") if pval == "" { @@ -448,7 +467,8 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st return } - client, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + ctx := r.Context() + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return @@ -525,6 +545,9 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st // RemoveShare handles DELETE requests on /apps/files_sharing/api/v1/shares/(shareid) func (h *Handler) RemoveShare(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "RemoveShare") + defer span.End() + shareID := chi.URLParam(r, "shareid") switch { case h.isPublicShare(r, shareID): @@ -539,6 +562,9 @@ func (h *Handler) RemoveShare(w http.ResponseWriter, r *http.Request) { // ListShares handles GET requests on /apps/files_sharing/api/v1/shares func (h *Handler) ListShares(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "ListShares") + defer span.End() + if r.FormValue("shared_with_me") != "" { var err error listSharedWithMe, err := strconv.ParseBool(r.FormValue("shared_with_me")) @@ -561,18 +587,20 @@ const ( ) func (h *Handler) listSharesWithMe(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "listSharesWithMe") + defer span.End() + // which pending state to list stateFilter := getStateFilter(r.FormValue("state")) - log := appctx.GetLogger(r.Context()) - client, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + ctx := r.Context() + log := appctx.GetLogger(ctx) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return } - ctx := r.Context() - var pinfo *provider.ResourceInfo p := r.URL.Query().Get("path") // we need to lookup the resource id so we can filter the list of shares later @@ -782,6 +810,9 @@ func findMatch(shareJailInfos []*provider.ResourceInfo, id *provider.ResourceId) } func (h *Handler) listSharesWithOthers(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "listSharesWithOthers") + defer span.End() + shares := make([]*conversions.ShareData, 0) filters := []*collaboration.Filter{} @@ -863,12 +894,15 @@ func (h *Handler) logProblems(s *rpc.Status, e error, msg string) { } func (h *Handler) addFilters(w http.ResponseWriter, r *http.Request, prefix string) ([]*collaboration.Filter, []*link.ListPublicSharesRequest_Filter, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "addFilters") + defer span.End() + collaborationFilters := []*collaboration.Filter{} linkFilters := []*link.ListPublicSharesRequest_Filter{} - ctx := r.Context() + ctx := r.Context() // first check if the file exists - client, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return nil, nil, err @@ -899,6 +933,9 @@ func (h *Handler) addFilters(w http.ResponseWriter, r *http.Request, prefix stri } func (h *Handler) addFileInfo(ctx context.Context, s *conversions.ShareData, info *provider.ResourceInfo) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "addFileInfo") + defer span.End() + log := appctx.GetLogger(ctx) if info != nil { // TODO The owner is not set in the storage stat metadata ... @@ -942,6 +979,9 @@ func (h *Handler) addFileInfo(ctx context.Context, s *conversions.ShareData, inf // mustGetIdentifiers always returns a struct with identifiers, if the user or group could not be found they will all be empty func (h *Handler) mustGetIdentifiers(ctx context.Context, client gateway.GatewayAPIClient, id string, isGroup bool) *userIdentifiers { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "mustGetIdentifiers") + defer span.End() + sublog := appctx.GetLogger(ctx).With().Str("id", id).Logger() if id == "" { return &userIdentifiers{} @@ -1022,6 +1062,9 @@ func (h *Handler) mustGetIdentifiers(ctx context.Context, client gateway.Gateway } func (h *Handler) mapUserIds(ctx context.Context, client gateway.GatewayAPIClient, s *conversions.ShareData) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "mapUserIds") + defer span.End() + if s.UIDOwner != "" { owner := h.mustGetIdentifiers(ctx, client, s.UIDOwner, false) s.UIDOwner = owner.Username @@ -1057,6 +1100,9 @@ func (h *Handler) mapUserIds(ctx context.Context, client gateway.GatewayAPIClien } func (h *Handler) getAdditionalInfoAttribute(ctx context.Context, u *userIdentifiers) string { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getAdditionalInfoAttribute") + defer span.End() + var buf bytes.Buffer if err := h.additionalInfoTemplate.Execute(&buf, u); err != nil { log := appctx.GetLogger(ctx) @@ -1067,18 +1113,27 @@ func (h *Handler) getAdditionalInfoAttribute(ctx context.Context, u *userIdentif } func (h *Handler) getResourceInfoByPath(ctx context.Context, client gateway.GatewayAPIClient, path string) (*provider.ResourceInfo, *rpc.Status, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getResourceInfoByPath") + defer span.End() + return h.getResourceInfo(ctx, client, path, &provider.Reference{ Path: path, }) } func (h *Handler) getResourceInfoByID(ctx context.Context, client gateway.GatewayAPIClient, id *provider.ResourceId) (*provider.ResourceInfo, *rpc.Status, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getResourceInfoByID") + defer span.End() + return h.getResourceInfo(ctx, client, resourceid.OwnCloudResourceIDWrap(id), &provider.Reference{ResourceId: id}) } // getResourceInfo retrieves the resource info to a target. // This method utilizes caching if it is enabled. func (h *Handler) getResourceInfo(ctx context.Context, client gateway.GatewayAPIClient, key string, ref *provider.Reference) (*provider.ResourceInfo, *rpc.Status, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getResourceInfo") + defer span.End() + logger := appctx.GetLogger(ctx) var pinfo *provider.ResourceInfo @@ -1117,7 +1172,11 @@ func (h *Handler) getResourceInfo(ctx context.Context, client gateway.GatewayAPI return pinfo, status, nil } -func (h *Handler) createCs3Share(ctx context.Context, w http.ResponseWriter, r *http.Request, client gateway.GatewayAPIClient, req *collaboration.CreateShareRequest, info *provider.ResourceInfo) { +func (h *Handler) createCs3Share(w http.ResponseWriter, r *http.Request, client gateway.GatewayAPIClient, req *collaboration.CreateShareRequest, info *provider.ResourceInfo) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "createCs3Share") + defer span.End() + + ctx := r.Context() createShareResponse, err := client.CreateShare(ctx, req) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error sending a grpc create share request", err) diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares_test.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares_test.go index d21b7e42dc..4264ecdbfa 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares_test.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares_test.go @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go index 29aa0194da..8b3790ec92 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go @@ -34,13 +34,17 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/pkg/errors" ) func (h *Handler) getGrantee(ctx context.Context, name string) (provider.Grantee, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getGrantee") + defer span.End() + log := appctx.GetLogger(ctx) - client, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { return provider.Grantee{}, err } @@ -72,8 +76,10 @@ func (h *Handler) getGrantee(ctx context.Context, name string) (provider.Grantee } func (h *Handler) addSpaceMember(w http.ResponseWriter, r *http.Request, info *provider.ResourceInfo, role *conversions.Role, roleVal []byte) { - ctx := r.Context() + r, span := tracing.SpanStartFromRequest(r, tracerName, "addSpaceMember") + defer span.End() + ctx := r.Context() shareWith := r.FormValue("shareWith") if shareWith == "" { response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "missing shareWith", nil) @@ -94,7 +100,7 @@ func (h *Handler) addSpaceMember(w http.ResponseWriter, r *http.Request, info *p return } - providerClient, err := h.getStorageProviderClient(providers[0]) + providerClient, err := h.getStorageProviderClient(ctx, providers[0]) if err != nil { response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "error getting storage provider", err) return @@ -116,8 +122,10 @@ func (h *Handler) addSpaceMember(w http.ResponseWriter, r *http.Request, info *p } func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx := r.Context() + r, span := tracing.SpanStartFromRequest(r, tracerName, "removeSpaceMember") + defer span.End() + ctx := r.Context() shareWith := r.URL.Query().Get("shareWith") if shareWith == "" { response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "missing shareWith", nil) @@ -142,7 +150,7 @@ func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spac return } - providerClient, err := h.getStorageProviderClient(providers[0]) + providerClient, err := h.getStorageProviderClient(ctx, providers[0]) if err != nil { response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "error getting storage provider", err) return @@ -166,8 +174,11 @@ func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spac response.WriteOCSSuccess(w, r, nil) } -func (h *Handler) getStorageProviderClient(p *registry.ProviderInfo) (provider.ProviderAPIClient, error) { - c, err := pool.GetStorageProviderServiceClient(pool.Endpoint(p.Address)) +func (h *Handler) getStorageProviderClient(ctx context.Context, p *registry.ProviderInfo) (provider.ProviderAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getStorageProviderClient") + defer span.End() + + c, err := pool.GetStorageProviderServiceClient(ctx, pool.Endpoint(p.Address)) if err != nil { err = errors.Wrap(err, "gateway: error getting a storage provider client") return nil, err @@ -177,7 +188,10 @@ func (h *Handler) getStorageProviderClient(p *registry.ProviderInfo) (provider.P } func (h *Handler) findProviders(ctx context.Context, ref *provider.Reference) ([]*registry.ProviderInfo, error) { - c, err := pool.GetStorageRegistryClient(pool.Endpoint(h.storageRegistryAddr)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "findProviders") + defer span.End() + + c, err := pool.GetStorageRegistryClient(ctx, pool.Endpoint(h.storageRegistryAddr)) if err != nil { return nil, errors.Wrap(err, "gateway: error getting storage registry client") } diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go index 857e8c7365..8c7818d825 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go @@ -35,11 +35,15 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" ) func (h *Handler) createUserShare(w http.ResponseWriter, r *http.Request, statInfo *provider.ResourceInfo, role *conversions.Role, roleVal []byte) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "createUserShare") + defer span.End() + ctx := r.Context() - c, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + c, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return @@ -87,12 +91,16 @@ func (h *Handler) createUserShare(w http.ResponseWriter, r *http.Request, statIn }, } - h.createCs3Share(ctx, w, r, c, createShareReq, statInfo) + h.createCs3Share(w, r, c, createShareReq, statInfo) } func (h *Handler) isUserShare(r *http.Request, oid string) bool { - logger := appctx.GetLogger(r.Context()) - client, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + r, span := tracing.SpanStartFromRequest(r, tracerName, "isUserShare") + defer span.End() + + ctx := r.Context() + logger := appctx.GetLogger(ctx) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { logger.Err(err) } @@ -115,9 +123,11 @@ func (h *Handler) isUserShare(r *http.Request, oid string) bool { } func (h *Handler) removeUserShare(w http.ResponseWriter, r *http.Request, shareID string) { - ctx := r.Context() + r, span := tracing.SpanStartFromRequest(r, tracerName, "removeUserShare") + defer span.End() - uClient, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + ctx := r.Context() + uClient, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) return @@ -171,6 +181,9 @@ func (h *Handler) removeUserShare(w http.ResponseWriter, r *http.Request, shareI } func (h *Handler) listUserShares(r *http.Request, filters []*collaboration.Filter, ctxPath string) ([]*conversions.ShareData, *rpc.Status, error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "listUserShares") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) @@ -184,7 +197,7 @@ func (h *Handler) listUserShares(r *http.Request, filters []*collaboration.Filte } ocsDataPayload := make([]*conversions.ShareData, 0) - client, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { return ocsDataPayload, nil, err } diff --git a/internal/http/services/owncloud/ocs/handlers/cloud/capabilities/capabilities.go b/internal/http/services/owncloud/ocs/handlers/cloud/capabilities/capabilities.go index edf85ee6da..267a5ed38b 100644 --- a/internal/http/services/owncloud/ocs/handlers/cloud/capabilities/capabilities.go +++ b/internal/http/services/owncloud/ocs/handlers/cloud/capabilities/capabilities.go @@ -24,6 +24,7 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/config" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/data" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" + "github.com/cs3org/reva/pkg/tracing" ) // Handler renders the capability endpoint @@ -238,6 +239,9 @@ func (h *Handler) Init(c *config.Config) { // Handler renders the capabilities func (h *Handler) GetCapabilities(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "GetCapabilities") + defer span.End() + c := h.getCapabilitiesForUserAgent(r.Context(), r.UserAgent()) response.WriteOCSSuccess(w, r, c) } diff --git a/internal/http/services/owncloud/ocs/handlers/cloud/capabilities/uploads.go b/internal/http/services/owncloud/ocs/handlers/cloud/capabilities/uploads.go index eeb3e3dc1a..02fd9acca1 100644 --- a/internal/http/services/owncloud/ocs/handlers/cloud/capabilities/uploads.go +++ b/internal/http/services/owncloud/ocs/handlers/cloud/capabilities/uploads.go @@ -24,9 +24,12 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/data" ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/tracing" "github.com/juliangruber/go-intersect" ) +const tracerName = "capabilities" + type chunkProtocol string var ( @@ -36,6 +39,9 @@ var ( ) func (h *Handler) getCapabilitiesForUserAgent(ctx context.Context, userAgent string) data.CapabilitiesData { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getCapabilitiesForUserAgent") + defer span.End() + // Creating a copy of the capabilities struct is less expensive than taking a lock c := *h.c.Capabilities if userAgent != "" { @@ -58,6 +64,9 @@ func (h *Handler) getCapabilitiesForUserAgent(ctx context.Context, userAgent str } func ctxUserBelongsToGroups(ctx context.Context, groups []string) bool { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ctxUserBelongsToGroups") + defer span.End() + if user, ok := ctxpkg.ContextGetUser(ctx); ok { return len(intersect.Simple(groups, user.Groups)) > 0 } diff --git a/internal/http/services/owncloud/ocs/handlers/cloud/user/user.go b/internal/http/services/owncloud/ocs/handlers/cloud/user/user.go index 22c7190846..33d29dffd5 100644 --- a/internal/http/services/owncloud/ocs/handlers/cloud/user/user.go +++ b/internal/http/services/owncloud/ocs/handlers/cloud/user/user.go @@ -25,14 +25,19 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/tracing" ) +const tracerName = "user" + // The Handler renders the user endpoint type Handler struct { } // GetSelf handles GET requests on /cloud/user func (h *Handler) GetSelf(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "GetSelf") + defer span.End() ctx := r.Context() // TODO move user to handler parameter? diff --git a/internal/http/services/owncloud/ocs/handlers/cloud/users/users.go b/internal/http/services/owncloud/ocs/handlers/cloud/users/users.go index 2f6d7a84a7..dcd441a474 100644 --- a/internal/http/services/owncloud/ocs/handlers/cloud/users/users.go +++ b/internal/http/services/owncloud/ocs/handlers/cloud/users/users.go @@ -33,9 +33,12 @@ import ( "github.com/cs3org/reva/pkg/appctx" ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/go-chi/chi/v5" ) +const tracerName = "users" + // Handler renders user data for the user id given in the url path type Handler struct { gatewayAddr string @@ -49,6 +52,9 @@ func (h *Handler) Init(c *config.Config) { // GetGroups handles GET requests on /cloud/users/groups // TODO: implement func (h *Handler) GetGroups(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "GetGroups") + defer span.End() + response.WriteOCSSuccess(w, r, &Groups{}) } @@ -81,6 +87,9 @@ type Groups struct { // Only allow self-read currently. TODO: List Users and Get on other users (both require // administrative privileges) func (h *Handler) GetUsers(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "GetUsers") + defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(r.Context()) @@ -97,7 +106,7 @@ func (h *Handler) GetUsers(w http.ResponseWriter, r *http.Request) { return } - gc, err := pool.GetGatewayServiceClient(pool.Endpoint(h.gatewayAddr)) + gc, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(h.gatewayAddr)) if err != nil { sublog.Error().Err(err).Msg("error getting gateway client") w.WriteHeader(http.StatusInternalServerError) @@ -111,7 +120,7 @@ func (h *Handler) GetUsers(w http.ResponseWriter, r *http.Request) { return } if getHomeRes.Status.Code != rpc.Code_CODE_OK { - ocdav.HandleErrorStatus(sublog, w, getHomeRes.Status) + ocdav.HandleErrorStatus(ctx, sublog, w, getHomeRes.Status) return } var total, used uint64 = 2, 1 @@ -126,7 +135,7 @@ func (h *Handler) GetUsers(w http.ResponseWriter, r *http.Request) { } if getQuotaRes.Status.Code != rpc.Code_CODE_OK { - ocdav.HandleErrorStatus(sublog, w, getQuotaRes.Status) + ocdav.HandleErrorStatus(ctx, sublog, w, getQuotaRes.Status) return } total = getQuotaRes.TotalBytes diff --git a/internal/http/services/owncloud/ocs/handlers/config/config.go b/internal/http/services/owncloud/ocs/handlers/config/config.go index 852e12b813..9439990d74 100644 --- a/internal/http/services/owncloud/ocs/handlers/config/config.go +++ b/internal/http/services/owncloud/ocs/handlers/config/config.go @@ -24,8 +24,11 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/config" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/data" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" + "github.com/cs3org/reva/pkg/tracing" ) +const tracerName = "ocs" + // Handler renders the config endpoint type Handler struct { c data.ConfigData @@ -54,5 +57,8 @@ func (h *Handler) Init(c *config.Config) { // Handler renders the config func (h *Handler) GetConfig(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "GetConfig") + defer span.End() + response.WriteOCSSuccess(w, r, h.c) } diff --git a/internal/http/services/owncloud/ocs/ocs.go b/internal/http/services/owncloud/ocs/ocs.go index 8a166ee0ba..e21e43f72e 100644 --- a/internal/http/services/owncloud/ocs/ocs.go +++ b/internal/http/services/owncloud/ocs/ocs.go @@ -33,16 +33,21 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" + "github.com/cs3org/reva/pkg/tracing" "github.com/go-chi/chi/v5" "github.com/mitchellh/mapstructure" "github.com/rs/zerolog" ) +const serviceName = "ocs" +const tracerName = "ocs" + func init() { global.Register("ocs", New) } type svc struct { + tracing.HttpMiddleware c *config.Config router *chi.Mux warmupCacheTracker *ttlcache.Cache @@ -144,7 +149,11 @@ func (s *svc) routerInit() error { func (s *svc) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - log := appctx.GetLogger(r.Context()) + r, span := tracing.SpanStartFromRequest(r, tracerName, "Ocs Service HTTP Handler") + defer span.End() + + ctx := r.Context() + log := appctx.GetLogger(ctx) log.Debug().Str("path", r.URL.Path).Msg("ocs routing") // Warmup the share cache for the user diff --git a/internal/http/services/owncloud/ocs/response/response.go b/internal/http/services/owncloud/ocs/response/response.go index f92af90875..0f72aed32e 100644 --- a/internal/http/services/owncloud/ocs/response/response.go +++ b/internal/http/services/owncloud/ocs/response/response.go @@ -27,9 +27,12 @@ import ( "reflect" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/tracing" "github.com/go-chi/chi/v5" ) +const tracerName = "response" + type key int const ( @@ -129,16 +132,26 @@ var MetaUnknownError = Meta{Status: "error", StatusCode: 999, Message: "Unknown // WriteOCSSuccess handles writing successful ocs response data func WriteOCSSuccess(w http.ResponseWriter, r *http.Request, d interface{}) { + ctx := r.Context() + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "WriteOCSSuccess") + defer span.End() + WriteOCSData(w, r, MetaOK, d, nil) } // WriteOCSError handles writing error ocs responses func WriteOCSError(w http.ResponseWriter, r *http.Request, c int, m string, err error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "WriteOCSError") + defer span.End() + WriteOCSData(w, r, Meta{Status: "error", StatusCode: c, Message: m}, nil, err) } // WriteOCSData handles writing ocs data in json and xml func WriteOCSData(w http.ResponseWriter, r *http.Request, m Meta, d interface{}, err error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "WriteOCSData") + defer span.End() + WriteOCSResponse(w, r, Response{ OCS: &Payload{ Meta: m, @@ -149,6 +162,9 @@ func WriteOCSData(w http.ResponseWriter, r *http.Request, m Meta, d interface{}, // WriteOCSResponse handles writing ocs responses in json and xml func WriteOCSResponse(w http.ResponseWriter, r *http.Request, res Response, err error) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "WriteOCSResponse") + defer span.End() + if err != nil { appctx.GetLogger(r.Context()).Error().Err(err).Msg(res.OCS.Meta.Message) } @@ -236,6 +252,10 @@ func OcsV2StatusCodes(meta Meta) int { // WithAPIVersion puts the api version in the context. func VersionCtx(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "VersionCtx") + defer span.End() + + ctx := r.Context() version := chi.URLParam(r, "version") if version == "" { WriteOCSError(w, r, MetaBadRequest.StatusCode, "unknown ocs api version", nil) @@ -244,7 +264,7 @@ func VersionCtx(next http.Handler) http.Handler { w.Header().Set("Ocs-Api-Version", version) // store version in context so handlers can access it - ctx := context.WithValue(r.Context(), apiVersionKey, version) + ctx = context.WithValue(ctx, apiVersionKey, version) next.ServeHTTP(w, r.WithContext(ctx)) }) } diff --git a/internal/http/services/preferences/preferences.go b/internal/http/services/preferences/preferences.go index 7ae1d3221a..ffc2eeadd7 100644 --- a/internal/http/services/preferences/preferences.go +++ b/internal/http/services/preferences/preferences.go @@ -28,11 +28,15 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/go-chi/chi/v5" "github.com/mitchellh/mapstructure" "github.com/rs/zerolog" ) +const serviceName = "preferences" +const tracerName = "preferences" + func init() { global.Register("preferences", New) } @@ -51,13 +55,13 @@ func (c *Config) init() { } type svc struct { + tracing.HttpMiddleware conf *Config router *chi.Mux } // New returns a new ocmd object func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) { - conf := &Config{} if err := mapstructure.Decode(m, conf); err != nil { return nil, err @@ -98,11 +102,17 @@ func (s *svc) Unprotected() []string { func (s *svc) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Preferences Service HTTP Handler") + defer span.End() + s.router.ServeHTTP(w, r) }) } func (s *svc) handleGet(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handleGet") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) @@ -119,7 +129,7 @@ func (s *svc) handleGet(w http.ResponseWriter, r *http.Request) { } - client, err := pool.GetGatewayServiceClient(pool.Endpoint(s.conf.GatewaySvc)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(s.conf.GatewaySvc)) if err != nil { log.Error().Err(err).Msg("error getting grpc gateway client") w.WriteHeader(http.StatusInternalServerError) @@ -168,6 +178,9 @@ func (s *svc) handleGet(w http.ResponseWriter, r *http.Request) { } func (s *svc) handlePost(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "handlePost") + defer span.End() + ctx := r.Context() log := appctx.GetLogger(ctx) @@ -185,7 +198,7 @@ func (s *svc) handlePost(w http.ResponseWriter, r *http.Request) { } - client, err := pool.GetGatewayServiceClient(pool.Endpoint(s.conf.GatewaySvc)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(s.conf.GatewaySvc)) if err != nil { log.Error().Err(err).Msg("error getting grpc gateway client") w.WriteHeader(http.StatusInternalServerError) diff --git a/internal/http/services/prometheus/prometheus.go b/internal/http/services/prometheus/prometheus.go index 14b6b9ed2f..bac6b5b841 100644 --- a/internal/http/services/prometheus/prometheus.go +++ b/internal/http/services/prometheus/prometheus.go @@ -28,8 +28,12 @@ import ( "go.opencensus.io/stats/view" "github.com/cs3org/reva/pkg/rhttp/global" + "github.com/cs3org/reva/pkg/tracing" ) +const serviceName = "prometheus" +const tracerName = "prometheus" + func init() { global.Register("prometheus", New) } @@ -65,6 +69,7 @@ func (c *config) init() { } type svc struct { + tracing.HttpMiddleware prefix string h http.Handler } diff --git a/internal/http/services/reverseproxy/reverseproxy.go b/internal/http/services/reverseproxy/reverseproxy.go index 09d7d968a3..794b3d8d72 100644 --- a/internal/http/services/reverseproxy/reverseproxy.go +++ b/internal/http/services/reverseproxy/reverseproxy.go @@ -27,11 +27,15 @@ import ( ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rhttp/global" + "github.com/cs3org/reva/pkg/tracing" "github.com/go-chi/chi/v5" "github.com/mitchellh/mapstructure" "github.com/rs/zerolog" ) +const serviceName = "reverseproxy" +const tracerName = "reverseproxy" + func init() { global.Register("reverseproxy", New) } @@ -52,6 +56,7 @@ func (c *config) init() { } type svc struct { + tracing.HttpMiddleware router *chi.Mux } @@ -114,6 +119,9 @@ func (s *svc) Unprotected() []string { func (s *svc) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Reverseproxy Service HTTP Handler") + defer span.End() + s.router.ServeHTTP(w, r) }) } diff --git a/internal/http/services/siteacc/siteacc.go b/internal/http/services/siteacc/siteacc.go index 8bed2526ba..3b2374eb00 100644 --- a/internal/http/services/siteacc/siteacc.go +++ b/internal/http/services/siteacc/siteacc.go @@ -23,6 +23,7 @@ import ( "github.com/cs3org/reva/pkg/siteacc" "github.com/cs3org/reva/pkg/siteacc/config" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/rs/zerolog" @@ -30,21 +31,21 @@ import ( "github.com/cs3org/reva/pkg/rhttp/global" ) +const serviceName = "siteacc" +const tracerName = "siteacc" + func init() { global.Register(serviceName, New) } type svc struct { + tracing.HttpMiddleware conf *config.Configuration log *zerolog.Logger siteacc *siteacc.SiteAccounts } -const ( - serviceName = "siteacc" -) - // Close is called when this service is being stopped. func (s *svc) Close() error { return nil diff --git a/internal/http/services/sysinfo/sysinfo.go b/internal/http/services/sysinfo/sysinfo.go index 65ce0d7949..c1c74daef7 100644 --- a/internal/http/services/sysinfo/sysinfo.go +++ b/internal/http/services/sysinfo/sysinfo.go @@ -28,8 +28,12 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sysinfo" + "github.com/cs3org/reva/pkg/tracing" ) +const serviceName = "sysinfo" +const tracerName = "sysinfo" + func init() { global.Register(serviceName, New) } @@ -39,13 +43,10 @@ type config struct { } type svc struct { + tracing.HttpMiddleware conf *config } -const ( - serviceName = "sysinfo" -) - // Close is called when this service is being stopped. func (s *svc) Close() error { return nil @@ -64,6 +65,9 @@ func (s *svc) Unprotected() []string { // Handler serves all HTTP requests. func (s *svc) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Sysinfo Service HTTP Handler") + defer span.End() + log := appctx.GetLogger(r.Context()) if _, err := w.Write([]byte(s.getJSONData())); err != nil { log.Err(err).Msg("error writing SysInfo response") diff --git a/internal/http/services/thumbnails/handler.go b/internal/http/services/thumbnails/handler.go index 97b71e7120..013d5b05d8 100644 --- a/internal/http/services/thumbnails/handler.go +++ b/internal/http/services/thumbnails/handler.go @@ -44,12 +44,16 @@ import ( "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/storage/utils/downloader" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/rs/zerolog" "google.golang.org/grpc/metadata" ) +const serviceName = "thumbnails" +const tracerName = "thumbnails" + func init() { global.Register("thumbnails", New) } @@ -73,6 +77,7 @@ type config struct { } type svc struct { + tracing.HttpMiddleware c *config log *zerolog.Logger client gateway.GatewayAPIClient @@ -94,6 +99,9 @@ func (c *config) init() { // New creates a new thumbnails HTTP service func New(conf map[string]interface{}, log *zerolog.Logger) (global.Service, error) { + ctx, span := tracing.SpanStart(context.Background(), serviceName, tracerName, "New") + defer span.End() + c := &config{} err := mapstructure.Decode(conf, c) if err != nil { @@ -101,7 +109,7 @@ func New(conf map[string]interface{}, log *zerolog.Logger) (global.Service, erro } c.init() - gtw, err := pool.GetGatewayServiceClient(pool.Endpoint(c.GatewaySVC)) + gtw, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(c.GatewaySVC)) if err != nil { return nil, errors.Wrap(err, "error getting gateway client") } diff --git a/internal/http/services/wellknown/openidconfiguration.go b/internal/http/services/wellknown/openidconfiguration.go index eb7da95a6a..869aa7a119 100644 --- a/internal/http/services/wellknown/openidconfiguration.go +++ b/internal/http/services/wellknown/openidconfiguration.go @@ -23,9 +23,13 @@ import ( "net/http" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/tracing" ) func (s *svc) doOpenidConfiguration(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "doOpenidConfiguration") + defer span.End() + log := appctx.GetLogger(r.Context()) pm := &ProviderMetadata{ Issuer: s.conf.Issuer, diff --git a/internal/http/services/wellknown/webfinger.go b/internal/http/services/wellknown/webfinger.go index 8d4ffc91e9..bd9bfbaad6 100644 --- a/internal/http/services/wellknown/webfinger.go +++ b/internal/http/services/wellknown/webfinger.go @@ -20,8 +20,13 @@ package wellknown import ( "net/http" + + "github.com/cs3org/reva/pkg/tracing" ) func (s *svc) doWebfinger(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "doWebfinger") + defer span.End() + w.WriteHeader(http.StatusNotFound) } diff --git a/internal/http/services/wellknown/wellknown.go b/internal/http/services/wellknown/wellknown.go index 524cc4cffd..4bb2035576 100644 --- a/internal/http/services/wellknown/wellknown.go +++ b/internal/http/services/wellknown/wellknown.go @@ -24,10 +24,14 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/rhttp/router" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/rs/zerolog" ) +const serviceName = "wellknown" +const tracerName = "wellknown" + func init() { global.Register("wellknown", New) } @@ -51,6 +55,7 @@ func (c *config) init() { } type svc struct { + tracing.HttpMiddleware conf *config handler http.Handler } @@ -91,6 +96,9 @@ func (s *svc) Unprotected() []string { func (s *svc) setHandler() { s.handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Wellknown Service HTTP Handler") + defer span.End() + log := appctx.GetLogger(r.Context()) var head string head, r.URL.Path = router.ShiftPath(r.URL.Path) diff --git a/pkg/auth/manager/appauth/appauth.go b/pkg/auth/manager/appauth/appauth.go index e6d2571834..b8fe4811a7 100644 --- a/pkg/auth/manager/appauth/appauth.go +++ b/pkg/auth/manager/appauth/appauth.go @@ -29,10 +29,13 @@ import ( "github.com/cs3org/reva/pkg/auth/manager/registry" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) +const tracerName = "appauth" + func init() { registry.Register("appauth", New) } @@ -60,7 +63,10 @@ func (m *manager) Configure(ml map[string]interface{}) error { } func (m *manager) Authenticate(ctx context.Context, username, password string) (*user.User, map[string]*authpb.Scope, error) { - gtw, err := pool.GetGatewayServiceClient(pool.Endpoint(m.GatewayAddr)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + + gtw, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(m.GatewayAddr)) if err != nil { return nil, nil, err } diff --git a/pkg/auth/manager/demo/demo.go b/pkg/auth/manager/demo/demo.go index c3a23790ca..4d2fb8d6fc 100644 --- a/pkg/auth/manager/demo/demo.go +++ b/pkg/auth/manager/demo/demo.go @@ -27,8 +27,11 @@ import ( "github.com/cs3org/reva/pkg/auth/manager/registry" "github.com/cs3org/reva/pkg/auth/scope" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/tracing" ) +const tracerName = "demo" + func init() { registry.Register("demo", New) } @@ -58,6 +61,9 @@ func (m *manager) Configure(ml map[string]interface{}) error { } func (m *manager) Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + if c, ok := m.credentials[clientID]; ok { if c.Secret == clientSecret { var scopes map[string]*authpb.Scope diff --git a/pkg/auth/manager/impersonator/impersonator.go b/pkg/auth/manager/impersonator/impersonator.go index 19d7f88000..ab9fa75040 100644 --- a/pkg/auth/manager/impersonator/impersonator.go +++ b/pkg/auth/manager/impersonator/impersonator.go @@ -27,8 +27,11 @@ import ( "github.com/cs3org/reva/pkg/auth" "github.com/cs3org/reva/pkg/auth/manager/registry" "github.com/cs3org/reva/pkg/auth/scope" + "github.com/cs3org/reva/pkg/tracing" ) +const tracerName = "impersonator" + func init() { registry.Register("impersonator", New) } @@ -45,6 +48,9 @@ func (m *mgr) Configure(ml map[string]interface{}) error { } func (m *mgr) Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + // allow passing in uid as @ at := strings.LastIndex(clientID, "@") uid := &user.UserId{Type: user.UserType_USER_TYPE_PRIMARY} diff --git a/pkg/auth/manager/json/json.go b/pkg/auth/manager/json/json.go index 1e989fba5f..37fe6dd4fd 100644 --- a/pkg/auth/manager/json/json.go +++ b/pkg/auth/manager/json/json.go @@ -30,10 +30,13 @@ import ( "github.com/cs3org/reva/pkg/auth/manager/registry" "github.com/cs3org/reva/pkg/auth/scope" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) +const tracerName = "json" + func init() { registry.Register("json", New) } @@ -113,6 +116,9 @@ func (m *manager) Configure(ml map[string]interface{}) error { } func (m *manager) Authenticate(ctx context.Context, username string, secret string) (*user.User, map[string]*authpb.Scope, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + if c, ok := m.credentials[username]; ok { if c.Secret == secret { var scopes map[string]*authpb.Scope diff --git a/pkg/auth/manager/ldap/ldap.go b/pkg/auth/manager/ldap/ldap.go index 900d272daf..9d772eff67 100644 --- a/pkg/auth/manager/ldap/ldap.go +++ b/pkg/auth/manager/ldap/ldap.go @@ -34,12 +34,15 @@ import ( "github.com/cs3org/reva/pkg/logger" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/go-ldap/ldap/v3" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) +const tracerName = "ldap" + func init() { registry.Register("ldap", New) } @@ -132,6 +135,9 @@ func (am *mgr) Configure(m map[string]interface{}) error { } func (am *mgr) Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + log := appctx.GetLogger(ctx) l, err := utils.GetLDAPConnection(&am.c.LDAPConn) if err != nil { @@ -171,7 +177,7 @@ func (am *mgr) Authenticate(ctx context.Context, clientID, clientSecret string) OpaqueId: sr.Entries[0].GetEqualFoldAttributeValue(am.c.Schema.UID), Type: user.UserType_USER_TYPE_PRIMARY, // TODO: assign the appropriate user type } - gwc, err := pool.GetGatewayServiceClient(pool.Endpoint(am.c.GatewaySvc)) + gwc, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(am.c.GatewaySvc)) if err != nil { return nil, nil, errors.Wrap(err, "ldap: error getting gateway grpc client") } diff --git a/pkg/auth/manager/machine/machine.go b/pkg/auth/manager/machine/machine.go index a124bbba47..ba7984ad07 100644 --- a/pkg/auth/manager/machine/machine.go +++ b/pkg/auth/manager/machine/machine.go @@ -30,10 +30,13 @@ import ( "github.com/cs3org/reva/pkg/auth/scope" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) +const tracerName = "machine" + // 'machine' is an authentication method used to impersonate users. // To impersonate the given user it's only needed an api-key, saved // in a config file. @@ -71,11 +74,14 @@ func New(conf map[string]interface{}) (auth.Manager, error) { // Authenticate impersonate an user if the provided secret is equal to the api-key func (m *manager) Authenticate(ctx context.Context, user, secret string) (*userpb.User, map[string]*authpb.Scope, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + if m.APIKey != secret { return nil, nil, errtypes.InvalidCredentials("") } - gtw, err := pool.GetGatewayServiceClient(pool.Endpoint(m.GatewayAddr)) + gtw, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(m.GatewayAddr)) if err != nil { return nil, nil, err } diff --git a/pkg/auth/manager/nextcloud/nextcloud.go b/pkg/auth/manager/nextcloud/nextcloud.go index 5d01d264b1..a2dd2c2eb9 100644 --- a/pkg/auth/manager/nextcloud/nextcloud.go +++ b/pkg/auth/manager/nextcloud/nextcloud.go @@ -31,10 +31,13 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth" "github.com/cs3org/reva/pkg/auth/manager/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) +const tracerName = "nextcloud" + func init() { registry.Register("nextcloud", New) } @@ -119,6 +122,9 @@ func (am *Manager) SetHTTPClient(c *http.Client) { } func (am *Manager) do(ctx context.Context, a Action) (int, []byte, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "do") + defer span.End() + log := appctx.GetLogger(ctx) url := am.endPoint + "~" + a.username + "/api/auth/" + a.verb log.Info().Msgf("am.do %s %s %s", url, a.argS, am.sharedSecret) @@ -146,6 +152,9 @@ func (am *Manager) do(ctx context.Context, a Action) (int, []byte, error) { // Authenticate method as defined in https://github.com/cs3org/reva/blob/28500a8/pkg/auth/auth.go#L31-L33 func (am *Manager) Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + type paramsObj struct { ClientID string `json:"clientID"` ClientSecret string `json:"clientSecret"` diff --git a/pkg/auth/manager/nextcloud/nextcloud_server_mock.go b/pkg/auth/manager/nextcloud/nextcloud_server_mock.go index f81e2fcec5..d8380e79d0 100644 --- a/pkg/auth/manager/nextcloud/nextcloud_server_mock.go +++ b/pkg/auth/manager/nextcloud/nextcloud_server_mock.go @@ -26,6 +26,8 @@ import ( "net/http" "net/http/httptest" "strings" + + "github.com/cs3org/reva/pkg/tracing" ) // Response contains data for the Nextcloud mock server to respond @@ -49,6 +51,9 @@ var responses = map[string]Response{ // GetNextcloudServerMock returns a handler that pretends to be a remote Nextcloud server func GetNextcloudServerMock(called *[]string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "GetNextcloudServerMock") + defer span.End() + buf := new(strings.Builder) _, err := io.Copy(buf, r.Body) if err != nil { diff --git a/pkg/auth/manager/oidc/oidc.go b/pkg/auth/manager/oidc/oidc.go index d43e0fdfdc..22dd9b22d8 100644 --- a/pkg/auth/manager/oidc/oidc.go +++ b/pkg/auth/manager/oidc/oidc.go @@ -41,12 +41,15 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/juliangruber/go-intersect" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "golang.org/x/oauth2" ) +const tracerName = "oidc" + func init() { registry.Register("oidc", New) } @@ -148,6 +151,9 @@ func (am *mgr) Configure(m map[string]interface{}) error { // which contains the access token that we can use to contact the UserInfo endpoint // and get the user claims. func (am *mgr) Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + ctx = am.getOAuthCtx(ctx) log := appctx.GetLogger(ctx) @@ -210,7 +216,7 @@ func (am *mgr) Authenticate(ctx context.Context, clientID, clientSecret string) Type: getUserType(claims[am.c.IDClaim].(string)), } - gwc, err := pool.GetGatewayServiceClient(pool.Endpoint(am.c.GatewaySvc)) + gwc, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(am.c.GatewaySvc)) if err != nil { return nil, nil, errors.Wrap(err, "oidc: error getting gateway grpc client") } @@ -265,6 +271,9 @@ func (am *mgr) getUserID(claims map[string]interface{}) (int64, int64) { } func (am *mgr) getOAuthCtx(ctx context.Context) context.Context { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getOAuthCtx") + defer span.End() + // Sometimes for testing we need to skip the TLS check, that's why we need a // custom HTTP client. customHTTPClient := rhttp.GetHTTPClient( @@ -280,6 +289,9 @@ func (am *mgr) getOAuthCtx(ctx context.Context) context.Context { // getOIDCProvider returns a singleton OIDC provider func (am *mgr) getOIDCProvider(ctx context.Context) (*oidc.Provider, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getOIDCProvider") + defer span.End() + ctx = am.getOAuthCtx(ctx) log := appctx.GetLogger(ctx) @@ -303,6 +315,9 @@ func (am *mgr) getOIDCProvider(ctx context.Context) (*oidc.Provider, error) { } func (am *mgr) resolveUser(ctx context.Context, claims map[string]interface{}) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "resolveUser") + defer span.End() + var ( claim string value string @@ -351,7 +366,7 @@ func (am *mgr) resolveUser(ctx context.Context, claims map[string]interface{}) e return nil } - upsc, err := pool.GetGatewayServiceClient(pool.Endpoint(am.c.GatewaySvc)) + upsc, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(am.c.GatewaySvc)) if err != nil { return errors.Wrap(err, "error getting user provider grpc client") } diff --git a/pkg/auth/manager/owncloudsql/accounts/accounts.go b/pkg/auth/manager/owncloudsql/accounts/accounts.go index 1489669892..d205285afe 100644 --- a/pkg/auth/manager/owncloudsql/accounts/accounts.go +++ b/pkg/auth/manager/owncloudsql/accounts/accounts.go @@ -25,9 +25,12 @@ import ( "time" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) +const tracerName = "accounts" + // Accounts represents oc10-style Accounts type Accounts struct { driver string @@ -111,6 +114,9 @@ type Account struct { } func (as *Accounts) rowToAccount(ctx context.Context, row Scannable) (*Account, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "rowToAccount") + defer span.End() + a := Account{} if err := row.Scan(&a.ID, &a.Email, &a.UserID, &a.DisplayName, &a.Quota, &a.LastLogin, &a.Backend, &a.Home, &a.State, &a.PasswordHash, &a.Username, &a.OwnCloudUUID); err != nil { appctx.GetLogger(ctx).Error().Err(err).Msg("could not scan row, skipping") @@ -127,6 +133,9 @@ type Scannable interface { // GetAccountByLogin fetches an account by mail or username func (as *Accounts) GetAccountByLogin(ctx context.Context, login string) (*Account, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAccountByLogin") + defer span.End() + var row *sql.Row username := strings.ToLower(login) // usernames are lowercased in owncloud classic if as.joinUsername { @@ -140,6 +149,9 @@ func (as *Accounts) GetAccountByLogin(ctx context.Context, login string) (*Accou // GetAccountGroups reads the groups for an account func (as *Accounts) GetAccountGroups(ctx context.Context, uid string) ([]string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAccountGroups") + defer span.End() + rows, err := as.db.QueryContext(ctx, "SELECT gid FROM oc_group_user WHERE uid=?", uid) if err != nil { return nil, err diff --git a/pkg/auth/manager/owncloudsql/owncloudsql.go b/pkg/auth/manager/owncloudsql/owncloudsql.go index 65bba2c5a3..40f319289e 100644 --- a/pkg/auth/manager/owncloudsql/owncloudsql.go +++ b/pkg/auth/manager/owncloudsql/owncloudsql.go @@ -36,6 +36,7 @@ import ( "github.com/cs3org/reva/pkg/auth/manager/registry" "github.com/cs3org/reva/pkg/auth/scope" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" @@ -43,6 +44,8 @@ import ( _ "github.com/go-sql-driver/mysql" ) +const tracerName = "owncloudsql" + func init() { registry.Register("owncloudsql", NewMysql) } @@ -110,6 +113,9 @@ func parseConfig(m map[string]interface{}) (*config, error) { } func (m *manager) Authenticate(ctx context.Context, login, clientSecret string) (*user.User, map[string]*authpb.Scope, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + log := appctx.GetLogger(ctx) // 1. find user by login diff --git a/pkg/auth/manager/publicshares/publicshares.go b/pkg/auth/manager/publicshares/publicshares.go index 1a6dc62a16..a2952d4068 100644 --- a/pkg/auth/manager/publicshares/publicshares.go +++ b/pkg/auth/manager/publicshares/publicshares.go @@ -34,10 +34,13 @@ import ( "github.com/cs3org/reva/pkg/auth/scope" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) +const tracerName = "publicshares" + func init() { registry.Register("publicshares", New) } @@ -79,7 +82,10 @@ func (m *manager) Configure(ml map[string]interface{}) error { } func (m *manager) Authenticate(ctx context.Context, token, secret string) (*user.User, map[string]*authpb.Scope, error) { - gwConn, err := pool.GetGatewayServiceClient(pool.Endpoint(m.c.GatewayAddr)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + + gwConn, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(m.c.GatewayAddr)) if err != nil { return nil, nil, err } diff --git a/pkg/auth/registry/static/static.go b/pkg/auth/registry/static/static.go index cb34592bc8..9734bb7f92 100644 --- a/pkg/auth/registry/static/static.go +++ b/pkg/auth/registry/static/static.go @@ -26,9 +26,12 @@ import ( "github.com/cs3org/reva/pkg/auth/registry/registry" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" ) +const tracerName = "static" + func init() { registry.Register("static", New) } @@ -50,6 +53,9 @@ type reg struct { } func (r *reg) ListProviders(ctx context.Context) ([]*registrypb.ProviderInfo, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "ListProviders") + defer span.End() + providers := []*registrypb.ProviderInfo{} for k, v := range r.rules { providers = append(providers, ®istrypb.ProviderInfo{ @@ -61,6 +67,9 @@ func (r *reg) ListProviders(ctx context.Context) ([]*registrypb.ProviderInfo, er } func (r *reg) GetProvider(ctx context.Context, authType string) (*registrypb.ProviderInfo, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "GetProvider") + defer span.End() + for k, v := range r.rules { if k == authType { return ®istrypb.ProviderInfo{ diff --git a/pkg/auth/rpc_auth.go b/pkg/auth/rpc_auth.go index 92dbee5bb4..4a334f10ab 100644 --- a/pkg/auth/rpc_auth.go +++ b/pkg/auth/rpc_auth.go @@ -26,9 +26,12 @@ import ( user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/plugin" + "github.com/cs3org/reva/pkg/tracing" hcplugin "github.com/hashicorp/go-plugin" ) +const tracerName = "authprovider" + func init() { plugin.Register("authprovider", &ProviderPlugin{}) } @@ -88,6 +91,9 @@ type AuthenticateReply struct { // Authenticate RPCClient Authenticate method func (m *RPCClient) Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + ctxVal := appctx.GetKeyValuesFromCtx(ctx) args := AuthenticateArgs{Ctx: ctxVal, ClientID: clientID, ClientSecret: clientSecret} reply := AuthenticateReply{} @@ -113,6 +119,9 @@ func (m *RPCServer) Configure(args ConfigureArg, resp *ConfigureReply) error { // Authenticate RPCServer Authenticate method func (m *RPCServer) Authenticate(args AuthenticateArgs, resp *AuthenticateReply) error { ctx := appctx.PutKeyValuesToCtx(args.Ctx) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Authenticate") + defer span.End() + resp.User, resp.Auth, resp.Error = m.Impl.Authenticate(ctx, args.ClientID, args.ClientSecret) return nil } diff --git a/pkg/auth/scope/lightweight.go b/pkg/auth/scope/lightweight.go index 5ebc8d2225..efa5eb50dd 100644 --- a/pkg/auth/scope/lightweight.go +++ b/pkg/auth/scope/lightweight.go @@ -26,11 +26,15 @@ import ( collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/rs/zerolog" ) -func lightweightAccountScope(_ context.Context, scope *authpb.Scope, resource interface{}, _ *zerolog.Logger) (bool, error) { +func lightweightAccountScope(ctx context.Context, scope *authpb.Scope, resource interface{}, _ *zerolog.Logger) (bool, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "lightweightAccountScope") + defer span.End() + // Lightweight accounts have access to resources shared with them. // These cannot be resolved from here, but need to be added to the scope from // where the call to mint tokens is made. diff --git a/pkg/auth/scope/publicshare.go b/pkg/auth/scope/publicshare.go index bfa538040f..0260cd7489 100644 --- a/pkg/auth/scope/publicshare.go +++ b/pkg/auth/scope/publicshare.go @@ -33,11 +33,15 @@ import ( registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/rs/zerolog" ) func publicshareScope(ctx context.Context, scope *authpb.Scope, resource interface{}, logger *zerolog.Logger) (bool, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "publicshareScope") + defer span.End() + var share link.PublicShare err := utils.UnmarshalJSONToProtoV1(scope.Resource.Value, &share) if err != nil { @@ -95,6 +99,9 @@ func publicshareScope(ctx context.Context, scope *authpb.Scope, resource interfa } func checkStorageRef(ctx context.Context, s *link.PublicShare, r *provider.Reference) bool { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "checkStorageRef") + defer span.End() + // r: > // OR // r: > diff --git a/pkg/auth/scope/receivedshare.go b/pkg/auth/scope/receivedshare.go index 81236a3c35..091915ec84 100644 --- a/pkg/auth/scope/receivedshare.go +++ b/pkg/auth/scope/receivedshare.go @@ -26,11 +26,15 @@ import ( collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/rs/zerolog" ) -func receivedShareScope(_ context.Context, scope *authpb.Scope, resource interface{}, logger *zerolog.Logger) (bool, error) { +func receivedShareScope(ctx context.Context, scope *authpb.Scope, resource interface{}, logger *zerolog.Logger) (bool, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "receivedShareScope") + defer span.End() + var share collaboration.ReceivedShare err := utils.UnmarshalJSONToProtoV1(scope.Resource.Value, &share) if err != nil { diff --git a/pkg/auth/scope/resourceinfo.go b/pkg/auth/scope/resourceinfo.go index 07a49f7642..1e1605e9fb 100644 --- a/pkg/auth/scope/resourceinfo.go +++ b/pkg/auth/scope/resourceinfo.go @@ -32,10 +32,14 @@ import ( types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" ) -func resourceinfoScope(_ context.Context, scope *authpb.Scope, resource interface{}, logger *zerolog.Logger) (bool, error) { +func resourceinfoScope(ctx context.Context, scope *authpb.Scope, resource interface{}, logger *zerolog.Logger) (bool, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "resourceinfoScope") + defer span.End() + var r provider.ResourceInfo err := utils.UnmarshalJSONToProtoV1(scope.Resource.Value, &r) if err != nil { diff --git a/pkg/auth/scope/scope.go b/pkg/auth/scope/scope.go index c040854e80..d3e08232ea 100644 --- a/pkg/auth/scope/scope.go +++ b/pkg/auth/scope/scope.go @@ -24,9 +24,12 @@ import ( authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/tracing" "github.com/rs/zerolog" ) +const tracerName = "scope" + // Verifier is the function signature which every scope verifier should implement. type Verifier func(context.Context, *authpb.Scope, interface{}, *zerolog.Logger) (bool, error) @@ -42,6 +45,9 @@ var supportedScopes = map[string]Verifier{ // VerifyScope is the function to be called when dismantling tokens to check if // the token has access to a particular resource. func VerifyScope(ctx context.Context, scopeMap map[string]*authpb.Scope, resource interface{}) (bool, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "VerifyScope") + defer span.End() + logger := appctx.GetLogger(ctx) for k, scope := range scopeMap { for s, f := range supportedScopes { diff --git a/pkg/auth/scope/share.go b/pkg/auth/scope/share.go index 6284efd007..d2f2211e81 100644 --- a/pkg/auth/scope/share.go +++ b/pkg/auth/scope/share.go @@ -29,11 +29,15 @@ import ( registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/rs/zerolog" ) -func shareScope(_ context.Context, scope *authpb.Scope, resource interface{}, logger *zerolog.Logger) (bool, error) { +func shareScope(ctx context.Context, scope *authpb.Scope, resource interface{}, logger *zerolog.Logger) (bool, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "shareScope") + defer span.End() + var share collaboration.Share err := utils.UnmarshalJSONToProtoV1(scope.Resource.Value, &share) if err != nil { diff --git a/pkg/auth/scope/user.go b/pkg/auth/scope/user.go index b20330caf1..fc5789aa06 100644 --- a/pkg/auth/scope/user.go +++ b/pkg/auth/scope/user.go @@ -24,11 +24,15 @@ import ( authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/rs/zerolog" ) -func userScope(_ context.Context, scope *authpb.Scope, resource interface{}, _ *zerolog.Logger) (bool, error) { +func userScope(ctx context.Context, scope *authpb.Scope, resource interface{}, _ *zerolog.Logger) (bool, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "userScope") + defer span.End() + // Always return true. Registered users can access all paths. // TODO(ishank011): Add checks for read/write permissions. return true, nil diff --git a/pkg/cbox/favorite/sql/sql.go b/pkg/cbox/favorite/sql/sql.go index ebb6c85ec9..df655fb15f 100644 --- a/pkg/cbox/favorite/sql/sql.go +++ b/pkg/cbox/favorite/sql/sql.go @@ -29,9 +29,12 @@ import ( ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/storage/favorite" "github.com/cs3org/reva/pkg/storage/favorite/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" ) +const tracerName = "cbox" + func init() { registry.Register("sql", New) } @@ -68,6 +71,9 @@ func New(m map[string]interface{}) (favorite.Manager, error) { } func (m *mgr) ListFavorites(ctx context.Context, userID *user.UserId) ([]*provider.ResourceId, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListFavorites") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) infos := []*provider.ResourceId{} query := `SELECT fileid_prefix, fileid FROM cbox_metadata WHERE uid=? AND tag_key="fav"` @@ -92,6 +98,9 @@ func (m *mgr) ListFavorites(ctx context.Context, userID *user.UserId) ([]*provid } func (m *mgr) SetFavorite(ctx context.Context, userID *user.UserId, resourceInfo *provider.ResourceInfo) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetFavorite") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) // The primary key is just the ID in the table, it should ideally be (uid, fileid_prefix, fileid, tag_key) @@ -117,6 +126,9 @@ func (m *mgr) SetFavorite(ctx context.Context, userID *user.UserId, resourceInfo } func (m *mgr) UnsetFavorite(ctx context.Context, userID *user.UserId, resourceInfo *provider.ResourceInfo) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UnsetFavorite") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) stmt, err := m.db.Prepare(`DELETE FROM cbox_metadata WHERE uid=? AND fileid_prefix=? AND fileid=? AND tag_key="fav"`) if err != nil { diff --git a/pkg/cbox/group/rest/rest.go b/pkg/cbox/group/rest/rest.go index e7996fab99..68a5dff9ec 100644 --- a/pkg/cbox/group/rest/rest.go +++ b/pkg/cbox/group/rest/rest.go @@ -34,11 +34,14 @@ import ( utils "github.com/cs3org/reva/pkg/cbox/utils" "github.com/cs3org/reva/pkg/group" "github.com/cs3org/reva/pkg/group/manager/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/gomodule/redigo/redis" "github.com/mitchellh/mapstructure" "github.com/rs/zerolog/log" ) +const tracerName = "rest" + func init() { registry.Register("rest", New) } @@ -186,6 +189,9 @@ func (m *manager) fetchAllGroupAccounts() error { } func (m *manager) parseAndCacheGroup(ctx context.Context, groupData map[string]interface{}) (*grouppb.Group, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "parseAndCacheGroup") + defer span.End() + id, ok := groupData["groupIdentifier"].(string) if !ok { return nil, errors.New("rest: missing upn in user data") @@ -225,6 +231,9 @@ func (m *manager) parseAndCacheGroup(ctx context.Context, groupData map[string]i } func (m *manager) GetGroup(ctx context.Context, gid *grouppb.GroupId, skipFetchingMembers bool) (*grouppb.Group, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetGroup") + defer span.End() + g, err := m.fetchCachedGroupDetails(gid) if err != nil { return nil, err @@ -242,6 +251,9 @@ func (m *manager) GetGroup(ctx context.Context, gid *grouppb.GroupId, skipFetchi } func (m *manager) GetGroupByClaim(ctx context.Context, claim, value string, skipFetchingMembers bool) (*grouppb.Group, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetGroupByClaim") + defer span.End() + if claim == "group_name" { return m.GetGroup(ctx, &grouppb.GroupId{OpaqueId: value}, skipFetchingMembers) } @@ -263,6 +275,8 @@ func (m *manager) GetGroupByClaim(ctx context.Context, claim, value string, skip } func (m *manager) FindGroups(ctx context.Context, query string, skipFetchingMembers bool) ([]*grouppb.Group, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "FindGroups") + defer span.End() // Look at namespaces filters. If the query starts with: // "a" or none => get egroups @@ -282,6 +296,8 @@ func (m *manager) FindGroups(ctx context.Context, query string, skipFetchingMemb } func (m *manager) GetMembers(ctx context.Context, gid *grouppb.GroupId) ([]*userpb.UserId, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetMembers") + defer span.End() users, err := m.fetchCachedGroupMembers(gid) if err == nil { @@ -320,6 +336,9 @@ func (m *manager) GetMembers(ctx context.Context, gid *grouppb.GroupId) ([]*user } func (m *manager) HasMember(ctx context.Context, gid *grouppb.GroupId, uid *userpb.UserId) (bool, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "HasMember") + defer span.End() + groupMemers, err := m.GetMembers(ctx, gid) if err != nil { return false, err diff --git a/pkg/cbox/http/services/eosprojects/eosprojects.go b/pkg/cbox/http/services/eosprojects/eosprojects.go index 18807407aa..a84a1691cf 100644 --- a/pkg/cbox/http/services/eosprojects/eosprojects.go +++ b/pkg/cbox/http/services/eosprojects/eosprojects.go @@ -14,17 +14,21 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/juliangruber/go-intersect" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/rs/zerolog" ) +const tracerName = "eosprojects" + func init() { global.Register("eosprojects", New) } type eosProj struct { + tracing.HttpMiddleware log *zerolog.Logger c *config db *sql.DB @@ -94,6 +98,9 @@ func New(conf map[string]interface{}, log *zerolog.Logger) (global.Service, erro func (e *eosProj) Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Wellknown Service HTTP Handler") + defer span.End() + ctx := r.Context() projects, err := e.getProjects(ctx) @@ -141,6 +148,9 @@ func (e *eosProj) Unprotected() []string { // Insecure bool `mapstructure:"insecure" docs:"false;Whether to skip certificate checks when sending requests."` func (e *eosProj) getProjects(ctx context.Context) ([]*project, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getProjects") + defer span.End() + user, ok := ctxpkg.ContextGetUser(ctx) if !ok { return nil, errtypes.UserRequired("") @@ -209,7 +219,10 @@ func (e *eosProj) getProjects(ctx context.Context) ([]*project, error) { } func (e *eosProj) getUserGroups(ctx context.Context, user *userpb.User) ([]string, error) { - client, err := pool.GetGatewayServiceClient(pool.Endpoint(e.c.GatewaySvc)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getUserGroups") + defer span.End() + + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(e.c.GatewaySvc)) if err != nil { return nil, err } diff --git a/pkg/cbox/preferences/sql/sql.go b/pkg/cbox/preferences/sql/sql.go index 67ba2ad731..8f22ad3a17 100644 --- a/pkg/cbox/preferences/sql/sql.go +++ b/pkg/cbox/preferences/sql/sql.go @@ -27,9 +27,12 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/preferences" "github.com/cs3org/reva/pkg/preferences/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" ) +const tracerName = "sql" + func init() { registry.Register("sql", New) } @@ -66,6 +69,9 @@ func New(m map[string]interface{}) (preferences.Manager, error) { } func (m *mgr) SetKey(ctx context.Context, key, namespace, value string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetKey") + defer span.End() + user, ok := ctxpkg.ContextGetUser(ctx) if !ok { return errtypes.UserRequired("preferences: error getting user from ctx") @@ -84,6 +90,9 @@ func (m *mgr) SetKey(ctx context.Context, key, namespace, value string) error { } func (m *mgr) GetKey(ctx context.Context, key, namespace string) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetKey") + defer span.End() + user, ok := ctxpkg.ContextGetUser(ctx) if !ok { return "", errtypes.UserRequired("preferences: error getting user from ctx") diff --git a/pkg/cbox/publicshare/sql/sql.go b/pkg/cbox/publicshare/sql/sql.go index 8b1581e085..796b829560 100644 --- a/pkg/cbox/publicshare/sql/sql.go +++ b/pkg/cbox/publicshare/sql/sql.go @@ -41,11 +41,14 @@ import ( "github.com/cs3org/reva/pkg/publicshare" "github.com/cs3org/reva/pkg/publicshare/manager/registry" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) +const tracerName = "sql" + const ( publicShareType = 3 @@ -129,6 +132,8 @@ func New(m map[string]interface{}) (publicshare.Manager, error) { } func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *provider.ResourceInfo, g *link.Grant, description string, internal bool) (*link.PublicShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreatePublicShare") + defer span.End() tkn := utils.RandString(15) now := time.Now().Unix() @@ -211,6 +216,9 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr } func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link.UpdatePublicShareRequest, g *link.Grant) (*link.PublicShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdatePublicShare") + defer span.End() + query := "update oc_share set " paramsMap := map[string]interface{}{} params := []interface{}{} @@ -269,6 +277,9 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link } func (m *manager) getByToken(ctx context.Context, token string, u *user.User) (*link.PublicShare, string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getByToken") + defer span.End() + s := conversions.DBShare{Token: token} query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source, coalesce(item_type, '') as item_type, coalesce(expiration, '') as expiration, coalesce(share_name, '') as share_name, id, stime, permissions, quicklink, description FROM oc_share WHERE (orphan = 0 or orphan IS NULL) AND share_type=? AND token=?" if err := m.db.QueryRow(query, publicShareType, token).Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.Prefix, &s.ItemSource, &s.ItemType, &s.Expiration, &s.ShareName, &s.ID, &s.STime, &s.Permissions, &s.Quicklink, &s.Description); err != nil { @@ -281,6 +292,9 @@ func (m *manager) getByToken(ctx context.Context, token string, u *user.User) (* } func (m *manager) getByID(ctx context.Context, id *link.PublicShareId, u *user.User) (*link.PublicShare, string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getByID") + defer span.End() + uid := conversions.FormatUserID(u.Id) s := conversions.DBShare{ID: id.OpaqueId} query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source, coalesce(item_type, '') as item_type, coalesce(token,'') as token, coalesce(expiration, '') as expiration, coalesce(share_name, '') as share_name, stime, permissions, quicklink, description FROM oc_share WHERE (orphan = 0 or orphan IS NULL) AND share_type=? AND id=? AND (uid_owner=? OR uid_initiator=?)" @@ -294,6 +308,9 @@ func (m *manager) getByID(ctx context.Context, id *link.PublicShareId, u *user.U } func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference, sign bool) (*link.PublicShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPublicShare") + defer span.End() + var s *link.PublicShare var pw string var err error @@ -360,6 +377,9 @@ func (m *manager) isProjectAdmin(ctx context.Context, u *user.User) bool { } func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter, md *provider.ResourceInfo, sign bool) ([]*link.PublicShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListPublicShares") + defer span.End() + query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source, coalesce(item_type, '') as item_type, coalesce(token,'') as token, coalesce(expiration, '') as expiration, coalesce(share_name, '') as share_name, id, stime, permissions, quicklink, description FROM oc_share WHERE (orphan = 0 or orphan IS NULL) AND (share_type=?) AND internal=false" var resourceFilters, ownerFilters, creatorFilters string var resourceParams, ownerParams, creatorParams []interface{} @@ -441,6 +461,9 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] } func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RevokePublicShare") + defer span.End() + uid := conversions.FormatUserID(u.Id) query := "delete from oc_share where " params := []interface{}{} @@ -476,6 +499,9 @@ func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, ref *link } func (m *manager) GetPublicShareByToken(ctx context.Context, token string, auth *link.PublicShareAuthentication, sign bool) (*link.PublicShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPublicShareByToken") + defer span.End() + s := conversions.DBShare{Token: token} query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source, coalesce(item_type, '') as item_type, coalesce(expiration, '') as expiration, coalesce(share_name, '') as share_name, id, stime, permissions, quicklink, description FROM oc_share WHERE share_type=? AND token=?" if err := m.db.QueryRow(query, publicShareType, token).Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.Prefix, &s.ItemSource, &s.ItemType, &s.Expiration, &s.ShareName, &s.ID, &s.STime, &s.Permissions, &s.Quicklink, &s.Description); err != nil { @@ -527,6 +553,9 @@ func (m *manager) cleanupExpiredShares() error { } func (m *manager) uidOwnerFilters(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter) (string, []interface{}, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "uidOwnerFilters") + defer span.End() + uid := conversions.FormatUserID(u.Id) query := "uid_owner=? or uid_initiator=?" diff --git a/pkg/cbox/share/sql/sql.go b/pkg/cbox/share/sql/sql.go index eff330ab21..e1602e4dbf 100644 --- a/pkg/cbox/share/sql/sql.go +++ b/pkg/cbox/share/sql/sql.go @@ -38,6 +38,7 @@ import ( "github.com/cs3org/reva/pkg/share" "github.com/cs3org/reva/pkg/share/manager/registry" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" @@ -47,6 +48,8 @@ import ( _ "github.com/go-sql-driver/mysql" ) +const tracerName = "sql" + const ( shareTypeUser = 0 shareTypeGroup = 1 @@ -104,6 +107,9 @@ func parseConfig(m map[string]interface{}) (*config, error) { } func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collaboration.ShareGrant) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Share") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) // do not allow share to myself or the owner if share is for a user @@ -175,6 +181,9 @@ func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collabora } func (m *mgr) getByID(ctx context.Context, id *collaboration.ShareId, checkOwner bool) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getByID") + defer span.End() + uid := conversions.FormatUserID(ctxpkg.ContextMustGetUser(ctx).Id) s := conversions.DBShare{ID: id.OpaqueId} query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, lower(coalesce(share_with, '')) as share_with, coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source, coalesce(item_type, '') as item_type, stime, permissions, share_type FROM oc_share WHERE (orphan = 0 or orphan IS NULL) AND id=?" @@ -193,6 +202,9 @@ func (m *mgr) getByID(ctx context.Context, id *collaboration.ShareId, checkOwner } func (m *mgr) getByKey(ctx context.Context, key *collaboration.ShareKey, checkOwner bool) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getByKey") + defer span.End() + owner := conversions.FormatUserID(key.Owner) uid := conversions.FormatUserID(ctxpkg.ContextMustGetUser(ctx).Id) @@ -214,6 +226,8 @@ func (m *mgr) getByKey(ctx context.Context, key *collaboration.ShareKey, checkOw } func (m *mgr) GetShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetShare") + defer span.End() var s *collaboration.Share var err error @@ -251,6 +265,9 @@ func (m *mgr) GetShare(ctx context.Context, ref *collaboration.ShareReference) ( } func (m *mgr) Unshare(ctx context.Context, ref *collaboration.ShareReference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Unshare") + defer span.End() + var query string params := []interface{}{} switch { @@ -297,6 +314,9 @@ func (m *mgr) Unshare(ctx context.Context, ref *collaboration.ShareReference) er } func (m *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReference, p *collaboration.SharePermissions) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateShare") + defer span.End() + permissions := conversions.SharePermToInt(p.Permissions) var query string @@ -337,7 +357,7 @@ func (m *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReference } func (m *mgr) getPath(ctx context.Context, resID *provider.ResourceId) (string, error) { - client, err := pool.GetGatewayServiceClient(pool.Endpoint(m.c.GatewaySvc)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(m.c.GatewaySvc)) if err != nil { return "", err } @@ -415,6 +435,9 @@ func (m *mgr) isProjectAdmin(u *user.User, path string) bool { } func (m *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListShares") + defer span.End() + query := `select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, lower(coalesce(share_with, '')) as share_with, coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source, coalesce(item_type, '') as item_type, id, stime, permissions, share_type @@ -461,6 +484,9 @@ func (m *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) ( // we list the shares that are targeted to the user in context or to the user groups. func (m *mgr) ListReceivedShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListReceivedShares") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) uid := conversions.FormatUserID(user.Id) @@ -513,6 +539,9 @@ func (m *mgr) ListReceivedShares(ctx context.Context, filters []*collaboration.F } func (m *mgr) getReceivedByID(ctx context.Context, id *collaboration.ShareId) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getReceivedByID") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) uid := conversions.FormatUserID(user.Id) @@ -542,6 +571,9 @@ func (m *mgr) getReceivedByID(ctx context.Context, id *collaboration.ShareId) (* } func (m *mgr) getReceivedByKey(ctx context.Context, key *collaboration.ShareKey) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getReceivedByKey") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) uid := conversions.FormatUserID(user.Id) @@ -573,6 +605,9 @@ func (m *mgr) getReceivedByKey(ctx context.Context, key *collaboration.ShareKey) } func (m *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetReceivedShare") + defer span.End() + var s *collaboration.ReceivedShare var err error switch { @@ -593,6 +628,9 @@ func (m *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareRefe } func (m *mgr) UpdateReceivedShare(ctx context.Context, share *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateReceivedShare") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) rs, err := m.GetReceivedShare(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{Id: share.Share.Id}}) @@ -647,6 +685,9 @@ func (m *mgr) appendUidOwnerFilters(ctx context.Context, query string, params [] } func (m *mgr) uidOwnerFilters(ctx context.Context) (string, []interface{}, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "uidOwnerFilters") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) uid := conversions.FormatUserID(user.Id) diff --git a/pkg/cbox/storage/eoshomewrapper/eoshomewrapper.go b/pkg/cbox/storage/eoshomewrapper/eoshomewrapper.go index 39a021d92b..f0abcec76c 100644 --- a/pkg/cbox/storage/eoshomewrapper/eoshomewrapper.go +++ b/pkg/cbox/storage/eoshomewrapper/eoshomewrapper.go @@ -30,10 +30,13 @@ import ( "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" "github.com/cs3org/reva/pkg/storage/utils/eosfs" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) +const tracerName = "eoshomewrapper" + func init() { registry.Register("eoshomewrapper", New) } @@ -89,6 +92,9 @@ func New(m map[string]interface{}) (storage.FS, error) { // StorageId in the ResourceInfo objects. func (w *wrapper) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetMD") + defer span.End() + res, err := w.FS.GetMD(ctx, ref, mdKeys) if err != nil { return nil, err @@ -103,6 +109,9 @@ func (w *wrapper) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []s } func (w *wrapper) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys []string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListFolder") + defer span.End() + res, err := w.FS.ListFolder(ctx, ref, mdKeys) if err != nil { return nil, err @@ -114,10 +123,16 @@ func (w *wrapper) ListFolder(ctx context.Context, ref *provider.Reference, mdKey } func (w *wrapper) DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DenyGrant") + defer span.End() + return errtypes.NotSupported("eos: deny grant is only enabled for project spaces") } func (w *wrapper) getMountID(ctx context.Context, r *provider.ResourceInfo) string { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getMountID") + defer span.End() + u := ctxpkg.ContextMustGetUser(ctx) b := bytes.Buffer{} if err := w.mountIDTemplate.Execute(&b, u); err != nil { diff --git a/pkg/cbox/storage/eoswrapper/eoswrapper.go b/pkg/cbox/storage/eoswrapper/eoswrapper.go index 29c191a484..4c4905d74b 100644 --- a/pkg/cbox/storage/eoswrapper/eoswrapper.go +++ b/pkg/cbox/storage/eoswrapper/eoswrapper.go @@ -32,11 +32,14 @@ import ( "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" "github.com/cs3org/reva/pkg/storage/utils/eosfs" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) +const tracerName = "eoswrapper" + func init() { registry.Register("eoswrapper", New) } @@ -106,6 +109,9 @@ func New(m map[string]interface{}) (storage.FS, error) { // StorageId in the ResourceInfo objects. func (w *wrapper) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetMD") + defer span.End() + res, err := w.FS.GetMD(ctx, ref, mdKeys) if err != nil { return nil, err @@ -126,6 +132,9 @@ func (w *wrapper) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []s } func (w *wrapper) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys []string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListFolder") + defer span.End() + res, err := w.FS.ListFolder(ctx, ref, mdKeys) if err != nil { return nil, err @@ -140,6 +149,9 @@ func (w *wrapper) ListFolder(ctx context.Context, ref *provider.Reference, mdKey } func (w *wrapper) ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListRevisions") + defer span.End() + if err := w.userIsProjectAdmin(ctx, ref); err != nil { return nil, err } @@ -148,6 +160,9 @@ func (w *wrapper) ListRevisions(ctx context.Context, ref *provider.Reference) ([ } func (w *wrapper) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DownloadRevision") + defer span.End() + if err := w.userIsProjectAdmin(ctx, ref); err != nil { return nil, err } @@ -156,6 +171,9 @@ func (w *wrapper) DownloadRevision(ctx context.Context, ref *provider.Reference, } func (w *wrapper) RestoreRevision(ctx context.Context, ref *provider.Reference, revisionKey string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreRevision") + defer span.End() + if err := w.userIsProjectAdmin(ctx, ref); err != nil { return err } @@ -164,6 +182,9 @@ func (w *wrapper) RestoreRevision(ctx context.Context, ref *provider.Reference, } func (w *wrapper) DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DenyGrant") + defer span.End() + // This is only allowed for project space admins if strings.HasPrefix(w.conf.Namespace, eosProjectsNamespace) { if err := w.userIsProjectAdmin(ctx, ref); err != nil { @@ -176,6 +197,9 @@ func (w *wrapper) DenyGrant(ctx context.Context, ref *provider.Reference, g *pro } func (w *wrapper) getMountID(ctx context.Context, r *provider.ResourceInfo) string { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getMountID") + defer span.End() + if r == nil { return "" } @@ -187,6 +211,9 @@ func (w *wrapper) getMountID(ctx context.Context, r *provider.ResourceInfo) stri } func (w *wrapper) setProjectSharingPermissions(ctx context.Context, r *provider.ResourceInfo) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "setProjectSharingPermissions") + defer span.End() + // Check if this storage provider corresponds to a project spaces instance if strings.HasPrefix(w.conf.Namespace, eosProjectsNamespace) { @@ -220,6 +247,9 @@ func (w *wrapper) setProjectSharingPermissions(ctx context.Context, r *provider. } func (w *wrapper) userIsProjectAdmin(ctx context.Context, ref *provider.Reference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "userIsProjectAdmin") + defer span.End() + // Check if this storage provider corresponds to a project spaces instance if !strings.HasPrefix(w.conf.Namespace, eosProjectsNamespace) { return nil diff --git a/pkg/cbox/user/rest/rest.go b/pkg/cbox/user/rest/rest.go index de2d9fbfe8..5d4c4eb9be 100644 --- a/pkg/cbox/user/rest/rest.go +++ b/pkg/cbox/user/rest/rest.go @@ -30,6 +30,7 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" "github.com/cs3org/reva/pkg/appctx" utils "github.com/cs3org/reva/pkg/cbox/utils" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/user" "github.com/cs3org/reva/pkg/user/manager/registry" "github.com/gomodule/redigo/redis" @@ -38,6 +39,8 @@ import ( "github.com/rs/zerolog/log" ) +const tracerName = "rest" + func init() { registry.Register("rest", New) } @@ -194,6 +197,9 @@ func (m *manager) fetchAllUserAccounts() error { } func (m *manager) parseAndCacheUser(ctx context.Context, userData map[string]interface{}) (*userpb.User, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "parseAndCacheUser") + defer span.End() + upn, ok := userData["upn"].(string) if !ok { return nil, errors.New("rest: missing upn in user data") @@ -226,6 +232,9 @@ func (m *manager) parseAndCacheUser(ctx context.Context, userData map[string]int } func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetUser") + defer span.End() + u, err := m.fetchCachedUserDetails(uid) if err != nil { return nil, err @@ -243,6 +252,9 @@ func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingG } func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetUserByClaim") + defer span.End() + u, err := m.fetchCachedUserByParam(claim, value) if err != nil { return nil, err @@ -260,6 +272,8 @@ func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipF } func (m *manager) FindUsers(ctx context.Context, query string, skipFetchingGroups bool) ([]*userpb.User, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "FindUsers") + defer span.End() // Look at namespaces filters. If the query starts with: // "a" => look into primary/secondary/service accounts @@ -311,6 +325,9 @@ func isUserAnyType(user *userpb.User, types []userpb.UserType) bool { } func (m *manager) GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetUserGroups") + defer span.End() + groups, err := m.fetchCachedUserGroups(uid) if err == nil { return groups, nil @@ -345,6 +362,9 @@ func (m *manager) GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]stri } func (m *manager) IsInGroup(ctx context.Context, uid *userpb.UserId, group string) (bool, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "IsInGroup") + defer span.End() + userGroups, err := m.GetUserGroups(ctx, uid) if err != nil { return false, err diff --git a/pkg/cbox/utils/tokenmanagement.go b/pkg/cbox/utils/tokenmanagement.go index 8a995dc324..447e61917b 100644 --- a/pkg/cbox/utils/tokenmanagement.go +++ b/pkg/cbox/utils/tokenmanagement.go @@ -30,9 +30,12 @@ import ( "time" "github.com/cs3org/reva/pkg/rhttp" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" ) +const tracerName = "utils" + // APITokenManager stores config related to api management type APITokenManager struct { oidcToken OIDCToken @@ -72,6 +75,9 @@ func InitAPITokenManager(conf map[string]interface{}) (*APITokenManager, error) } func (a *APITokenManager) renewAPIToken(ctx context.Context, forceRenewal bool) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "renewAPIToken") + defer span.End() + // Received tokens have an expiration time of 20 minutes. // Take a couple of seconds as buffer time for the API call to complete if forceRenewal || a.oidcToken.tokenExpirationTime.Before(time.Now().Add(time.Second*time.Duration(2))) { @@ -90,6 +96,8 @@ func (a *APITokenManager) renewAPIToken(ctx context.Context, forceRenewal bool) } func (a *APITokenManager) getAPIToken(ctx context.Context) (string, time.Time, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getAPIToken") + defer span.End() params := url.Values{ "grant_type": {"client_credentials"}, @@ -130,6 +138,9 @@ func (a *APITokenManager) getAPIToken(ctx context.Context) (string, time.Time, e // SendAPIGetRequest makes an API GET Request to the passed URL func (a *APITokenManager) SendAPIGetRequest(ctx context.Context, url string, forceRenewal bool) (map[string]interface{}, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SendAPIGetRequest") + defer span.End() + err := a.renewAPIToken(ctx, forceRenewal) if err != nil { return nil, err diff --git a/pkg/eosclient/eosbinary/eosbinary.go b/pkg/eosclient/eosbinary/eosbinary.go index 0f80ec55c6..8890cf0634 100644 --- a/pkg/eosclient/eosbinary/eosbinary.go +++ b/pkg/eosclient/eosbinary/eosbinary.go @@ -40,7 +40,6 @@ import ( "github.com/cs3org/reva/pkg/storage/utils/acl" "github.com/google/uuid" "github.com/pkg/errors" - "go.opentelemetry.io/otel/trace" ) const ( @@ -234,9 +233,6 @@ func (c *Client) executeEOS(ctx context.Context, cmdArgs []string, auth eosclien cmd.Args = append(cmd.Args, cmdArgs...) - span := trace.SpanFromContext(ctx) - cmd.Args = append(cmd.Args, "--comment", span.SpanContext().TraceID().String()) - err := cmd.Run() var exitStatus int diff --git a/pkg/eosclient/eosgrpc/eosgrpc.go b/pkg/eosclient/eosgrpc/eosgrpc.go index 47bd3c4a7f..5efd5e3529 100644 --- a/pkg/eosclient/eosgrpc/eosgrpc.go +++ b/pkg/eosclient/eosgrpc/eosgrpc.go @@ -1238,8 +1238,10 @@ func (c *Client) List(ctx context.Context, auth eosclient.Authorization, dpath s // Read reads a file from the mgm and returns a handle to read it // This handle could be directly the body of the response or a local tmp file -// returning a handle to the body is nice, yet it gives less control on the transaction -// itself, e.g. strange timeouts or TCP issues may be more difficult to trace +// +// returning a handle to the body is nice, yet it gives less control on the transaction +// itself, e.g. strange timeouts or TCP issues may be more difficult to trace +// // Let's consider this experimental for the moment, maybe I'll like to add a config // parameter to choose between the two behaviours func (c *Client) Read(ctx context.Context, auth eosclient.Authorization, path string) (io.ReadCloser, error) { diff --git a/pkg/mentix/key/apikey.go b/pkg/mentix/key/apikey.go index 8da609a016..3481b293b0 100644 --- a/pkg/mentix/key/apikey.go +++ b/pkg/mentix/key/apikey.go @@ -48,7 +48,8 @@ const ( // GenerateAPIKey generates a new (random) API key which also contains flags and a (salted) hash. // An API key has the following format: -// +// +// func GenerateAPIKey(salt string, flags int) (APIKey, error) { if len(salt) == 0 { return "", errors.Errorf("no salt specified") diff --git a/pkg/mentix/mentix.go b/pkg/mentix/mentix.go index 0b07e811f5..90ebd4a0f9 100644 --- a/pkg/mentix/mentix.go +++ b/pkg/mentix/mentix.go @@ -34,6 +34,7 @@ import ( "github.com/cs3org/reva/pkg/mentix/exchangers/exporters" "github.com/cs3org/reva/pkg/mentix/exchangers/importers" "github.com/cs3org/reva/pkg/mentix/meshdata" + "github.com/cs3org/reva/pkg/tracing" ) // Mentix represents the main Mentix service object. @@ -50,6 +51,8 @@ type Mentix struct { updateInterval time.Duration } +const tracerName = "mentix" + const ( runLoopSleeptime = time.Millisecond * 1000 ) @@ -294,6 +297,9 @@ func (mntx *Mentix) GetRequestExporters() []exchangers.RequestExchanger { // RequestHandler handles any incoming HTTP requests by asking each RequestExchanger whether it wants to // handle the request (usually based on the relative URL path). func (mntx *Mentix) RequestHandler(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Mentix RequestHandler") + defer span.End() + defer r.Body.Close() log := appctx.GetLogger(r.Context()) diff --git a/pkg/registry/config_test.go b/pkg/registry/config_test.go index d981677da9..a065974d5c 100644 --- a/pkg/registry/config_test.go +++ b/pkg/registry/config_test.go @@ -28,20 +28,20 @@ config example: --- services: - authprovider: - basic: - name: auth-basic - nodes: - - address: 0.0.0.0:1234 - metadata: - version: v0.1.0 - bearer: - name: auth-bearer - nodes: - - address: 0.0.0.0:5678 - metadata: - version: v0.1.0 + authprovider: + basic: + name: auth-basic + nodes: + - address: 0.0.0.0:1234 + metadata: + version: v0.1.0 + bearer: + name: auth-bearer + nodes: + - address: 0.0.0.0:5678 + metadata: + version: v0.1.0 */ func TestParseConfig(t *testing.T) { type args struct { diff --git a/pkg/rgrpc/rgrpc.go b/pkg/rgrpc/rgrpc.go index 05fa952153..b0844c7024 100644 --- a/pkg/rgrpc/rgrpc.go +++ b/pkg/rgrpc/rgrpc.go @@ -31,12 +31,11 @@ import ( "github.com/cs3org/reva/internal/grpc/interceptors/token" "github.com/cs3org/reva/internal/grpc/interceptors/useragent" "github.com/cs3org/reva/pkg/sharedconf" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/tracing" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/rs/zerolog" - "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "google.golang.org/grpc" "google.golang.org/grpc/reflection" ) @@ -80,6 +79,7 @@ type Service interface { Register(ss *grpc.Server) io.Closer UnprotectedEndpoints() []string + tracing.GrpcMiddlewarer } type unaryInterceptorTriple struct { @@ -199,7 +199,8 @@ func (s *Server) registerServices() error { } grpcServer := grpc.NewServer(opts...) - for _, svc := range s.services { + for name, svc := range s.services { + svc.SetInterceptors(name) svc.Register(grpcServer) } @@ -282,19 +283,15 @@ func (s *Server) getInterceptors(unprotected []string) ([]grpc.ServerOption, err s.log.Info().Msgf("rgrpc: chaining grpc unary interceptor %s with priority %d", t.Name, t.Priority) } - unaryInterceptors = append(unaryInterceptors, - otelgrpc.UnaryServerInterceptor( - otelgrpc.WithTracerProvider(rtrace.Provider), - otelgrpc.WithPropagators(rtrace.Propagator)), - ) - unaryInterceptors = append([]grpc.UnaryServerInterceptor{ + tracing.UnaryServerInterceptor(), appctx.NewUnary(s.log), token.NewUnary(), useragent.NewUnary(), log.NewUnary(), recovery.NewUnary(), }, unaryInterceptors...) + unaryChain := grpc_middleware.ChainUnaryServer(unaryInterceptors...) streamTriples := []*streamInterceptorTriple{} @@ -330,6 +327,7 @@ func (s *Server) getInterceptors(unprotected []string) ([]grpc.ServerOption, err } streamInterceptors = append([]grpc.StreamServerInterceptor{ + tracing.StreamServerInterceptor(), authStream, appctx.NewStream(s.log), token.NewStream(), @@ -337,6 +335,7 @@ func (s *Server) getInterceptors(unprotected []string) ([]grpc.ServerOption, err log.NewStream(), recovery.NewStream(), }, streamInterceptors...) + streamChain := grpc_middleware.ChainStreamServer(streamInterceptors...) opts := []grpc.ServerOption{ diff --git a/pkg/rgrpc/status/status.go b/pkg/rgrpc/status/status.go index 47da94647f..e115240b36 100644 --- a/pkg/rgrpc/status/status.go +++ b/pkg/rgrpc/status/status.go @@ -28,7 +28,6 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" - "go.opentelemetry.io/otel/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -36,8 +35,7 @@ import ( // NewOK returns a Status with CODE_OK. func NewOK(ctx context.Context) *rpc.Status { return &rpc.Status{ - Code: rpc.Code_CODE_OK, - Trace: getTrace(ctx), + Code: rpc.Code_CODE_OK, } } @@ -48,7 +46,6 @@ func NewNotFound(ctx context.Context, msg string) *rpc.Status { return &rpc.Status{ Code: rpc.Code_CODE_NOT_FOUND, Message: msg, - Trace: getTrace(ctx), } } @@ -59,7 +56,6 @@ func NewInvalid(ctx context.Context, msg string) *rpc.Status { return &rpc.Status{ Code: rpc.Code_CODE_INVALID_ARGUMENT, Message: msg, - Trace: getTrace(ctx), } } @@ -76,7 +72,6 @@ func NewInternal(ctx context.Context, err error, msg string) *rpc.Status { return &rpc.Status{ Code: rpc.Code_CODE_INTERNAL, Message: msg, - Trace: getTrace(ctx), } } @@ -87,7 +82,6 @@ func NewUnauthenticated(ctx context.Context, err error, msg string) *rpc.Status return &rpc.Status{ Code: rpc.Code_CODE_UNAUTHENTICATED, Message: msg, - Trace: getTrace(ctx), } } @@ -99,7 +93,6 @@ func NewPermissionDenied(ctx context.Context, err error, msg string) *rpc.Status return &rpc.Status{ Code: rpc.Code_CODE_PERMISSION_DENIED, Message: msg, - Trace: getTrace(ctx), } } @@ -111,7 +104,6 @@ func NewInsufficientStorage(ctx context.Context, err error, msg string) *rpc.Sta return &rpc.Status{ Code: rpc.Code_CODE_INSUFFICIENT_STORAGE, Message: msg, - Trace: getTrace(ctx), } } @@ -122,7 +114,6 @@ func NewUnimplemented(ctx context.Context, err error, msg string) *rpc.Status { return &rpc.Status{ Code: rpc.Code_CODE_UNIMPLEMENTED, Message: msg, - Trace: getTrace(ctx), } } @@ -133,7 +124,6 @@ func NewAlreadyExists(ctx context.Context, err error, msg string) *rpc.Status { return &rpc.Status{ Code: rpc.Code_CODE_ALREADY_EXISTS, Message: msg, - Trace: getTrace(ctx), } } @@ -141,7 +131,6 @@ func NewAlreadyExists(ctx context.Context, err error, msg string) *rpc.Status { func NewInvalidArg(ctx context.Context, msg string) *rpc.Status { return &rpc.Status{Code: rpc.Code_CODE_INVALID_ARGUMENT, Message: msg, - Trace: getTrace(ctx), } } @@ -150,7 +139,6 @@ func NewConflict(ctx context.Context, err error, msg string) *rpc.Status { return &rpc.Status{ Code: rpc.Code_CODE_ABORTED, Message: msg, - Trace: getTrace(ctx), } } @@ -161,7 +149,6 @@ func NewFailedPrecondition(ctx context.Context, err error, msg string) *rpc.Stat return &rpc.Status{ Code: rpc.Code_CODE_FAILED_PRECONDITION, Message: msg, - Trace: getTrace(ctx), } } @@ -211,9 +198,3 @@ func NewStatusFromErrType(ctx context.Context, msg string, err error) *rpc.Statu func NewErrorFromCode(code rpc.Code, pkgname string) error { return errors.New(pkgname + ": grpc failed with code " + code.String()) } - -// internal function to attach the trace to a context -func getTrace(ctx context.Context) string { - span := trace.SpanFromContext(ctx) - return span.SpanContext().TraceID().String() -} diff --git a/pkg/rgrpc/todo/pool/pool.go b/pkg/rgrpc/todo/pool/pool.go index 3f062e5130..a35b8071bd 100644 --- a/pkg/rgrpc/todo/pool/pool.go +++ b/pkg/rgrpc/todo/pool/pool.go @@ -19,6 +19,7 @@ package pool import ( + "context" "sync" appprovider "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1" @@ -40,12 +41,13 @@ import ( storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" storageregistry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" datatx "github.com/cs3org/go-cs3apis/cs3/tx/v1beta1" - rtrace "github.com/cs3org/reva/pkg/trace" - "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "github.com/cs3org/reva/pkg/tracing" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) +const tracerName = "pool" + type provider struct { m sync.Mutex conn map[string]interface{} @@ -83,43 +85,24 @@ var ( ) // NewConn creates a new connection to a grpc server -// with open census tracing support. // TODO(labkode): make grpc tls configurable. -func NewConn(options Options) (*grpc.ClientConn, error) { - conn, err := grpc.Dial( - options.Endpoint, +func NewConn(ctx context.Context, options Options) (*grpc.ClientConn, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "NewConn") + defer span.End() + + return grpc.Dial(options.Endpoint, grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithDefaultCallOptions( - grpc.MaxCallRecvMsgSize(options.MaxCallRecvMsgSize), - ), - grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor( - otelgrpc.WithTracerProvider( - rtrace.Provider, - ), - otelgrpc.WithPropagators( - rtrace.Propagator, - ), - )), - grpc.WithUnaryInterceptor( - otelgrpc.UnaryClientInterceptor( - otelgrpc.WithTracerProvider( - rtrace.Provider, - ), - otelgrpc.WithPropagators( - rtrace.Propagator, - ), - ), - ), + grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(options.MaxCallRecvMsgSize)), + grpc.WithUnaryInterceptor(tracing.UnaryClientInterceptor()), + grpc.WithStreamInterceptor(tracing.StreamClientInterceptor()), ) - if err != nil { - return nil, err - } - - return conn, nil } // GetGatewayServiceClient returns a GatewayServiceClient. -func GetGatewayServiceClient(opts ...Option) (gateway.GatewayAPIClient, error) { +func GetGatewayServiceClient(ctx context.Context, opts ...Option) (gateway.GatewayAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetGatewayServiceClient") + defer span.End() + gatewayProviders.m.Lock() defer gatewayProviders.m.Unlock() @@ -128,19 +111,21 @@ func GetGatewayServiceClient(opts ...Option) (gateway.GatewayAPIClient, error) { return val.(gateway.GatewayAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } v := gateway.NewGatewayAPIClient(conn) gatewayProviders.conn[options.Endpoint] = v - return v, nil } // GetUserProviderServiceClient returns a UserProviderServiceClient. -func GetUserProviderServiceClient(opts ...Option) (user.UserAPIClient, error) { +func GetUserProviderServiceClient(ctx context.Context, opts ...Option) (user.UserAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetUserProviderServiceClient") + defer span.End() + userProviders.m.Lock() defer userProviders.m.Unlock() @@ -149,7 +134,7 @@ func GetUserProviderServiceClient(opts ...Option) (user.UserAPIClient, error) { return val.(user.UserAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -160,7 +145,10 @@ func GetUserProviderServiceClient(opts ...Option) (user.UserAPIClient, error) { } // GetGroupProviderServiceClient returns a GroupProviderServiceClient. -func GetGroupProviderServiceClient(opts ...Option) (group.GroupAPIClient, error) { +func GetGroupProviderServiceClient(ctx context.Context, opts ...Option) (group.GroupAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetGroupProviderServiceClient") + defer span.End() + groupProviders.m.Lock() defer groupProviders.m.Unlock() @@ -169,7 +157,7 @@ func GetGroupProviderServiceClient(opts ...Option) (group.GroupAPIClient, error) return val.(group.GroupAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -180,7 +168,10 @@ func GetGroupProviderServiceClient(opts ...Option) (group.GroupAPIClient, error) } // GetStorageProviderServiceClient returns a StorageProviderServiceClient. -func GetStorageProviderServiceClient(opts ...Option) (storageprovider.ProviderAPIClient, error) { +func GetStorageProviderServiceClient(ctx context.Context, opts ...Option) (storageprovider.ProviderAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetStorageProviderServiceClient") + defer span.End() + storageProviders.m.Lock() defer storageProviders.m.Unlock() @@ -189,7 +180,7 @@ func GetStorageProviderServiceClient(opts ...Option) (storageprovider.ProviderAP return c.(storageprovider.ProviderAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -200,7 +191,10 @@ func GetStorageProviderServiceClient(opts ...Option) (storageprovider.ProviderAP } // GetAuthRegistryServiceClient returns a new AuthRegistryServiceClient. -func GetAuthRegistryServiceClient(opts ...Option) (authregistry.RegistryAPIClient, error) { +func GetAuthRegistryServiceClient(ctx context.Context, opts ...Option) (authregistry.RegistryAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAuthRegistryServiceClient") + defer span.End() + authRegistries.m.Lock() defer authRegistries.m.Unlock() @@ -211,7 +205,7 @@ func GetAuthRegistryServiceClient(opts ...Option) (authregistry.RegistryAPIClien } // if not, create a new connection - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -223,7 +217,10 @@ func GetAuthRegistryServiceClient(opts ...Option) (authregistry.RegistryAPIClien } // GetAuthProviderServiceClient returns a new AuthProviderServiceClient. -func GetAuthProviderServiceClient(opts ...Option) (authprovider.ProviderAPIClient, error) { +func GetAuthProviderServiceClient(ctx context.Context, opts ...Option) (authprovider.ProviderAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAuthProviderServiceClient") + defer span.End() + authProviders.m.Lock() defer authProviders.m.Unlock() @@ -232,7 +229,7 @@ func GetAuthProviderServiceClient(opts ...Option) (authprovider.ProviderAPIClien return c.(authprovider.ProviderAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -243,7 +240,10 @@ func GetAuthProviderServiceClient(opts ...Option) (authprovider.ProviderAPIClien } // GetAppAuthProviderServiceClient returns a new AppAuthProviderServiceClient. -func GetAppAuthProviderServiceClient(opts ...Option) (applicationauth.ApplicationsAPIClient, error) { +func GetAppAuthProviderServiceClient(ctx context.Context, opts ...Option) (applicationauth.ApplicationsAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAppAuthProviderServiceClient") + defer span.End() + appAuthProviders.m.Lock() defer appAuthProviders.m.Unlock() @@ -252,7 +252,7 @@ func GetAppAuthProviderServiceClient(opts ...Option) (applicationauth.Applicatio return c.(applicationauth.ApplicationsAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -263,7 +263,10 @@ func GetAppAuthProviderServiceClient(opts ...Option) (applicationauth.Applicatio } // GetUserShareProviderClient returns a new UserShareProviderClient. -func GetUserShareProviderClient(opts ...Option) (collaboration.CollaborationAPIClient, error) { +func GetUserShareProviderClient(ctx context.Context, opts ...Option) (collaboration.CollaborationAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetUserShareProviderClient") + defer span.End() + userShareProviders.m.Lock() defer userShareProviders.m.Unlock() @@ -272,7 +275,7 @@ func GetUserShareProviderClient(opts ...Option) (collaboration.CollaborationAPIC return c.(collaboration.CollaborationAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -283,7 +286,10 @@ func GetUserShareProviderClient(opts ...Option) (collaboration.CollaborationAPIC } // GetOCMShareProviderClient returns a new OCMShareProviderClient. -func GetOCMShareProviderClient(opts ...Option) (ocm.OcmAPIClient, error) { +func GetOCMShareProviderClient(ctx context.Context, opts ...Option) (ocm.OcmAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetOCMShareProviderClient") + defer span.End() + ocmShareProviders.m.Lock() defer ocmShareProviders.m.Unlock() @@ -292,18 +298,21 @@ func GetOCMShareProviderClient(opts ...Option) (ocm.OcmAPIClient, error) { return c.(ocm.OcmAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } v := ocm.NewOcmAPIClient(conn) - ocmShareProviders.conn[options.Endpoint] = v + //ocmShareProviders.conn[options.Endpoint] = v return v, nil } // GetOCMInviteManagerClient returns a new OCMInviteManagerClient. -func GetOCMInviteManagerClient(opts ...Option) (invitepb.InviteAPIClient, error) { +func GetOCMInviteManagerClient(ctx context.Context, opts ...Option) (invitepb.InviteAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetOCMInviteManagerClient") + defer span.End() + ocmInviteManagers.m.Lock() defer ocmInviteManagers.m.Unlock() @@ -312,7 +321,7 @@ func GetOCMInviteManagerClient(opts ...Option) (invitepb.InviteAPIClient, error) return c.(invitepb.InviteAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -323,7 +332,10 @@ func GetOCMInviteManagerClient(opts ...Option) (invitepb.InviteAPIClient, error) } // GetPublicShareProviderClient returns a new PublicShareProviderClient. -func GetPublicShareProviderClient(opts ...Option) (link.LinkAPIClient, error) { +func GetPublicShareProviderClient(ctx context.Context, opts ...Option) (link.LinkAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPublicShareProviderClient") + defer span.End() + publicShareProviders.m.Lock() defer publicShareProviders.m.Unlock() @@ -332,7 +344,7 @@ func GetPublicShareProviderClient(opts ...Option) (link.LinkAPIClient, error) { return c.(link.LinkAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -343,7 +355,10 @@ func GetPublicShareProviderClient(opts ...Option) (link.LinkAPIClient, error) { } // GetPreferencesClient returns a new PreferencesClient. -func GetPreferencesClient(opts ...Option) (preferences.PreferencesAPIClient, error) { +func GetPreferencesClient(ctx context.Context, opts ...Option) (preferences.PreferencesAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPreferencesClient") + defer span.End() + preferencesProviders.m.Lock() defer preferencesProviders.m.Unlock() @@ -352,7 +367,7 @@ func GetPreferencesClient(opts ...Option) (preferences.PreferencesAPIClient, err return c.(preferences.PreferencesAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -363,7 +378,10 @@ func GetPreferencesClient(opts ...Option) (preferences.PreferencesAPIClient, err } // GetPermissionsClient returns a new PermissionsClient. -func GetPermissionsClient(opts ...Option) (permissions.PermissionsAPIClient, error) { +func GetPermissionsClient(ctx context.Context, opts ...Option) (permissions.PermissionsAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPermissionsClient") + defer span.End() + permissionsProviders.m.Lock() defer permissionsProviders.m.Unlock() @@ -372,7 +390,7 @@ func GetPermissionsClient(opts ...Option) (permissions.PermissionsAPIClient, err return c.(permissions.PermissionsAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -383,7 +401,10 @@ func GetPermissionsClient(opts ...Option) (permissions.PermissionsAPIClient, err } // GetAppRegistryClient returns a new AppRegistryClient. -func GetAppRegistryClient(opts ...Option) (appregistry.RegistryAPIClient, error) { +func GetAppRegistryClient(ctx context.Context, opts ...Option) (appregistry.RegistryAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAppRegistryClient") + defer span.End() + appRegistries.m.Lock() defer appRegistries.m.Unlock() @@ -392,7 +413,7 @@ func GetAppRegistryClient(opts ...Option) (appregistry.RegistryAPIClient, error) return c.(appregistry.RegistryAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -403,7 +424,10 @@ func GetAppRegistryClient(opts ...Option) (appregistry.RegistryAPIClient, error) } // GetAppProviderClient returns a new AppRegistryClient. -func GetAppProviderClient(opts ...Option) (appprovider.ProviderAPIClient, error) { +func GetAppProviderClient(ctx context.Context, opts ...Option) (appprovider.ProviderAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetAppProviderClient") + defer span.End() + appProviders.m.Lock() defer appProviders.m.Unlock() @@ -412,7 +436,7 @@ func GetAppProviderClient(opts ...Option) (appprovider.ProviderAPIClient, error) return c.(appprovider.ProviderAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -423,7 +447,10 @@ func GetAppProviderClient(opts ...Option) (appprovider.ProviderAPIClient, error) } // GetStorageRegistryClient returns a new StorageRegistryClient. -func GetStorageRegistryClient(opts ...Option) (storageregistry.RegistryAPIClient, error) { +func GetStorageRegistryClient(ctx context.Context, opts ...Option) (storageregistry.RegistryAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetStorageRegistryClient") + defer span.End() + storageRegistries.m.Lock() defer storageRegistries.m.Unlock() @@ -432,7 +459,7 @@ func GetStorageRegistryClient(opts ...Option) (storageregistry.RegistryAPIClient return c.(storageregistry.RegistryAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -443,7 +470,10 @@ func GetStorageRegistryClient(opts ...Option) (storageregistry.RegistryAPIClient } // GetOCMProviderAuthorizerClient returns a new OCMProviderAuthorizerClient. -func GetOCMProviderAuthorizerClient(opts ...Option) (ocmprovider.ProviderAPIClient, error) { +func GetOCMProviderAuthorizerClient(ctx context.Context, opts ...Option) (ocmprovider.ProviderAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetOCMProviderAuthorizerClient") + defer span.End() + ocmProviderAuthorizers.m.Lock() defer ocmProviderAuthorizers.m.Unlock() @@ -452,7 +482,7 @@ func GetOCMProviderAuthorizerClient(opts ...Option) (ocmprovider.ProviderAPIClie return c.(ocmprovider.ProviderAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -463,7 +493,10 @@ func GetOCMProviderAuthorizerClient(opts ...Option) (ocmprovider.ProviderAPIClie } // GetOCMCoreClient returns a new OCMCoreClient. -func GetOCMCoreClient(opts ...Option) (ocmcore.OcmCoreAPIClient, error) { +func GetOCMCoreClient(ctx context.Context, opts ...Option) (ocmcore.OcmCoreAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetOCMCoreClient") + defer span.End() + ocmCores.m.Lock() defer ocmCores.m.Unlock() @@ -472,7 +505,7 @@ func GetOCMCoreClient(opts ...Option) (ocmcore.OcmCoreAPIClient, error) { return c.(ocmcore.OcmCoreAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } @@ -483,7 +516,10 @@ func GetOCMCoreClient(opts ...Option) (ocmcore.OcmCoreAPIClient, error) { } // GetDataTxClient returns a new DataTxClient. -func GetDataTxClient(opts ...Option) (datatx.TxAPIClient, error) { +func GetDataTxClient(ctx context.Context, opts ...Option) (datatx.TxAPIClient, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetDataTxClient") + defer span.End() + dataTxs.m.Lock() defer dataTxs.m.Unlock() @@ -492,7 +528,7 @@ func GetDataTxClient(opts ...Option) (datatx.TxAPIClient, error) { return c.(datatx.TxAPIClient), nil } - conn, err := NewConn(options) + conn, err := NewConn(ctx, options) if err != nil { return nil, err } diff --git a/pkg/rhttp/client.go b/pkg/rhttp/client.go index c74c00cb79..b4aab8c6c3 100644 --- a/pkg/rhttp/client.go +++ b/pkg/rhttp/client.go @@ -30,7 +30,6 @@ import ( "github.com/pkg/errors" ) -// GetHTTPClient returns an http client with open census tracing support. // TODO(labkode): harden it. // https://medium.com/@nate510/don-t-use-go-s-default-http-client-4804cb19f779 func GetHTTPClient(opts ...Option) *http.Client { diff --git a/pkg/rhttp/global/global.go b/pkg/rhttp/global/global.go index a3706abdf0..3be195ae6d 100644 --- a/pkg/rhttp/global/global.go +++ b/pkg/rhttp/global/global.go @@ -21,6 +21,7 @@ package global import ( "net/http" + "github.com/cs3org/reva/pkg/tracing" "github.com/rs/zerolog" ) @@ -58,4 +59,5 @@ type Service interface { // middleware. To be seen if we need url-verb fine grained skip checks like // GET is public and POST is not. Unprotected() []string + tracing.HttpMiddlewarer } diff --git a/pkg/rhttp/rhttp.go b/pkg/rhttp/rhttp.go index ba852572f1..1af177f0cb 100644 --- a/pkg/rhttp/rhttp.go +++ b/pkg/rhttp/rhttp.go @@ -25,7 +25,6 @@ import ( "net/http" "path" "sort" - "strings" "time" "github.com/cs3org/reva/internal/http/interceptors/appctx" @@ -33,11 +32,11 @@ import ( "github.com/cs3org/reva/internal/http/interceptors/log" "github.com/cs3org/reva/internal/http/interceptors/providerauthorizer" "github.com/cs3org/reva/pkg/rhttp/global" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/rhttp/utils" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/rs/zerolog" - "go.opentelemetry.io/otel/propagation" ) // New returns a new server @@ -205,10 +204,8 @@ func (s *Server) registerServices() error { err = errors.Wrapf(err, "http service %s could not be started,", svcName) return err } - - // instrument services with opencensus tracing. - h := traceHandler(svcName, svc.Handler()) - s.handlers[svc.Prefix()] = h + svc.SetMiddleware(svcName, svc.Prefix()) + s.handlers[svc.Prefix()] = svc.Handler() s.svcs[svc.Prefix()] = svc s.unprotected = append(s.unprotected, getUnprotected(svc.Prefix(), svc.Unprotected())...) s.log.Info().Msgf("http service enabled: %s@/%s", svcName, svc.Prefix()) @@ -234,45 +231,11 @@ func getUnprotected(prefix string, unprotected []string) []string { return unprotected } -// clean the url putting a slash (/) at the beginning if it does not have it -// and removing the slashes at the end -// if the url is "/", the output is "" -func cleanURL(url string) string { - if len(url) > 0 { - if url[0] != '/' { - url = "/" + url - } - url = strings.TrimRight(url, "/") - } - return url -} - -func urlHasPrefix(url, prefix string) bool { - url = cleanURL(url) - prefix = cleanURL(prefix) - - partsURL := strings.Split(url, "/") - partsPrefix := strings.Split(prefix, "/") - - if len(partsPrefix) > len(partsURL) { - return false - } - - for i, p := range partsPrefix { - u := partsURL[i] - if p != u { - return false - } - } - - return true -} - func (s *Server) getHandlerLongestCommongURL(url string) (http.Handler, string, bool) { var match string for k := range s.handlers { - if urlHasPrefix(url, k) && len(k) > len(match) { + if utils.UrlHasPrefix(url, k) && len(k) > len(match) { match = k } } @@ -281,15 +244,6 @@ func (s *Server) getHandlerLongestCommongURL(url string) (http.Handler, string, return h, match, ok } -func getSubURL(url, prefix string) string { - // pre cond: prefix is a prefix for url - // example: url = "/api/v0/", prefix = "/api", res = "/v0" - url = cleanURL(url) - prefix = cleanURL(prefix) - - return url[len(prefix):] -} - func (s *Server) getHandler() (http.Handler, error) { h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if h, ok := s.handlers[r.URL.Path]; ok { @@ -302,7 +256,7 @@ func (s *Server) getHandler() (http.Handler, error) { // find by longest common path if h, url, ok := s.getHandlerLongestCommongURL(r.URL.Path); ok { s.log.Debug().Msgf("http routing: url=%s", url) - r.URL.Path = getSubURL(r.URL.Path, url) + r.URL.Path = utils.GetSubURL(r.URL.Path, url) h.ServeHTTP(w, r) return } @@ -320,7 +274,7 @@ func (s *Server) getHandler() (http.Handler, error) { for _, triple := range s.middlewares { s.log.Info().Msgf("chaining http middleware %s with priority %d", triple.Name, triple.Priority) - handler = triple.Middleware(traceHandler(triple.Name, handler)) + handler = triple.Middleware(handler) } for _, v := range s.unprotected { @@ -348,22 +302,19 @@ func (s *Server) getHandler() (http.Handler, error) { coreMiddlewares = append(coreMiddlewares, &middlewareTriple{Middleware: appctx.New(s.log), Name: "appctx"}) for _, triple := range coreMiddlewares { - handler = triple.Middleware(traceHandler(triple.Name, handler)) + handler = triple.Middleware(handler) } - return handler, nil -} + ms := map[string]tracing.HttpMiddlewarer{} + for prefix, svc := range s.svcs { + if m, ok := svc.(tracing.HttpMiddlewarer); ok { + ms[prefix] = m + } + } -func traceHandler(name string, h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := rtrace.Propagator.Extract(r.Context(), propagation.HeaderCarrier(r.Header)) - t := rtrace.Provider.Tracer("reva") - ctx, span := t.Start(ctx, name) - defer span.End() + handler = tracing.Middleware(handler, ms) - rtrace.Propagator.Inject(ctx, propagation.HeaderCarrier(r.Header)) - h.ServeHTTP(w, r.WithContext(ctx)) - }) + return handler, nil } func addProviderAuthMiddleware(conf *config, unprotected []string) (global.Middleware, error) { diff --git a/pkg/rhttp/rhttp_test.go b/pkg/rhttp/rhttp_test.go index eb68a0c22d..63e267b973 100644 --- a/pkg/rhttp/rhttp_test.go +++ b/pkg/rhttp/rhttp_test.go @@ -18,7 +18,11 @@ package rhttp -import "testing" +import ( + "testing" + + "github.com/cs3org/reva/pkg/rhttp/utils" +) func TestURLHasPrefix(t *testing.T) { tests := map[string]struct { @@ -65,7 +69,7 @@ func TestURLHasPrefix(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { - res := urlHasPrefix(test.url, test.prefix) + res := utils.UrlHasPrefix(test.url, test.prefix) if res != test.expected { t.Fatalf("%s got an unexpected result: %+v instead of %+v", t.Name(), res, test.expected) } diff --git a/pkg/rhttp/utils/utils.go b/pkg/rhttp/utils/utils.go new file mode 100644 index 0000000000..54cb2e5a4c --- /dev/null +++ b/pkg/rhttp/utils/utils.go @@ -0,0 +1,64 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package utils + +import "strings" + +// clean the url putting a slash (/) at the beginning if it does not have it +// and removing the slashes at the end +// if the url is "/", the output is "" +func cleanURL(url string) string { + if len(url) > 0 { + if url[0] != '/' { + url = "/" + url + } + url = strings.TrimRight(url, "/") + } + return url +} + +func UrlHasPrefix(url, prefix string) bool { + url = cleanURL(url) + prefix = cleanURL(prefix) + + partsURL := strings.Split(url, "/") + partsPrefix := strings.Split(prefix, "/") + + if len(partsPrefix) > len(partsURL) { + return false + } + + for i, p := range partsPrefix { + u := partsURL[i] + if p != u { + return false + } + } + + return true +} + +func GetSubURL(url, prefix string) string { + // pre cond: prefix is a prefix for url + // example: url = "/api/v0/", prefix = "/api", res = "/v0" + url = cleanURL(url) + prefix = cleanURL(prefix) + + return url[len(prefix):] +} diff --git a/pkg/share/cache/warmup/cbox/cbox.go b/pkg/share/cache/warmup/cbox/cbox.go index 4a46f83574..fd7e4a7224 100644 --- a/pkg/share/cache/warmup/cbox/cbox.go +++ b/pkg/share/cache/warmup/cbox/cbox.go @@ -119,7 +119,7 @@ func (m *manager) GetResourceInfos() ([]*provider.ResourceInfo, error) { } ctx := metadata.AppendToOutgoingContext(context.Background(), ctxpkg.TokenHeader, tkn) - client, err := pool.GetGatewayServiceClient(pool.Endpoint(m.conf.GatewaySvc)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(m.conf.GatewaySvc)) if err != nil { return nil, err } diff --git a/pkg/share/manager/json/json.go b/pkg/share/manager/json/json.go index 55fcf2c691..f6b3903f32 100644 --- a/pkg/share/manager/json/json.go +++ b/pkg/share/manager/json/json.go @@ -32,6 +32,7 @@ import ( ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/share" + "github.com/cs3org/reva/pkg/tracing" "github.com/google/uuid" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" @@ -41,6 +42,8 @@ import ( "github.com/cs3org/reva/pkg/utils" ) +const tracerName = "json" + func init() { registry.Register("json", New) } @@ -177,6 +180,9 @@ func genID() string { } func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collaboration.ShareGrant) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Share") + defer span.End() + id := genID() user := ctxpkg.ContextMustGetUser(ctx) now := time.Now().UnixNano() @@ -231,6 +237,9 @@ func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collabora } func (m *mgr) getByID(ctx context.Context, id *collaboration.ShareId) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getByID") + defer span.End() + m.Lock() defer m.Unlock() for _, s := range m.model.Shares { @@ -242,6 +251,9 @@ func (m *mgr) getByID(ctx context.Context, id *collaboration.ShareId) (*collabor } func (m *mgr) getByKey(ctx context.Context, key *collaboration.ShareKey) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getByKey") + defer span.End() + m.Lock() defer m.Unlock() for _, s := range m.model.Shares { @@ -254,6 +266,9 @@ func (m *mgr) getByKey(ctx context.Context, key *collaboration.ShareKey) (*colla } func (m *mgr) get(ctx context.Context, ref *collaboration.ShareReference) (s *collaboration.Share, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "get") + defer span.End() + switch { case ref.GetId() != nil: s, err = m.getByID(ctx, ref.GetId()) @@ -283,6 +298,9 @@ func (m *mgr) get(ctx context.Context, ref *collaboration.ShareReference) (s *co } func (m *mgr) GetShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetShare") + defer span.End() + share, err := m.get(ctx, ref) if err != nil { return nil, err @@ -292,6 +310,9 @@ func (m *mgr) GetShare(ctx context.Context, ref *collaboration.ShareReference) ( } func (m *mgr) Unshare(ctx context.Context, ref *collaboration.ShareReference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Unshare") + defer span.End() + m.Lock() defer m.Unlock() user := ctxpkg.ContextMustGetUser(ctx) @@ -326,6 +347,9 @@ func sharesEqual(ref *collaboration.ShareReference, s *collaboration.Share) bool } func (m *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReference, p *collaboration.SharePermissions) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateShare") + defer span.End() + m.Lock() defer m.Unlock() user := ctxpkg.ContextMustGetUser(ctx) @@ -350,6 +374,9 @@ func (m *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReference } func (m *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListShares") + defer span.End() + var ss []*collaboration.Share m.Lock() defer m.Unlock() @@ -372,6 +399,9 @@ func (m *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) ( // we list the shares that are targeted to the user in context or to the user groups. func (m *mgr) ListReceivedShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListReceivedShares") + defer span.End() + var rss []*collaboration.ReceivedShare m.Lock() defer m.Unlock() @@ -398,6 +428,9 @@ func (m *mgr) ListReceivedShares(ctx context.Context, filters []*collaboration.F // convert must be called in a lock-controlled block. func (m *mgr) convert(ctx context.Context, s *collaboration.Share) *collaboration.ReceivedShare { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convert") + defer span.End() + rs := &collaboration.ReceivedShare{ Share: s, State: collaboration.ShareState_SHARE_STATE_PENDING, @@ -412,10 +445,16 @@ func (m *mgr) convert(ctx context.Context, s *collaboration.Share) *collaboratio } func (m *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetReceivedShare") + defer span.End() + return m.getReceived(ctx, ref) } func (m *mgr) getReceived(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getReceived") + defer span.End() + m.Lock() defer m.Unlock() user := ctxpkg.ContextMustGetUser(ctx) @@ -431,6 +470,9 @@ func (m *mgr) getReceived(ctx context.Context, ref *collaboration.ShareReference } func (m *mgr) UpdateReceivedShare(ctx context.Context, receivedShare *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateReceivedShare") + defer span.End() + rs, err := m.getReceived(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{Id: receivedShare.Share.Id}}) if err != nil { return nil, err diff --git a/pkg/share/manager/memory/memory.go b/pkg/share/manager/memory/memory.go index e292b73d72..daf9e80026 100644 --- a/pkg/share/manager/memory/memory.go +++ b/pkg/share/manager/memory/memory.go @@ -28,6 +28,7 @@ import ( ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/share" + "github.com/cs3org/reva/pkg/tracing" "google.golang.org/genproto/protobuf/field_mask" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" @@ -38,6 +39,8 @@ import ( "github.com/cs3org/reva/pkg/utils" ) +const tracerName = "memory" + var counter uint64 func init() { @@ -62,12 +65,18 @@ type manager struct { } func (m *manager) add(ctx context.Context, s *collaboration.Share) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "add") + defer span.End() + m.lock.Lock() defer m.lock.Unlock() m.shares = append(m.shares, s) } func (m *manager) Share(ctx context.Context, md *provider.ResourceInfo, g *collaboration.ShareGrant) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Share") + defer span.End() + id := atomic.AddUint64(&counter, 1) user := ctxpkg.ContextMustGetUser(ctx) now := time.Now().UnixNano() @@ -111,6 +120,9 @@ func (m *manager) Share(ctx context.Context, md *provider.ResourceInfo, g *colla } func (m *manager) getByID(ctx context.Context, id *collaboration.ShareId) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getByID") + defer span.End() + m.lock.Lock() defer m.lock.Unlock() for _, s := range m.shares { @@ -122,6 +134,9 @@ func (m *manager) getByID(ctx context.Context, id *collaboration.ShareId) (*coll } func (m *manager) getByKey(ctx context.Context, key *collaboration.ShareKey) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getByKey") + defer span.End() + m.lock.Lock() defer m.lock.Unlock() for _, s := range m.shares { @@ -134,6 +149,9 @@ func (m *manager) getByKey(ctx context.Context, key *collaboration.ShareKey) (*c } func (m *manager) get(ctx context.Context, ref *collaboration.ShareReference) (s *collaboration.Share, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "get") + defer span.End() + switch { case ref.GetId() != nil: s, err = m.getByID(ctx, ref.GetId()) @@ -158,6 +176,9 @@ func (m *manager) get(ctx context.Context, ref *collaboration.ShareReference) (s } func (m *manager) GetShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetShare") + defer span.End() + share, err := m.get(ctx, ref) if err != nil { return nil, err @@ -167,6 +188,9 @@ func (m *manager) GetShare(ctx context.Context, ref *collaboration.ShareReferenc } func (m *manager) Unshare(ctx context.Context, ref *collaboration.ShareReference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Unshare") + defer span.End() + m.lock.Lock() defer m.lock.Unlock() user := ctxpkg.ContextMustGetUser(ctx) @@ -197,6 +221,9 @@ func sharesEqual(ref *collaboration.ShareReference, s *collaboration.Share) bool } func (m *manager) UpdateShare(ctx context.Context, ref *collaboration.ShareReference, p *collaboration.SharePermissions) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateShare") + defer span.End() + m.lock.Lock() defer m.lock.Unlock() user := ctxpkg.ContextMustGetUser(ctx) @@ -217,6 +244,9 @@ func (m *manager) UpdateShare(ctx context.Context, ref *collaboration.ShareRefer } func (m *manager) ListShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListShares") + defer span.End() + var ss []*collaboration.Share m.lock.Lock() defer m.lock.Unlock() @@ -239,6 +269,9 @@ func (m *manager) ListShares(ctx context.Context, filters []*collaboration.Filte // we list the shares that are targeted to the user in context or to the user groups. func (m *manager) ListReceivedShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListReceivedShares") + defer span.End() + var rss []*collaboration.ReceivedShare m.lock.Lock() defer m.lock.Unlock() @@ -265,6 +298,9 @@ func (m *manager) ListReceivedShares(ctx context.Context, filters []*collaborati // convert must be called in a lock-controlled block. func (m *manager) convert(ctx context.Context, s *collaboration.Share) *collaboration.ReceivedShare { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convert") + defer span.End() + rs := &collaboration.ReceivedShare{ Share: s, State: collaboration.ShareState_SHARE_STATE_PENDING, @@ -279,10 +315,16 @@ func (m *manager) convert(ctx context.Context, s *collaboration.Share) *collabor } func (m *manager) GetReceivedShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetReceivedShare") + defer span.End() + return m.getReceived(ctx, ref) } func (m *manager) getReceived(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getReceived") + defer span.End() + m.lock.Lock() defer m.lock.Unlock() user := ctxpkg.ContextMustGetUser(ctx) @@ -298,6 +340,9 @@ func (m *manager) getReceived(ctx context.Context, ref *collaboration.ShareRefer } func (m *manager) UpdateReceivedShare(ctx context.Context, receivedShare *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateReceivedShare") + defer span.End() + rs, err := m.getReceived(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{Id: receivedShare.Share.Id}}) if err != nil { return nil, err diff --git a/pkg/share/manager/sql/conversions.go b/pkg/share/manager/sql/conversions.go index 3745b93fd4..5c6d139ef3 100644 --- a/pkg/share/manager/sql/conversions.go +++ b/pkg/share/manager/sql/conversions.go @@ -31,6 +31,7 @@ import ( conversions "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/tracing" ) //go:generate mockery -name UserConverter @@ -74,7 +75,10 @@ func NewGatewayUserConverter(gwAddr string) *GatewayUserConverter { // UserIDToUserName converts a user ID to an username func (c *GatewayUserConverter) UserIDToUserName(ctx context.Context, userid *userpb.UserId) (string, error) { - gwConn, err := pool.GetGatewayServiceClient(pool.Endpoint(c.gwAddr)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UserIDToUserName") + defer span.End() + + gwConn, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(c.gwAddr)) if err != nil { return "", err } @@ -93,7 +97,10 @@ func (c *GatewayUserConverter) UserIDToUserName(ctx context.Context, userid *use // UserNameToUserID converts a username to an user ID func (c *GatewayUserConverter) UserNameToUserID(ctx context.Context, username string) (*userpb.UserId, error) { - gwConn, err := pool.GetGatewayServiceClient(pool.Endpoint(c.gwAddr)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UserNameToUserID") + defer span.End() + + gwConn, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(c.gwAddr)) if err != nil { return nil, err } @@ -112,6 +119,9 @@ func (c *GatewayUserConverter) UserNameToUserID(ctx context.Context, username st } func (m *mgr) formatGrantee(ctx context.Context, g *provider.Grantee) (int, string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "formatGrantee") + defer span.End() + var granteeType int var formattedID string switch g.Type { @@ -132,6 +142,9 @@ func (m *mgr) formatGrantee(ctx context.Context, g *provider.Grantee) (int, stri } func (m *mgr) extractGrantee(ctx context.Context, t int, g string) (*provider.Grantee, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "extractGrantee") + defer span.End() + var grantee provider.Grantee switch t { case 0: @@ -204,6 +217,9 @@ func extractGroupID(u string) *grouppb.GroupId { } func (m *mgr) convertToCS3Share(ctx context.Context, s DBShare, storageMountID string) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convertToCS3Share") + defer span.End() + ts := &typespb.Timestamp{ Seconds: uint64(s.STime), } @@ -246,6 +262,9 @@ func (m *mgr) convertToCS3Share(ctx context.Context, s DBShare, storageMountID s } func (m *mgr) convertToCS3ReceivedShare(ctx context.Context, s DBShare, storageMountID string) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convertToCS3ReceivedShare") + defer span.End() + share, err := m.convertToCS3Share(ctx, s, storageMountID) if err != nil { return nil, err diff --git a/pkg/share/manager/sql/sql.go b/pkg/share/manager/sql/sql.go index 1164105637..cab897079f 100644 --- a/pkg/share/manager/sql/sql.go +++ b/pkg/share/manager/sql/sql.go @@ -34,6 +34,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/share" "github.com/cs3org/reva/pkg/share/manager/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" @@ -43,6 +44,8 @@ import ( _ "github.com/go-sql-driver/mysql" ) +const tracerName = "sql" + const ( shareTypeUser = 0 shareTypeGroup = 1 @@ -106,6 +109,9 @@ func parseConfig(m map[string]interface{}) (*config, error) { } func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collaboration.ShareGrant) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Share") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) // do not allow share to myself or the owner if share is for a user @@ -183,6 +189,9 @@ func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collabora } func (m *mgr) GetShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetShare") + defer span.End() + var s *collaboration.Share var err error switch { @@ -202,6 +211,9 @@ func (m *mgr) GetShare(ctx context.Context, ref *collaboration.ShareReference) ( } func (m *mgr) Unshare(ctx context.Context, ref *collaboration.ShareReference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Unshare") + defer span.End() + uid := ctxpkg.ContextMustGetUser(ctx).Username var query string params := []interface{}{} @@ -242,6 +254,9 @@ func (m *mgr) Unshare(ctx context.Context, ref *collaboration.ShareReference) er } func (m *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReference, p *collaboration.SharePermissions) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateShare") + defer span.End() + permissions := sharePermToInt(p.Permissions) uid := ctxpkg.ContextMustGetUser(ctx).Username @@ -276,6 +291,9 @@ func (m *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReference } func (m *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListShares") + defer span.End() + uid := ctxpkg.ContextMustGetUser(ctx).Username query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(item_source, '') as item_source, id, stime, permissions, share_type FROM oc_share WHERE (uid_owner=? or uid_initiator=?)" params := []interface{}{uid, uid} @@ -328,6 +346,9 @@ func (m *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) ( // we list the shares that are targeted to the user in context or to the user groups. func (m *mgr) ListReceivedShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListReceivedShares") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) uid := user.Username @@ -385,6 +406,9 @@ func (m *mgr) ListReceivedShares(ctx context.Context, filters []*collaboration.F } func (m *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetReceivedShare") + defer span.End() + var s *collaboration.ReceivedShare var err error switch { @@ -405,6 +429,9 @@ func (m *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareRefe } func (m *mgr) UpdateReceivedShare(ctx context.Context, share *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateReceivedShare") + defer span.End() + rs, err := m.GetReceivedShare(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{Id: share.Share.Id}}) if err != nil { return nil, err @@ -443,6 +470,9 @@ func (m *mgr) UpdateReceivedShare(ctx context.Context, share *collaboration.Rece } func (m *mgr) getByID(ctx context.Context, id *collaboration.ShareId) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getByID") + defer span.End() + uid := ctxpkg.ContextMustGetUser(ctx).Username s := DBShare{ID: id.OpaqueId} query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(item_source, '') as item_source, stime, permissions, share_type FROM oc_share WHERE id=? AND (uid_owner=? or uid_initiator=?)" @@ -456,6 +486,9 @@ func (m *mgr) getByID(ctx context.Context, id *collaboration.ShareId) (*collabor } func (m *mgr) getByKey(ctx context.Context, key *collaboration.ShareKey) (*collaboration.Share, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getByKey") + defer span.End() + owner, err := m.userConverter.UserIDToUserName(ctx, key.Owner) if err != nil { return nil, err @@ -478,6 +511,9 @@ func (m *mgr) getByKey(ctx context.Context, key *collaboration.ShareKey) (*colla } func (m *mgr) getReceivedByID(ctx context.Context, id *collaboration.ShareId) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getReceivedByID") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) uid := user.Username @@ -503,6 +539,9 @@ func (m *mgr) getReceivedByID(ctx context.Context, id *collaboration.ShareId) (* } func (m *mgr) getReceivedByKey(ctx context.Context, key *collaboration.ShareKey) (*collaboration.ReceivedShare, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getReceivedByKey") + defer span.End() + user := ctxpkg.ContextMustGetUser(ctx) uid := user.Username diff --git a/pkg/siteacc/siteacc.go b/pkg/siteacc/siteacc.go index 569e0a978f..634df2dd44 100644 --- a/pkg/siteacc/siteacc.go +++ b/pkg/siteacc/siteacc.go @@ -29,10 +29,13 @@ import ( "github.com/cs3org/reva/pkg/siteacc/manager" accpanel "github.com/cs3org/reva/pkg/siteacc/panels/account" "github.com/cs3org/reva/pkg/siteacc/panels/admin" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" "github.com/rs/zerolog" ) +const tracerName = "siteacc" + // SiteAccounts represents the main Site Accounts service object. type SiteAccounts struct { conf *config.Configuration @@ -125,6 +128,9 @@ func (siteacc *SiteAccounts) initialize(conf *config.Configuration, log *zerolog // RequestHandler returns the HTTP request handler of the service. func (siteacc *SiteAccounts) RequestHandler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r, span := tracing.SpanStartFromRequest(r, tracerName, "Siteacc Service HTTP Handler") + defer span.End() + defer r.Body.Close() // Get the active session for the request (or create a new one); a valid session object will always be returned diff --git a/pkg/storage/fs/cephfs/connections.go b/pkg/storage/fs/cephfs/connections.go index ef37870490..9450cd0a11 100644 --- a/pkg/storage/fs/cephfs/connections.go +++ b/pkg/storage/fs/cephfs/connections.go @@ -54,7 +54,7 @@ type connections struct { groupCache *ristretto.Cache } -//TODO: make configurable/add to options +// TODO: make configurable/add to options var usrLimit int64 = 1e4 func newCache() (c *connections, err error) { diff --git a/pkg/storage/fs/nextcloud/nextcloud_server_mock.go b/pkg/storage/fs/nextcloud/nextcloud_server_mock.go index db514cbb5c..675a1e92f0 100644 --- a/pkg/storage/fs/nextcloud/nextcloud_server_mock.go +++ b/pkg/storage/fs/nextcloud/nextcloud_server_mock.go @@ -165,9 +165,9 @@ var responses = map[string]Response{ `POST /apps/sciencemesh/~tester/api/storage/GetQuota `: {200, `{"totalBytes":456,"usedBytes":123}`, serverStateEmpty}, `POST /apps/sciencemesh/~tester/api/storage/CreateReference {"path":"some/file/path.txt","url":"http://bing.com/search?q=dotnet"}`: {200, ``, serverStateEmpty}, `POST /apps/sciencemesh/~tester/api/storage/Shutdown `: {200, ``, serverStateEmpty}, - `POST /apps/sciencemesh/~tester/api/storage/SetArbitraryMetadata {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"md":{"metadata":{"arbi":"trary","meta":"data"}}}`: {200, ``, serverStateEmpty}, - `POST /apps/sciencemesh/~tester/api/storage/UnsetArbitraryMetadata {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"keys":["arbi"]}`: {200, ``, serverStateEmpty}, - `POST /apps/sciencemesh/~tester/api/storage/ListStorageSpaces [{"type":3,"Term":{"Owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},{"type":2,"Term":{"Id":{"opaque_id":"opaque-id"}}},{"type":4,"Term":{"SpaceType":"home"}}]`: {200, ` [{"opaque":{"map":{"bar":{"value":"c2FtYQ=="},"foo":{"value":"c2FtYQ=="}}},"id":{"opaque_id":"some-opaque-storage-space-id"},"owner":{"id":{"idp":"some-idp","opaque_id":"some-opaque-user-id","type":1}},"root":{"storage_id":"some-storage-ud","opaque_id":"some-opaque-root-id"},"name":"My Storage Space","quota":{"quota_max_bytes":456,"quota_max_files":123},"space_type":"home","mtime":{"seconds":1234567890}}]`, serverStateEmpty}, + `POST /apps/sciencemesh/~tester/api/storage/SetArbitraryMetadata {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"md":{"metadata":{"arbi":"trary","meta":"data"}}}`: {200, ``, serverStateEmpty}, + `POST /apps/sciencemesh/~tester/api/storage/UnsetArbitraryMetadata {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"keys":["arbi"]}`: {200, ``, serverStateEmpty}, + `POST /apps/sciencemesh/~tester/api/storage/ListStorageSpaces [{"type":3,"Term":{"Owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},{"type":2,"Term":{"Id":{"opaque_id":"opaque-id"}}},{"type":4,"Term":{"SpaceType":"home"}}]`: {200, ` [{"opaque":{"map":{"bar":{"value":"c2FtYQ=="},"foo":{"value":"c2FtYQ=="}}},"id":{"opaque_id":"some-opaque-storage-space-id"},"owner":{"id":{"idp":"some-idp","opaque_id":"some-opaque-user-id","type":1}},"root":{"storage_id":"some-storage-ud","opaque_id":"some-opaque-root-id"},"name":"My Storage Space","quota":{"quota_max_bytes":456,"quota_max_files":123},"space_type":"home","mtime":{"seconds":1234567890}}]`, serverStateEmpty}, `POST /apps/sciencemesh/~tester/api/storage/CreateStorageSpace {"opaque":{"map":{"bar":{"value":"c2FtYQ=="},"foo":{"value":"c2FtYQ=="}}},"owner":{"id":{"idp":"some-idp","opaque_id":"some-opaque-user-id","type":1}},"type":"home","name":"My Storage Space","quota":{"quota_max_bytes":456,"quota_max_files":123}}`: {200, `{"storage_space":{"opaque":{"map":{"bar":{"value":"c2FtYQ=="},"foo":{"value":"c2FtYQ=="}}},"id":{"opaque_id":"some-opaque-storage-space-id"},"owner":{"id":{"idp":"some-idp","opaque_id":"some-opaque-user-id","type":1}},"root":{"storage_id":"some-storage-ud","opaque_id":"some-opaque-root-id"},"name":"My Storage Space","quota":{"quota_max_bytes":456,"quota_max_files":123},"space_type":"home","mtime":{"seconds":1234567890}}}`, serverStateEmpty}, } diff --git a/pkg/storage/fs/owncloud/owncloud.go b/pkg/storage/fs/owncloud/owncloud.go index 8a8d38945f..ace1a12813 100644 --- a/pkg/storage/fs/owncloud/owncloud.go +++ b/pkg/storage/fs/owncloud/owncloud.go @@ -49,6 +49,7 @@ import ( "github.com/cs3org/reva/pkg/storage/utils/ace" "github.com/cs3org/reva/pkg/storage/utils/chunking" "github.com/cs3org/reva/pkg/storage/utils/templates" + "github.com/cs3org/reva/pkg/tracing" "github.com/gomodule/redigo/redis" "github.com/google/uuid" "github.com/mitchellh/mapstructure" @@ -56,6 +57,8 @@ import ( "github.com/pkg/xattr" ) +const tracerName = "owncloud" + const ( // Currently,extended file attributes have four separated // namespaces (user, trusted, security and system) followed by a dot. @@ -216,11 +219,16 @@ type ocfs struct { } func (fs *ocfs) Shutdown(ctx context.Context) error { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "Shutdown") + defer span.End() return fs.pool.Close() } // scan files and add uuid to path mapping to kv store func (fs *ocfs) scanFiles(ctx context.Context, conn redis.Conn) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "scanFiles") + defer span.End() + if fs.c.Scan { fs.c.Scan = false // TODO ... in progress use mutex ? log := appctx.GetLogger(ctx) @@ -260,6 +268,9 @@ func (fs *ocfs) scanFiles(ctx context.Context, conn redis.Conn) { // and prefix the data directory // TODO the path handed to a storage provider should not contain the username func (fs *ocfs) toInternalPath(ctx context.Context, sp string) (ip string) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "toInternalPath") + defer span.End() + if fs.c.EnableHome { u := ctxpkg.ContextMustGetUser(ctx) layout := templates.WithUser(u, fs.c.UserLayout) @@ -300,6 +311,9 @@ func (fs *ocfs) toInternalPath(ctx context.Context, sp string) (ip string) { } func (fs *ocfs) toInternalShadowPath(ctx context.Context, sp string) (internal string) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "toInternalShadowPath") + defer span.End() + if fs.c.EnableHome { u := ctxpkg.ContextMustGetUser(ctx) layout := templates.WithUser(u, fs.c.UserLayout) @@ -341,6 +355,9 @@ func (fs *ocfs) toInternalShadowPath(ctx context.Context, sp string) (internal s // and prefix the data directory // TODO the path handed to a storage provider should not contain the username func (fs *ocfs) getVersionsPath(ctx context.Context, ip string) string { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getVersionsPath") + defer span.End() + // ip = /path/to/data//files/foo/bar.txt // remove data dir if fs.c.DataDirectory != "/" { @@ -373,6 +390,9 @@ func (fs *ocfs) getVersionsPath(ctx context.Context, ip string) string { // owncloud stores trashed items in the files_trashbin subfolder of a users home func (fs *ocfs) getRecyclePath(ctx context.Context) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getRecyclePath") + defer span.End() + u, ok := ctxpkg.ContextGetUser(ctx) if !ok { err := errors.Wrap(errtypes.UserRequired("userrequired"), "error getting user from ctx") @@ -383,6 +403,9 @@ func (fs *ocfs) getRecyclePath(ctx context.Context) (string, error) { } func (fs *ocfs) getVersionRecyclePath(ctx context.Context) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getVersionRecyclePath") + defer span.End() + u, ok := ctxpkg.ContextGetUser(ctx) if !ok { err := errors.Wrap(errtypes.UserRequired("userrequired"), "error getting user from ctx") @@ -393,6 +416,9 @@ func (fs *ocfs) getVersionRecyclePath(ctx context.Context) (string, error) { } func (fs *ocfs) toStoragePath(ctx context.Context, ip string) (sp string) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "toStoragePath") + defer span.End() + if fs.c.EnableHome { u := ctxpkg.ContextMustGetUser(ctx) layout := templates.WithUser(u, fs.c.UserLayout) @@ -430,6 +456,9 @@ func (fs *ocfs) toStoragePath(ctx context.Context, ip string) (sp string) { } func (fs *ocfs) toStorageShadowPath(ctx context.Context, ip string) (sp string) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "toStorageShadowPath") + defer span.End() + if fs.c.EnableHome { u := ctxpkg.ContextMustGetUser(ctx) layout := templates.WithUser(u, fs.c.UserLayout) @@ -473,6 +502,9 @@ func (fs *ocfs) getOwner(ip string) string { // TODO cache user lookup func (fs *ocfs) getUser(ctx context.Context, usernameOrID string) (id *userpb.User, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getUser") + defer span.End() + u := ctxpkg.ContextMustGetUser(ctx) // check if username matches and id is set if u.Username == usernameOrID && u.Id != nil && u.Id.OpaqueId != "" { @@ -485,7 +517,7 @@ func (fs *ocfs) getUser(ctx context.Context, usernameOrID string) (id *userpb.Us // look up at the userprovider // parts[0] contains the username or userid. use user service to look up id - c, err := pool.GetUserProviderServiceClient(pool.Endpoint(fs.c.UserProviderEndpoint)) + c, err := pool.GetUserProviderServiceClient(ctx, pool.Endpoint(fs.c.UserProviderEndpoint)) if err != nil { appctx.GetLogger(ctx). Error().Err(err). @@ -530,6 +562,9 @@ func (fs *ocfs) getUser(ctx context.Context, usernameOrID string) (id *userpb.Us // permissionSet returns the permission set for the current user func (fs *ocfs) permissionSet(ctx context.Context, owner *userpb.UserId) *provider.ResourcePermissions { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "permissionSet") + defer span.End() + if owner == nil { return &provider.ResourcePermissions{ Stat: true, @@ -592,6 +627,9 @@ func (fs *ocfs) permissionSet(ctx context.Context, owner *userpb.UserId) *provid } } func (fs *ocfs) convertToResourceInfo(ctx context.Context, fi os.FileInfo, ip string, sp string, c redis.Conn, mdKeys []string) *provider.ResourceInfo { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convertToResourceInfo") + defer span.End() + id := readOrCreateID(ctx, ip, c) etag := calcEtag(ctx, fi) @@ -707,10 +745,16 @@ func getResourceType(isDir bool) provider.ResourceType { // CreateStorageSpace creates a storage space func (fs *ocfs) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convertToResourceInfo") + defer span.End() + return nil, fmt.Errorf("unimplemented: CreateStorageSpace") } func readOrCreateID(ctx context.Context, ip string, conn redis.Conn) string { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "readOrCreateID") + defer span.End() + log := appctx.GetLogger(ctx) // read extended file attribute for id @@ -746,6 +790,9 @@ func readOrCreateID(ctx context.Context, ip string, conn redis.Conn) string { } func (fs *ocfs) getPath(ctx context.Context, id *provider.ResourceId) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getPath") + defer span.End() + log := appctx.GetLogger(ctx) c := fs.pool.Get() defer c.Close() @@ -777,6 +824,9 @@ func (fs *ocfs) getPath(ctx context.Context, id *provider.ResourceId) (string, e // GetPathByID returns the storage relative path for the file id, without the internal namespace func (fs *ocfs) GetPathByID(ctx context.Context, id *provider.ResourceId) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPathByID") + defer span.End() + ip, err := fs.getPath(ctx, id) if err != nil { return "", err @@ -799,6 +849,8 @@ func (fs *ocfs) GetPathByID(ctx context.Context, id *provider.ResourceId) (strin // resolve takes in a request path or request id and converts it to an internal path. func (fs *ocfs) resolve(ctx context.Context, ref *provider.Reference) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "resolve") + defer span.End() // if storage id is set look up that if ref.ResourceId != nil { @@ -815,10 +867,16 @@ func (fs *ocfs) resolve(ctx context.Context, ref *provider.Reference) (string, e } func (fs *ocfs) DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DenyGrant") + defer span.End() + return errtypes.NotSupported("ocfs: deny grant not supported") } func (fs *ocfs) AddGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "AddGrant") + defer span.End() + ip, err := fs.resolve(ctx, ref) if err != nil { return errors.Wrap(err, "ocfs: error resolving reference") @@ -846,6 +904,9 @@ func (fs *ocfs) AddGrant(ctx context.Context, ref *provider.Reference, g *provid // extractACEsFromAttrs reads ACEs in the list of attrs from the file func extractACEsFromAttrs(ctx context.Context, ip string, attrs []string) (entries []*ace.ACE) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "extractACEsFromAttrs") + defer span.End() + log := appctx.GetLogger(ctx) entries = []*ace.ACE{} for i := range attrs { @@ -876,6 +937,8 @@ func extractACEsFromAttrs(ctx context.Context, ip string, attrs []string) (entri // We need the storage relative path so we can calculate the permissions // for the node based on all acls in the tree up to the root func (fs *ocfs) readPermissions(ctx context.Context, ip string) (p *provider.ResourcePermissions, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "readPermissions") + defer span.End() u, ok := ctxpkg.ContextGetUser(ctx) if !ok { @@ -995,6 +1058,9 @@ func isNotFound(err error) bool { } func (fs *ocfs) readACE(ctx context.Context, ip string, principal string) (e *ace.ACE, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "readACE") + defer span.End() + var b []byte if b, err = xattr.Get(ip, sharePrefix+principal); err != nil { return nil, err @@ -1028,6 +1094,9 @@ func addPermissions(p1 *provider.ResourcePermissions, p2 *provider.ResourcePermi } func (fs *ocfs) ListGrants(ctx context.Context, ref *provider.Reference) (grants []*provider.Grant, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListGrants") + defer span.End() + log := appctx.GetLogger(ctx) var ip string if ip, err = fs.resolve(ctx, ref); err != nil { @@ -1066,6 +1135,8 @@ func (fs *ocfs) ListGrants(ctx context.Context, ref *provider.Reference) (grants } func (fs *ocfs) RemoveGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RemoveGrant") + defer span.End() var ip string if ip, err = fs.resolve(ctx, ref); err != nil { @@ -1099,6 +1170,9 @@ func (fs *ocfs) RemoveGrant(ctx context.Context, ref *provider.Reference, g *pro } func (fs *ocfs) UpdateGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateGrant") + defer span.End() + ip, err := fs.resolve(ctx, ref) if err != nil { return errors.Wrap(err, "ocfs: error resolving reference") @@ -1125,6 +1199,9 @@ func (fs *ocfs) UpdateGrant(ctx context.Context, ref *provider.Reference, g *pro } func (fs *ocfs) CreateHome(ctx context.Context) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateHome") + defer span.End() + u, ok := ctxpkg.ContextGetUser(ctx) if !ok { err := errors.Wrap(errtypes.UserRequired("userrequired"), "error getting user from ctx") @@ -1151,6 +1228,9 @@ func (fs *ocfs) CreateHome(ctx context.Context) error { // If home is enabled, the relative home is always the empty string func (fs *ocfs) GetHome(ctx context.Context) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetHome") + defer span.End() + if !fs.c.EnableHome { return "", errtypes.NotSupported("ocfs: get home not supported") } @@ -1158,6 +1238,8 @@ func (fs *ocfs) GetHome(ctx context.Context) (string, error) { } func (fs *ocfs) CreateDir(ctx context.Context, ref *provider.Reference) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateDir") + defer span.End() ip, err := fs.resolve(ctx, ref) if err != nil { @@ -1188,6 +1270,9 @@ func (fs *ocfs) CreateDir(ctx context.Context, ref *provider.Reference) (err err // TouchFile as defined in the storage.FS interface func (fs *ocfs) TouchFile(ctx context.Context, ref *provider.Reference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "TouchFile") + defer span.End() + return fmt.Errorf("unimplemented: TouchFile") } @@ -1200,6 +1285,9 @@ func (fs *ocfs) isShareFolderRoot(sp string) bool { } func (fs *ocfs) CreateReference(ctx context.Context, sp string, targetURI *url.URL) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateReference") + defer span.End() + if !fs.isShareFolderChild(sp) { return errtypes.PermissionDenied("ocfs: cannot create references outside the share folder: share_folder=" + "/Shares" + " path=" + sp) } @@ -1225,6 +1313,9 @@ func (fs *ocfs) CreateReference(ctx context.Context, sp string, targetURI *url.U } func (fs *ocfs) setMtime(ctx context.Context, ip string, mtime string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "setMtime") + defer span.End() + log := appctx.GetLogger(ctx) if mt, err := parseMTime(mtime); err == nil { // updating mtime also updates atime @@ -1245,6 +1336,9 @@ func (fs *ocfs) setMtime(ctx context.Context, ip string, mtime string) error { return nil } func (fs *ocfs) SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetArbitraryMetadata") + defer span.End() + log := appctx.GetLogger(ctx) var ip string @@ -1388,6 +1482,9 @@ func parseMTime(v string) (t time.Time, err error) { } func (fs *ocfs) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UnsetArbitraryMetadata") + defer span.End() + log := appctx.GetLogger(ctx) var ip string @@ -1475,21 +1572,33 @@ func (fs *ocfs) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Refere // GetLock returns an existing lock on the given reference func (fs *ocfs) GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetLock") + defer span.End() + return nil, errtypes.NotSupported("unimplemented") } // SetLock puts a lock on the given reference func (fs *ocfs) SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetLock") + defer span.End() + return errtypes.NotSupported("unimplemented") } // RefreshLock refreshes an existing lock on the given reference func (fs *ocfs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RefreshLock") + defer span.End() + return errtypes.NotSupported("unimplemented") } // Unlock removes an existing lock from the given reference func (fs *ocfs) Unlock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Unlock") + defer span.End() + return errtypes.NotSupported("unimplemented") } @@ -1503,6 +1612,9 @@ func (fs *ocfs) Unlock(ctx context.Context, ref *provider.Reference, lock *provi // We will live with that compromise since this storage driver will be // deprecated soon. func (fs *ocfs) Delete(ctx context.Context, ref *provider.Reference) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Delete") + defer span.End() + var ip string if ip, err = fs.resolve(ctx, ref); err != nil { return errors.Wrap(err, "ocfs: error resolving reference") @@ -1552,6 +1664,9 @@ func (fs *ocfs) Delete(ctx context.Context, ref *provider.Reference) (err error) } func (fs *ocfs) trash(ctx context.Context, ip string, rp string, origin string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "trash") + defer span.End() + // set origin location in metadata if err := xattr.Set(ip, trashOriginPrefix, []byte(origin)); err != nil { return err @@ -1579,6 +1694,9 @@ func (fs *ocfs) trash(ctx context.Context, ip string, rp string, origin string) } func (fs *ocfs) trashVersions(ctx context.Context, ip string, origin string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "trashVersions") + defer span.End() + vp := fs.getVersionsPath(ctx, ip) vrp, err := fs.getVersionRecyclePath(ctx) if err != nil { @@ -1601,6 +1719,9 @@ func (fs *ocfs) trashVersions(ctx context.Context, ip string, origin string) err } func (fs *ocfs) Move(ctx context.Context, oldRef, newRef *provider.Reference) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Move") + defer span.End() + var oldIP string if oldIP, err = fs.resolve(ctx, oldRef); err != nil { return errors.Wrap(err, "ocfs: error resolving reference") @@ -1659,6 +1780,9 @@ func (fs *ocfs) Move(ctx context.Context, oldRef, newRef *provider.Reference) (e } func (fs *ocfs) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetMD") + defer span.End() + ip, err := fs.resolve(ctx, ref) if err != nil { // TODO return correct errtype @@ -1707,6 +1831,9 @@ func (fs *ocfs) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []str } func (fs *ocfs) getMDShareFolder(ctx context.Context, sp string, mdKeys []string) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getMDShareFolder") + defer span.End() + ip := fs.toInternalShadowPath(ctx, sp) // check permissions @@ -1747,6 +1874,9 @@ func (fs *ocfs) getMDShareFolder(ctx context.Context, sp string, mdKeys []string } func (fs *ocfs) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys []string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListFolder") + defer span.End() + log := appctx.GetLogger(ctx) ip, err := fs.resolve(ctx, ref) @@ -1769,6 +1899,8 @@ func (fs *ocfs) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys } func (fs *ocfs) listWithNominalHome(ctx context.Context, ip string, mdKeys []string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listWithNominalHome") + defer span.End() // If a user wants to list a folder shared with him the path will already // be wrapped with the files directory path of the share owner. @@ -1805,6 +1937,9 @@ func (fs *ocfs) listWithNominalHome(ctx context.Context, ip string, mdKeys []str } func (fs *ocfs) listWithHome(ctx context.Context, home, p string, mdKeys []string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listWithHome") + defer span.End() + log := appctx.GetLogger(ctx) if p == home { log.Debug().Msg("listing home") @@ -1825,6 +1960,9 @@ func (fs *ocfs) listWithHome(ctx context.Context, home, p string, mdKeys []strin } func (fs *ocfs) listHome(ctx context.Context, home string, mdKeys []string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listHome") + defer span.End() + // list files ip := fs.toInternalPath(ctx, home) @@ -1870,6 +2008,9 @@ func (fs *ocfs) listHome(ctx context.Context, home string, mdKeys []string) ([]* } func (fs *ocfs) listShareFolderRoot(ctx context.Context, sp string, mdKeys []string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listShareFolderRoot") + defer span.End() + ip := fs.toInternalShadowPath(ctx, sp) // check permissions @@ -1912,6 +2053,9 @@ func (fs *ocfs) listShareFolderRoot(ctx context.Context, sp string, mdKeys []str } func (fs *ocfs) archiveRevision(ctx context.Context, vbp string, ip string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "archiveRevision") + defer span.End() + // move existing file to versions dir vp := fmt.Sprintf("%s.v%d", vbp, time.Now().Unix()) if err := os.MkdirAll(filepath.Dir(vp), 0700); err != nil { @@ -1946,6 +2090,9 @@ func (fs *ocfs) copyMD(s string, t string) (err error) { } func (fs *ocfs) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Download") + defer span.End() + ip, err := fs.resolve(ctx, ref) if err != nil { return nil, errors.Wrap(err, "ocfs: error resolving reference") @@ -1974,6 +2121,9 @@ func (fs *ocfs) Download(ctx context.Context, ref *provider.Reference) (io.ReadC } func (fs *ocfs) ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListRevisions") + defer span.End() + ip, err := fs.resolve(ctx, ref) if err != nil { return nil, errors.Wrap(err, "ocfs: error resolving reference") @@ -2011,6 +2161,9 @@ func (fs *ocfs) ListRevisions(ctx context.Context, ref *provider.Reference) ([]* } func (fs *ocfs) filterAsRevision(ctx context.Context, bn string, md os.FileInfo) *provider.FileVersion { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "filterAsRevision") + defer span.End() + if strings.HasPrefix(md.Name(), bn) { // versions have filename.ext.v12345678 version := md.Name()[len(bn)+2:] // truncate ".v" to get version mtime @@ -2032,10 +2185,16 @@ func (fs *ocfs) filterAsRevision(ctx context.Context, bn string, md os.FileInfo) } func (fs *ocfs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DownloadRevision") + defer span.End() + return nil, errtypes.NotSupported("download revision") } func (fs *ocfs) RestoreRevision(ctx context.Context, ref *provider.Reference, revisionKey string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreRevision") + defer span.End() + ip, err := fs.resolve(ctx, ref) if err != nil { return errors.Wrap(err, "ocfs: error resolving reference") @@ -2095,6 +2254,9 @@ func (fs *ocfs) RestoreRevision(ctx context.Context, ref *provider.Reference, re } func (fs *ocfs) PurgeRecycleItem(ctx context.Context, basePath, key, relativePath string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "PurgeRecycleItem") + defer span.End() + rp, err := fs.getRecyclePath(ctx) if err != nil { return errors.Wrap(err, "ocfs: error resolving recycle path") @@ -2129,6 +2291,9 @@ func (fs *ocfs) PurgeRecycleItem(ctx context.Context, basePath, key, relativePat } func (fs *ocfs) EmptyRecycle(ctx context.Context) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "EmptyRecycle") + defer span.End() + // TODO check permission? on what? user must be the owner rp, err := fs.getRecyclePath(ctx) if err != nil { @@ -2147,6 +2312,9 @@ func (fs *ocfs) EmptyRecycle(ctx context.Context) error { } func (fs *ocfs) convertToRecycleItem(ctx context.Context, rp string, md os.FileInfo) *provider.RecycleItem { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convertToRecycleItem") + defer span.End() + // trashbin items have filename.ext.d12345678 suffix := filepath.Ext(md.Name()) if len(suffix) == 0 || !strings.HasPrefix(suffix, ".d") { @@ -2188,6 +2356,9 @@ func (fs *ocfs) convertToRecycleItem(ctx context.Context, rp string, md os.FileI } func (fs *ocfs) ListRecycle(ctx context.Context, basePath, key, relativePath string) ([]*provider.RecycleItem, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListRecycle") + defer span.End() + // TODO check permission? on what? user must be the owner? rp, err := fs.getRecyclePath(ctx) if err != nil { @@ -2215,6 +2386,9 @@ func (fs *ocfs) ListRecycle(ctx context.Context, basePath, key, relativePath str } func (fs *ocfs) RestoreRecycleItem(ctx context.Context, basePath, key, relativePath string, restoreRef *provider.Reference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreRecycleItem") + defer span.End() + // TODO check permission? on what? user must be the owner? log := appctx.GetLogger(ctx) rp, err := fs.getRecyclePath(ctx) @@ -2256,15 +2430,24 @@ func (fs *ocfs) RestoreRecycleItem(ctx context.Context, basePath, key, relativeP } func (fs *ocfs) ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter) ([]*provider.StorageSpace, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListStorageSpaces") + defer span.End() + return nil, errtypes.NotSupported("list storage spaces") } // UpdateStorageSpace updates a storage space func (fs *ocfs) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateStorageSpace") + defer span.End() + return nil, errtypes.NotSupported("update storage space") } func (fs *ocfs) propagate(ctx context.Context, leafPath string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "propagate") + defer span.End() + var root string if fs.c.EnableHome { root = fs.toInternalPath(ctx, "/") @@ -2316,6 +2499,9 @@ func (fs *ocfs) propagate(ctx context.Context, leafPath string) error { } func readChecksumIntoResourceChecksum(ctx context.Context, nodePath, algo string, ri *provider.ResourceInfo) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "readChecksumIntoResourceChecksum") + defer span.End() + v, err := xattr.Get(nodePath, checksumPrefix+algo) log := appctx.GetLogger(ctx). Debug(). @@ -2338,6 +2524,9 @@ func readChecksumIntoResourceChecksum(ctx context.Context, nodePath, algo string } func readChecksumIntoOpaque(ctx context.Context, nodePath, algo string, ri *provider.ResourceInfo) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "readChecksumIntoOpaque") + defer span.End() + v, err := xattr.Get(nodePath, checksumPrefix+algo) log := appctx.GetLogger(ctx). Debug(). diff --git a/pkg/storage/fs/owncloudsql/owncloudsql.go b/pkg/storage/fs/owncloudsql/owncloudsql.go index 10b019baa2..4a769ab295 100644 --- a/pkg/storage/fs/owncloudsql/owncloudsql.go +++ b/pkg/storage/fs/owncloudsql/owncloudsql.go @@ -54,12 +54,15 @@ import ( "github.com/cs3org/reva/pkg/storage/fs/registry" "github.com/cs3org/reva/pkg/storage/utils/chunking" "github.com/cs3org/reva/pkg/storage/utils/templates" + "github.com/cs3org/reva/pkg/tracing" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/pkg/xattr" "github.com/rs/zerolog/log" ) +const tracerName = "owncloudsql" + const ( // Currently,extended file attributes have four separated // namespaces (user, trusted, security and system) followed by a dot. @@ -196,6 +199,9 @@ type owncloudsqlfs struct { } func (fs *owncloudsqlfs) Shutdown(ctx context.Context) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Shutdown") + defer span.End() + return nil } @@ -204,6 +210,9 @@ func (fs *owncloudsqlfs) Shutdown(ctx context.Context) error { // and prefix the data directory // TODO the path handed to a storage provider should not contain the username func (fs *owncloudsqlfs) toInternalPath(ctx context.Context, sp string) (ip string) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "toInternalPath") + defer span.End() + if fs.c.EnableHome { u := ctxpkg.ContextMustGetUser(ctx) layout := templates.WithUser(u, fs.c.UserLayout) @@ -246,6 +255,9 @@ func (fs *owncloudsqlfs) toInternalPath(ctx context.Context, sp string) (ip stri // and prefix the data directory // TODO the path handed to a storage provider should not contain the username func (fs *owncloudsqlfs) getVersionsPath(ctx context.Context, ip string) string { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getVersionsPath") + defer span.End() + // ip = /path/to/data//files/foo/bar.txt // remove data dir if fs.c.DataDirectory != "/" { @@ -278,6 +290,9 @@ func (fs *owncloudsqlfs) getVersionsPath(ctx context.Context, ip string) string // owncloudsql stores trashed items in the files_trashbin subfolder of a users home func (fs *owncloudsqlfs) getRecyclePath(ctx context.Context) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getRecyclePath") + defer span.End() + u, ok := ctxpkg.ContextGetUser(ctx) if !ok { err := errors.Wrap(errtypes.UserRequired("userrequired"), "error getting user from ctx") @@ -292,6 +307,9 @@ func (fs *owncloudsqlfs) getRecyclePathForUser(user string) (string, error) { } func (fs *owncloudsqlfs) getVersionRecyclePath(ctx context.Context) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getVersionRecyclePath") + defer span.End() + u, ok := ctxpkg.ContextGetUser(ctx) if !ok { err := errors.Wrap(errtypes.UserRequired("userrequired"), "error getting user from ctx") @@ -310,6 +328,9 @@ func (fs *owncloudsqlfs) toDatabasePath(ip string) string { } func (fs *owncloudsqlfs) toStoragePath(ctx context.Context, ip string) (sp string) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "toStoragePath") + defer span.End() + if fs.c.EnableHome { u := ctxpkg.ContextMustGetUser(ctx) layout := templates.WithUser(u, fs.c.UserLayout) @@ -358,6 +379,9 @@ func (fs *owncloudsqlfs) getOwner(ip string) string { // TODO cache user lookup func (fs *owncloudsqlfs) getUser(ctx context.Context, usernameOrID string) (id *userpb.User, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getUser") + defer span.End() + u := ctxpkg.ContextMustGetUser(ctx) // check if username matches and id is set if u.Username == usernameOrID && u.Id != nil && u.Id.OpaqueId != "" { @@ -370,7 +394,7 @@ func (fs *owncloudsqlfs) getUser(ctx context.Context, usernameOrID string) (id * // look up at the userprovider // parts[0] contains the username or userid. use user service to look up id - c, err := pool.GetUserProviderServiceClient(pool.Endpoint(fs.c.UserProviderEndpoint)) + c, err := pool.GetUserProviderServiceClient(ctx, pool.Endpoint(fs.c.UserProviderEndpoint)) if err != nil { appctx.GetLogger(ctx). Error().Err(err). @@ -415,6 +439,9 @@ func (fs *owncloudsqlfs) getUser(ctx context.Context, usernameOrID string) (id * // permissionSet returns the permission set for the current user func (fs *owncloudsqlfs) permissionSet(ctx context.Context, owner *userpb.UserId) *provider.ResourcePermissions { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "permissionSet") + defer span.End() + if owner == nil { return &provider.ResourcePermissions{ Stat: true, @@ -491,10 +518,16 @@ func (fs *owncloudsqlfs) getUserStorage(user string) (int, error) { // CreateStorageSpace creates a storage space func (fs *owncloudsqlfs) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateStorageSpace") + defer span.End() + return nil, fmt.Errorf("unimplemented: CreateStorageSpace") } func (fs *owncloudsqlfs) convertToResourceInfo(ctx context.Context, entry *filecache.File, ip string, mdKeys []string) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convertToResourceInfo") + defer span.End() + mdKeysMap := make(map[string]struct{}) for _, k := range mdKeys { mdKeysMap[k] = struct{}{} @@ -544,6 +577,9 @@ func (fs *owncloudsqlfs) convertToResourceInfo(ctx context.Context, entry *filec // GetPathByID returns the storage relative path for the file id, without the internal namespace func (fs *owncloudsqlfs) GetPathByID(ctx context.Context, id *provider.ResourceId) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPathByID") + defer span.End() + ip, err := fs.filecache.Path(id.OpaqueId) if err != nil { return "", err @@ -566,6 +602,8 @@ func (fs *owncloudsqlfs) GetPathByID(ctx context.Context, id *provider.ResourceI // resolve takes in a request path or request id and converts it to an internal path. func (fs *owncloudsqlfs) resolve(ctx context.Context, ref *provider.Reference) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "resolve") + defer span.End() if ref.GetResourceId() != nil { p, err := fs.filecache.Path(ref.GetResourceId().OpaqueId) @@ -592,14 +630,23 @@ func (fs *owncloudsqlfs) resolve(ctx context.Context, ref *provider.Reference) ( } func (fs *owncloudsqlfs) DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DenyGrant") + defer span.End() + return errtypes.NotSupported("owncloudsqlfs: deny grant not supported") } func (fs *owncloudsqlfs) AddGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "AddGrant") + defer span.End() + return errtypes.NotSupported("owncloudsqlfs: add grant not supported") } func (fs *owncloudsqlfs) readPermissions(ctx context.Context, ip string) (p *provider.ResourcePermissions, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "readPermissions") + defer span.End() + u, ok := ctxpkg.ContextGetUser(ctx) if !ok { appctx.GetLogger(ctx).Debug().Str("ipath", ip).Msg("no user in context, returning default permissions") @@ -640,18 +687,30 @@ func isNotFound(err error) bool { } func (fs *owncloudsqlfs) ListGrants(ctx context.Context, ref *provider.Reference) (grants []*provider.Grant, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListGrants") + defer span.End() + return []*provider.Grant{}, nil // nop } func (fs *owncloudsqlfs) RemoveGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RemoveGrant") + defer span.End() + return nil // nop } func (fs *owncloudsqlfs) UpdateGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateGrant") + defer span.End() + return nil // nop } func (fs *owncloudsqlfs) CreateHome(ctx context.Context) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateHome") + defer span.End() + u, ok := ctxpkg.ContextGetUser(ctx) if !ok { err := errors.Wrap(errtypes.UserRequired("userrequired"), "error getting user from ctx") @@ -661,6 +720,9 @@ func (fs *owncloudsqlfs) CreateHome(ctx context.Context) error { } func (fs *owncloudsqlfs) createHomeForUser(ctx context.Context, user string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "createHomeForUser") + defer span.End() + homePaths := []string{ filepath.Join(fs.c.DataDirectory, user), filepath.Join(fs.c.DataDirectory, user, "files"), @@ -701,6 +763,9 @@ func (fs *owncloudsqlfs) createHomeForUser(ctx context.Context, user string) err // If home is enabled, the relative home is always the empty string func (fs *owncloudsqlfs) GetHome(ctx context.Context) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetHome") + defer span.End() + if !fs.c.EnableHome { return "", errtypes.NotSupported("owncloudsql: get home not supported") } @@ -708,6 +773,8 @@ func (fs *owncloudsqlfs) GetHome(ctx context.Context) (string, error) { } func (fs *owncloudsqlfs) CreateDir(ctx context.Context, ref *provider.Reference) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateDir") + defer span.End() ip, err := fs.resolve(ctx, ref) if err != nil { @@ -768,14 +835,23 @@ func (fs *owncloudsqlfs) CreateDir(ctx context.Context, ref *provider.Reference) // TouchFile as defined in the storage.FS interface func (fs *owncloudsqlfs) TouchFile(ctx context.Context, ref *provider.Reference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "TouchFile") + defer span.End() + return fmt.Errorf("unimplemented: TouchFile") } func (fs *owncloudsqlfs) CreateReference(ctx context.Context, sp string, targetURI *url.URL) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateReference") + defer span.End() + return errtypes.NotSupported("owncloudsql: operation not supported") } func (fs *owncloudsqlfs) setMtime(ctx context.Context, ip string, mtime string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "setMtime") + defer span.End() + log := appctx.GetLogger(ctx) if mt, err := parseMTime(mtime); err == nil { // updating mtime also updates atime @@ -796,6 +872,9 @@ func (fs *owncloudsqlfs) setMtime(ctx context.Context, ip string, mtime string) return nil } func (fs *owncloudsqlfs) SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetArbitraryMetadata") + defer span.End() + log := appctx.GetLogger(ctx) var ip string @@ -939,6 +1018,9 @@ func parseMTime(v string) (t time.Time, err error) { } func (fs *owncloudsqlfs) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UnsetArbitraryMetadata") + defer span.End() + log := appctx.GetLogger(ctx) var ip string @@ -1026,21 +1108,33 @@ func (fs *owncloudsqlfs) UnsetArbitraryMetadata(ctx context.Context, ref *provid // GetLock returns an existing lock on the given reference func (fs *owncloudsqlfs) GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetLock") + defer span.End() + return nil, errtypes.NotSupported("unimplemented") } // SetLock puts a lock on the given reference func (fs *owncloudsqlfs) SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetLock") + defer span.End() + return errtypes.NotSupported("unimplemented") } // RefreshLock refreshes an existing lock on the given reference func (fs *owncloudsqlfs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RefreshLock") + defer span.End() + return errtypes.NotSupported("unimplemented") } // Unlock removes an existing lock from the given reference func (fs *owncloudsqlfs) Unlock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Unlock") + defer span.End() + return errtypes.NotSupported("unimplemented") } @@ -1054,6 +1148,9 @@ func (fs *owncloudsqlfs) Unlock(ctx context.Context, ref *provider.Reference, lo // We will live with that compromise since this storage driver will be // deprecated soon. func (fs *owncloudsqlfs) Delete(ctx context.Context, ref *provider.Reference) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Delete") + defer span.End() + var ip string if ip, err = fs.resolve(ctx, ref); err != nil { return errors.Wrap(err, "owncloudsql: error resolving reference") @@ -1100,6 +1197,9 @@ func (fs *owncloudsqlfs) Delete(ctx context.Context, ref *provider.Reference) (e } func (fs *owncloudsqlfs) trash(ctx context.Context, ip string, rp string, origin string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "trash") + defer span.End() + // move to trash location dtime := time.Now().Unix() tgt := filepath.Join(rp, fmt.Sprintf("%s.d%d", filepath.Base(ip), dtime)) @@ -1143,6 +1243,9 @@ func (fs *owncloudsqlfs) trash(ctx context.Context, ip string, rp string, origin } func (fs *owncloudsqlfs) trashVersions(ctx context.Context, ip string, origin string, dtime int64) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "trashVersions") + defer span.End() + vp := fs.getVersionsPath(ctx, ip) vrp, err := fs.getVersionRecyclePath(ctx) if err != nil { @@ -1183,6 +1286,9 @@ func (fs *owncloudsqlfs) trashVersions(ctx context.Context, ip string, origin st } func (fs *owncloudsqlfs) Move(ctx context.Context, oldRef, newRef *provider.Reference) (err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Move") + defer span.End() + var oldIP string if oldIP, err = fs.resolve(ctx, oldRef); err != nil { return errors.Wrap(err, "owncloudsql: error resolving reference") @@ -1230,6 +1336,9 @@ func (fs *owncloudsqlfs) Move(ctx context.Context, oldRef, newRef *provider.Refe } func (fs *owncloudsqlfs) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetMD") + defer span.End() + ip, err := fs.resolve(ctx, ref) if err != nil { // TODO return correct errtype @@ -1274,6 +1383,9 @@ func (fs *owncloudsqlfs) GetMD(ctx context.Context, ref *provider.Reference, mdK } func (fs *owncloudsqlfs) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys []string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListFolder") + defer span.End() + log := appctx.GetLogger(ctx) ip, err := fs.resolve(ctx, ref) @@ -1296,6 +1408,8 @@ func (fs *owncloudsqlfs) ListFolder(ctx context.Context, ref *provider.Reference } func (fs *owncloudsqlfs) listWithNominalHome(ctx context.Context, ip string, mdKeys []string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listWithNominalHome") + defer span.End() // If a user wants to list a folder shared with him the path will already // be wrapped with the files directory path of the share owner. @@ -1341,6 +1455,9 @@ func (fs *owncloudsqlfs) listWithNominalHome(ctx context.Context, ip string, mdK } func (fs *owncloudsqlfs) listWithHome(ctx context.Context, home, p string, mdKeys []string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listWithHome") + defer span.End() + log := appctx.GetLogger(ctx) if p == home { log.Debug().Msg("listing home") @@ -1352,6 +1469,9 @@ func (fs *owncloudsqlfs) listWithHome(ctx context.Context, home, p string, mdKey } func (fs *owncloudsqlfs) listHome(ctx context.Context, home string, mdKeys []string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listHome") + defer span.End() + // list files ip := fs.toInternalPath(ctx, home) @@ -1389,6 +1509,9 @@ func (fs *owncloudsqlfs) listHome(ctx context.Context, home string, mdKeys []str } func (fs *owncloudsqlfs) archiveRevision(ctx context.Context, vbp string, ip string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "archiveRevision") + defer span.End() + // move existing file to versions dir vp := fmt.Sprintf("%s.v%d", vbp, time.Now().Unix()) if err := os.MkdirAll(filepath.Dir(vp), 0700); err != nil { @@ -1437,6 +1560,9 @@ func (fs *owncloudsqlfs) archiveRevision(ctx context.Context, vbp string, ip str } func (fs *owncloudsqlfs) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Download") + defer span.End() + ip, err := fs.resolve(ctx, ref) if err != nil { return nil, errors.Wrap(err, "owncloudsql: error resolving reference") @@ -1465,6 +1591,9 @@ func (fs *owncloudsqlfs) Download(ctx context.Context, ref *provider.Reference) } func (fs *owncloudsqlfs) ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListRevisions") + defer span.End() + ip, err := fs.resolve(ctx, ref) if err != nil { return nil, errors.Wrap(err, "owncloudsql: error resolving reference") @@ -1516,10 +1645,16 @@ func (fs *owncloudsqlfs) ListRevisions(ctx context.Context, ref *provider.Refere } func (fs *owncloudsqlfs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DownloadRevision") + defer span.End() + return nil, errtypes.NotSupported("download revision") } func (fs *owncloudsqlfs) RestoreRevision(ctx context.Context, ref *provider.Reference, revisionKey string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreRevision") + defer span.End() + ip, err := fs.resolve(ctx, ref) if err != nil { return errors.Wrap(err, "owncloudsql: error resolving reference") @@ -1605,6 +1740,9 @@ func (fs *owncloudsqlfs) RestoreRevision(ctx context.Context, ref *provider.Refe } func (fs *owncloudsqlfs) PurgeRecycleItem(ctx context.Context, basePath, key, relativePath string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "PurgeRecycleItem") + defer span.End() + rp, err := fs.getRecyclePath(ctx) if err != nil { return errors.Wrap(err, "owncloudsql: error resolving recycle path") @@ -1665,6 +1803,9 @@ func (fs *owncloudsqlfs) PurgeRecycleItem(ctx context.Context, basePath, key, re } func (fs *owncloudsqlfs) EmptyRecycle(ctx context.Context) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "EmptyRecycle") + defer span.End() + // TODO check permission? on what? user must be the owner rp, err := fs.getRecyclePath(ctx) if err != nil { @@ -1704,6 +1845,9 @@ func splitTrashKey(key string) (string, int, error) { } func (fs *owncloudsqlfs) convertToRecycleItem(ctx context.Context, md os.FileInfo) *provider.RecycleItem { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convertToRecycleItem") + defer span.End() + base, ttime, err := splitTrashKey(md.Name()) if err != nil { log := appctx.GetLogger(ctx) @@ -1737,6 +1881,9 @@ func (fs *owncloudsqlfs) convertToRecycleItem(ctx context.Context, md os.FileInf } func (fs *owncloudsqlfs) ListRecycle(ctx context.Context, basePath, key, relativePath string) ([]*provider.RecycleItem, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListRecycle") + defer span.End() + // TODO check permission? on what? user must be the owner? rp, err := fs.getRecyclePath(ctx) if err != nil { @@ -1764,6 +1911,9 @@ func (fs *owncloudsqlfs) ListRecycle(ctx context.Context, basePath, key, relativ } func (fs *owncloudsqlfs) RestoreRecycleItem(ctx context.Context, basePath, key, relativePath string, restoreRef *provider.Reference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreRecycleItem") + defer span.End() + log := appctx.GetLogger(ctx) base, ttime, err := splitTrashKey(key) @@ -1817,6 +1967,9 @@ func (fs *owncloudsqlfs) RestoreRecycleItem(ctx context.Context, basePath, key, } func (fs *owncloudsqlfs) RestoreRecycleItemVersions(ctx context.Context, key, target string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreRecycleItemVersions") + defer span.End() + base, ttime, err := splitTrashKey(key) if err != nil { return fmt.Errorf("invalid trash item suffix") @@ -1856,6 +2009,9 @@ func (fs *owncloudsqlfs) RestoreRecycleItemVersions(ctx context.Context, key, ta } func (fs *owncloudsqlfs) propagate(ctx context.Context, leafPath string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "propagate") + defer span.End() + var root string if fs.c.EnableHome { root = filepath.Clean(fs.toInternalPath(ctx, "/")) @@ -1951,16 +2107,25 @@ func (fs *owncloudsqlfs) HashFile(path string) (string, string, string, error) { } func (fs *owncloudsqlfs) ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter) ([]*provider.StorageSpace, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListStorageSpaces") + defer span.End() + // TODO(corby): Implement return nil, errtypes.NotSupported("list storage spaces") } // UpdateStorageSpace updates a storage space func (fs *owncloudsqlfs) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateStorageSpace") + defer span.End() + return nil, errtypes.NotSupported("update storage space") } func readChecksumIntoResourceChecksum(ctx context.Context, checksums, algo string, ri *provider.ResourceInfo) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "readChecksumIntoResourceChecksum") + defer span.End() + re := regexp.MustCompile(strings.ToUpper(algo) + `:(.*)`) matches := re.FindStringSubmatch(checksums) if len(matches) < 2 { @@ -1978,6 +2143,9 @@ func readChecksumIntoResourceChecksum(ctx context.Context, checksums, algo strin } func readChecksumIntoOpaque(ctx context.Context, checksums, algo string, ri *provider.ResourceInfo) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "readChecksumIntoOpaque") + defer span.End() + re := regexp.MustCompile(strings.ToUpper(algo) + `:(.*)`) matches := re.FindStringSubmatch(checksums) if len(matches) < 2 { diff --git a/pkg/storage/utils/ace/ace.go b/pkg/storage/utils/ace/ace.go index 0123bce377..6db1434ccf 100644 --- a/pkg/storage/utils/ace/ace.go +++ b/pkg/storage/utils/ace/ace.go @@ -39,31 +39,31 @@ import ( // see https://linux.die.net/man/5/nfs4_acl: // the extended attributes will look like this // "user.oc.grant.:::" -// - *type* will be limited to A for now +// - *type* will be limited to A for now // A: Allow - allow *principal* to perform actions requiring *permissions* -// In the future we can use: +// In the future we can use: // U: aUdit - log any attempted access by principal which requires -// permissions. +// permissions. // L: aLarm - generate a system alarm at any attempted access by -// principal which requires permissions +// principal which requires permissions // D: for Deny is not recommended -// - *flags* for now empty or g for group, no inheritance yet +// - *flags* for now empty or g for group, no inheritance yet // - d directory-inherit - newly-created subdirectories will inherit the -// ACE. +// ACE. // - f file-inherit - newly-created files will inherit the ACE, minus its -// inheritance flags. Newly-created subdirectories -// will inherit the ACE; if directory-inherit is not -// also specified in the parent ACE, inherit-only will -// be added to the inherited ACE. +// inheritance flags. Newly-created subdirectories +// will inherit the ACE; if directory-inherit is not +// also specified in the parent ACE, inherit-only will +// be added to the inherited ACE. // - n no-propagate-inherit - newly-created subdirectories will inherit -// the ACE, minus its inheritance flags. +// the ACE, minus its inheritance flags. // - i inherit-only - the ACE is not considered in permissions checks, -// but it is heritable; however, the inherit-only -// flag is stripped from inherited ACEs. -// - *principal* a named user, group or special principal +// but it is heritable; however, the inherit-only +// flag is stripped from inherited ACEs. +// - *principal* a named user, group or special principal // - the oidc sub@iss maps nicely to this // - 'OWNER@', 'GROUP@', and 'EVERYONE@', which are, respectively, analogous to the POSIX user/group/other -// - *permissions* +// - *permissions* // - r read-data (files) / list-directory (directories) // - w write-data (files) / create-file (directories) // - a append-data (files) / create-subdirectory (directories) @@ -78,15 +78,18 @@ import ( // - C write-ACL - write the file/directory NFSv4 ACL. // - o write-owner - change ownership of the file/directory. // - y synchronize - allow clients to use synchronous I/O with the server. +// // TODO implement OWNER@ as "user.oc.grant.A::OWNER@:rwaDxtTnNcCy" // attribute names are limited to 255 chars by the linux kernel vfs, values to 64 kb // ext3 extended attributes must fit inside a single filesystem block ... 4096 bytes // that leaves us with "user.oc.grant.A::someonewithaslightlylongersubject@whateverissuer:rwaDxtTnNcCy" ~80 chars // 4096/80 = 51 shares ... with luck we might move the actual permissions to the value, saving ~15 chars // 4096/64 = 64 shares ... still meh ... we can do better by using ints instead of strings for principals -// "user.oc.grant.u:100000" is pretty neat, but we can still do better: base64 encode the int -// "user.oc.grant.u:6Jqg" but base64 always has at least 4 chars, maybe hex is better for smaller numbers -// well use 4 chars in addition to the ace: "user.oc.grant.u:////" = 65535 -> 18 chars +// +// "user.oc.grant.u:100000" is pretty neat, but we can still do better: base64 encode the int +// "user.oc.grant.u:6Jqg" but base64 always has at least 4 chars, maybe hex is better for smaller numbers +// well use 4 chars in addition to the ace: "user.oc.grant.u:////" = 65535 -> 18 chars +// // 4096/18 = 227 shares // still ... ext attrs for this are not infinite scale ... // so .. attach shares via fileid. @@ -95,8 +98,8 @@ import ( // // whatever ... 50 shares is good enough. If more is needed we can delegate to the metadata // if "user.oc.grant.M" is present look inside the metadata app. -// - if we cannot set an ace we might get an io error. -// in that case convert all shares to metadata and try to set "user.oc.grant.m" +// - if we cannot set an ace we might get an io error. +// in that case convert all shares to metadata and try to set "user.oc.grant.m" // // what about metadata like share creator, share time, expiry? // - creator is same as owner, but can be set diff --git a/pkg/storage/utils/decomposedfs/decomposedfs.go b/pkg/storage/utils/decomposedfs/decomposedfs.go index 427a429a74..eb2df7c734 100644 --- a/pkg/storage/utils/decomposedfs/decomposedfs.go +++ b/pkg/storage/utils/decomposedfs/decomposedfs.go @@ -47,12 +47,13 @@ import ( "github.com/cs3org/reva/pkg/storage/utils/decomposedfs/tree" "github.com/cs3org/reva/pkg/storage/utils/decomposedfs/xattrs" "github.com/cs3org/reva/pkg/storage/utils/templates" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" "github.com/pkg/errors" "github.com/pkg/xattr" ) +const tracerName = "decomposedfs" + // PermissionsChecker defines an interface for checking permissions on a Node type PermissionsChecker interface { AssemblePermissions(ctx context.Context, n *node.Node) (ap provider.ResourcePermissions, err error) @@ -440,9 +441,6 @@ func (fs *Decomposedfs) ListFolder(ctx context.Context, ref *provider.Reference, return } - ctx, span := rtrace.Provider.Tracer("decomposedfs").Start(ctx, "ListFolder") - defer span.End() - if !n.Exists { err = errtypes.NotFound(filepath.Join(n.ParentID, n.Name)) return diff --git a/pkg/storage/utils/decomposedfs/spaces.go b/pkg/storage/utils/decomposedfs/spaces.go index 4bbc05a2fc..5513182089 100644 --- a/pkg/storage/utils/decomposedfs/spaces.go +++ b/pkg/storage/utils/decomposedfs/spaces.go @@ -38,6 +38,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/storage/utils/decomposedfs/node" "github.com/cs3org/reva/pkg/storage/utils/decomposedfs/xattrs" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/google/uuid" "github.com/pkg/errors" @@ -51,6 +52,9 @@ const ( // CreateStorageSpace creates a storage space func (fs *Decomposedfs) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateStorageSpace") + defer span.End() + // spaces will be located by default in the root of the storage. r, err := fs.lu.RootNode(ctx) if err != nil { @@ -159,6 +163,9 @@ func (fs *Decomposedfs) CreateStorageSpace(ctx context.Context, req *provider.Cr // Spaces are persisted with symlinks in /spaces// pointing to ../../nodes/, the root node of the space // The spaceid is a concatenation of storageid + "!" + nodeid func (fs *Decomposedfs) ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter) ([]*provider.StorageSpace, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListStorageSpaces") + defer span.End() + // TODO check filters // TODO when a space symlink is broken delete the space for cleanup @@ -202,7 +209,7 @@ func (fs *Decomposedfs) ListStorageSpaces(ctx context.Context, filter []*provide return spaces, nil } - client, err := pool.GetGatewayServiceClient(pool.Endpoint(fs.o.GatewayAddr)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(fs.o.GatewayAddr)) if err != nil { return nil, err } @@ -265,6 +272,9 @@ func (fs *Decomposedfs) ListStorageSpaces(ctx context.Context, filter []*provide // UpdateStorageSpace updates a storage space func (fs *Decomposedfs) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateStorageSpace") + defer span.End() + space := req.StorageSpace _, spaceID, err := utils.SplitStorageSpaceID(space.Id.OpaqueId) @@ -325,6 +335,9 @@ func (fs *Decomposedfs) UpdateStorageSpace(ctx context.Context, req *provider.Up // Internally createHiddenSpaceFolder leverages the use of node.Child() to create a new node under the space root. // createHiddenSpaceFolder is just a contextual alias for node.Child() for ".spaces". func (fs *Decomposedfs) createHiddenSpaceFolder(ctx context.Context, r *node.Node) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "createHiddenSpaceFolder") + defer span.End() + hiddenSpace, err := r.Child(ctx, ".space") if err != nil { return err @@ -334,6 +347,9 @@ func (fs *Decomposedfs) createHiddenSpaceFolder(ctx context.Context, r *node.Nod } func (fs *Decomposedfs) createStorageSpace(ctx context.Context, spaceType, nodeID string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "createStorageSpace") + defer span.End() + // create space type dir if err := os.MkdirAll(filepath.Join(fs.o.Root, "spaces", spaceType), 0700); err != nil { return err @@ -354,6 +370,9 @@ func (fs *Decomposedfs) createStorageSpace(ctx context.Context, spaceType, nodeI } func (fs *Decomposedfs) storageSpaceFromNode(ctx context.Context, node *node.Node, nodePath, spaceType string, canListAllSpaces bool) (*provider.StorageSpace, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "storageSpaceFromNode") + defer span.End() + owner, err := node.Owner() if err != nil { return nil, err diff --git a/pkg/storage/utils/decomposedfs/testhelpers/helpers.go b/pkg/storage/utils/decomposedfs/testhelpers/helpers.go index 41ad8ac098..2128a75f05 100644 --- a/pkg/storage/utils/decomposedfs/testhelpers/helpers.go +++ b/pkg/storage/utils/decomposedfs/testhelpers/helpers.go @@ -56,9 +56,9 @@ type TestEnv struct { // NewTestEnv prepares a test environment on disk // The storage contains some directories and a file: // -// /dir1/ -// /dir1/file1 -// /dir1/subdir1/ +// /dir1/ +// /dir1/file1 +// /dir1/subdir1/ func NewTestEnv() (*TestEnv, error) { tmpRoot, err := helpers.TempDir("reva-unit-tests-*-root") if err != nil { diff --git a/pkg/storage/utils/eosfs/eosfs.go b/pkg/storage/utils/eosfs/eosfs.go index 5983d8ade3..340a2e27c3 100644 --- a/pkg/storage/utils/eosfs/eosfs.go +++ b/pkg/storage/utils/eosfs/eosfs.go @@ -57,10 +57,13 @@ import ( "github.com/cs3org/reva/pkg/storage/utils/chunking" "github.com/cs3org/reva/pkg/storage/utils/grants" "github.com/cs3org/reva/pkg/storage/utils/templates" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/pkg/utils" "github.com/pkg/errors" ) +const tracerName = "eosfs" + const ( refTargetAttrKey = "reva.target" ) @@ -265,11 +268,17 @@ func (fs *eosfs) userIDcacheWarmup() { } func (fs *eosfs) Shutdown(ctx context.Context) error { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "Shutdown") + defer span.End() + // TODO(labkode): in a grpc implementation we can close connections. return nil } func getUser(ctx context.Context) (*userpb.User, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getUser") + defer span.End() + u, ok := ctxpkg.ContextGetUser(ctx) if !ok { err := errors.Wrap(errtypes.UserRequired(""), "eosfs: error getting user from ctx") @@ -279,6 +288,9 @@ func getUser(ctx context.Context) (*userpb.User, error) { } func (fs *eosfs) getLayout(ctx context.Context) (layout string) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getLayout") + defer span.End() + if fs.conf.EnableHome { u, err := getUser(ctx) if err != nil { @@ -290,6 +302,9 @@ func (fs *eosfs) getLayout(ctx context.Context) (layout string) { } func (fs *eosfs) getInternalHome(ctx context.Context) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getInternalHome") + defer span.End() + if !fs.conf.EnableHome { return "", errtypes.NotSupported("eos: get home not supported") } @@ -305,6 +320,9 @@ func (fs *eosfs) getInternalHome(ctx context.Context) (string, error) { } func (fs *eosfs) wrapShadow(ctx context.Context, fn string) (internal string) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "wrapShadow") + defer span.End() + if fs.conf.EnableHome { layout, err := fs.getInternalHome(ctx) if err != nil { @@ -318,6 +336,9 @@ func (fs *eosfs) wrapShadow(ctx context.Context, fn string) (internal string) { } func (fs *eosfs) wrap(ctx context.Context, fn string) (internal string) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "wrap") + defer span.End() + if fs.conf.EnableHome { layout, err := fs.getInternalHome(ctx) if err != nil { @@ -333,6 +354,9 @@ func (fs *eosfs) wrap(ctx context.Context, fn string) (internal string) { } func (fs *eosfs) unwrap(ctx context.Context, internal string) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "unwrap") + defer span.End() + log := appctx.GetLogger(ctx) layout := fs.getLayout(ctx) ns, err := fs.getNsMatch(internal, []string{fs.conf.Namespace, fs.conf.ShadowNamespace}) @@ -364,6 +388,9 @@ func (fs *eosfs) getNsMatch(internal string, nss []string) (string, error) { } func (fs *eosfs) unwrapInternal(ctx context.Context, ns, np, layout string) (string, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "unwrapInternal") + defer span.End() + trim := path.Join(ns, layout) if !strings.HasPrefix(np, trim) { @@ -380,6 +407,9 @@ func (fs *eosfs) unwrapInternal(ctx context.Context, ns, np, layout string) (str } func (fs *eosfs) resolveRefForbidShareFolder(ctx context.Context, ref *provider.Reference) (string, eosclient.Authorization, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "resolveRefForbidShareFolder") + defer span.End() + p, err := fs.resolve(ctx, ref) if err != nil { return "", eosclient.Authorization{}, errors.Wrap(err, "eosfs: error resolving reference") @@ -402,6 +432,9 @@ func (fs *eosfs) resolveRefForbidShareFolder(ctx context.Context, ref *provider. } func (fs *eosfs) resolveRefAndGetAuth(ctx context.Context, ref *provider.Reference) (string, eosclient.Authorization, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "resolveRefAndGetAuth") + defer span.End() + p, err := fs.resolve(ctx, ref) if err != nil { return "", eosclient.Authorization{}, errors.Wrap(err, "eosfs: error resolving reference") @@ -422,6 +455,9 @@ func (fs *eosfs) resolveRefAndGetAuth(ctx context.Context, ref *provider.Referen // resolve takes in a request path or request id and returns the unwrapped path. func (fs *eosfs) resolve(ctx context.Context, ref *provider.Reference) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "resolve") + defer span.End() + if ref.ResourceId != nil { p, err := fs.getPath(ctx, ref.ResourceId) if err != nil { @@ -439,6 +475,9 @@ func (fs *eosfs) resolve(ctx context.Context, ref *provider.Reference) (string, } func (fs *eosfs) getPath(ctx context.Context, id *provider.ResourceId) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getPath") + defer span.End() + fid, err := strconv.ParseUint(id.OpaqueId, 10, 64) if err != nil { return "", fmt.Errorf("error converting string to int for eos fileid: %s", id.OpaqueId) @@ -458,20 +497,32 @@ func (fs *eosfs) getPath(ctx context.Context, id *provider.ResourceId) (string, } func (fs *eosfs) isShareFolder(ctx context.Context, p string) bool { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "isShareFolder") + defer span.End() + return strings.HasPrefix(p, fs.conf.ShareFolder) } func (fs *eosfs) isShareFolderRoot(ctx context.Context, p string) bool { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "isShareFolderRoot") + defer span.End() + return path.Clean(p) == fs.conf.ShareFolder } func (fs *eosfs) isShareFolderChild(ctx context.Context, p string) bool { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "isShareFolderChild") + defer span.End() + p = path.Clean(p) vals := strings.Split(p, fs.conf.ShareFolder+"/") return len(vals) > 1 && vals[1] != "" } func (fs *eosfs) GetPathByID(ctx context.Context, id *provider.ResourceId) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetPathByID") + defer span.End() + fid, err := strconv.ParseUint(id.OpaqueId, 10, 64) if err != nil { return "", errors.Wrap(err, "eosfs: error parsing fileid string") @@ -510,6 +561,9 @@ func (fs *eosfs) GetPathByID(ctx context.Context, id *provider.ResourceId) (stri } func (fs *eosfs) SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetArbitraryMetadata") + defer span.End() + if len(md.Metadata) == 0 { return errtypes.BadRequest("eosfs: no metadata set") } @@ -547,6 +601,9 @@ func (fs *eosfs) SetArbitraryMetadata(ctx context.Context, ref *provider.Referen } func (fs *eosfs) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UnsetArbitraryMetadata") + defer span.End() + if len(keys) == 0 { return errtypes.BadRequest("eosfs: no keys set") } @@ -576,6 +633,9 @@ func (fs *eosfs) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Refer } func (fs *eosfs) getLockExpiration(ctx context.Context, auth eosclient.Authorization, path string) (*types.Timestamp, bool, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getLockExpiration") + defer span.End() + expiration, err := fs.c.GetAttr(ctx, auth, "sys."+LockExpirationKey, path) if err != nil { // since the expiration is optional, if we do not find it in the attr @@ -598,6 +658,9 @@ func (fs *eosfs) getLockExpiration(ctx context.Context, auth eosclient.Authoriza } func (fs *eosfs) getLockContent(ctx context.Context, auth eosclient.Authorization, path string, expiration *types.Timestamp) (*provider.Lock, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getLockContent") + defer span.End() + t, err := fs.c.GetAttr(ctx, auth, "sys."+LockTypeKey, path) if err != nil { return nil, err @@ -630,6 +693,9 @@ func (fs *eosfs) getLockContent(ctx context.Context, auth eosclient.Authorizatio } func (fs *eosfs) removeLockAttrs(ctx context.Context, auth eosclient.Authorization, path string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "removeLockAttrs") + defer span.End() + err := fs.c.UnsetAttr(ctx, auth, &eosclient.Attribute{ Type: SystemAttr, Key: LockExpirationKey, @@ -662,6 +728,9 @@ func (fs *eosfs) removeLockAttrs(ctx context.Context, auth eosclient.Authorizati } func (fs *eosfs) getLock(ctx context.Context, auth eosclient.Authorization, user *userpb.User, path string, ref *provider.Reference) (*provider.Lock, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getLock") + defer span.End() + // the cs3apis require to have the read permission on the resource // to get the eventual lock. has, err := fs.userHasReadAccess(ctx, user, ref) @@ -696,6 +765,9 @@ func (fs *eosfs) getLock(ctx context.Context, auth eosclient.Authorization, user // GetLock returns an existing lock on the given reference func (fs *eosfs) GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetLock") + defer span.End() + path, err := fs.resolve(ctx, ref) if err != nil { return nil, errors.Wrap(err, "eosfs: error resolving reference") @@ -715,6 +787,9 @@ func (fs *eosfs) GetLock(ctx context.Context, ref *provider.Reference) (*provide } func (fs *eosfs) setLock(ctx context.Context, auth eosclient.Authorization, lock *provider.Lock, path string, check bool) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "setLock") + defer span.End() + encodedLock, err := encodeLock(lock) if err != nil { return errors.Wrap(err, "eosfs: error encoding lock") @@ -759,6 +834,9 @@ func (fs *eosfs) setLock(ctx context.Context, auth eosclient.Authorization, lock // SetLock puts a lock on the given reference func (fs *eosfs) SetLock(ctx context.Context, ref *provider.Reference, l *provider.Lock) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "SetLock") + defer span.End() + if l.Type == provider.LockType_LOCK_TYPE_SHARED { return errtypes.NotSupported("shared lock not yet implemented") } @@ -818,7 +896,10 @@ func (fs *eosfs) SetLock(ctx context.Context, ref *provider.Reference, l *provid } func (fs *eosfs) getUserFromID(ctx context.Context, userID *userpb.UserId) (*userpb.User, error) { - client, err := pool.GetGatewayServiceClient(pool.Endpoint(fs.conf.GatewaySvc)) + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getUserFromID") + defer span.End() + + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(fs.conf.GatewaySvc)) if err != nil { return nil, err } @@ -836,6 +917,9 @@ func (fs *eosfs) getUserFromID(ctx context.Context, userID *userpb.UserId) (*use } func (fs *eosfs) userHasWriteAccess(ctx context.Context, user *userpb.User, ref *provider.Reference) (bool, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "userHasWriteAccess") + defer span.End() + ctx = ctxpkg.ContextSetUser(ctx, user) resInfo, err := fs.GetMD(ctx, ref, nil) if err != nil { @@ -845,6 +929,9 @@ func (fs *eosfs) userHasWriteAccess(ctx context.Context, user *userpb.User, ref } func (fs *eosfs) userIDHasWriteAccess(ctx context.Context, userID *userpb.UserId, ref *provider.Reference) (bool, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "userIDHasWriteAccess") + defer span.End() + user, err := fs.getUserFromID(ctx, userID) if err != nil { return false, nil @@ -853,6 +940,9 @@ func (fs *eosfs) userIDHasWriteAccess(ctx context.Context, userID *userpb.UserId } func (fs *eosfs) userHasReadAccess(ctx context.Context, user *userpb.User, ref *provider.Reference) (bool, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "userHasReadAccess") + defer span.End() + ctx = ctxpkg.ContextSetUser(ctx, user) resInfo, err := fs.GetMD(ctx, ref, nil) if err != nil { @@ -871,6 +961,9 @@ func encodeLock(l *provider.Lock) (string, error) { // RefreshLock refreshes an existing lock on the given reference func (fs *eosfs) RefreshLock(ctx context.Context, ref *provider.Reference, newLock *provider.Lock, existingLockID string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RefreshLock") + defer span.End() + if newLock.Type == provider.LockType_LOCK_TYPE_SHARED { return errtypes.NotSupported("shared lock not yet implemented") } @@ -938,6 +1031,9 @@ func sameHolder(l1, l2 *provider.Lock) bool { // Unlock removes an existing lock from the given reference func (fs *eosfs) Unlock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Unlock") + defer span.End() + if lock.Type == provider.LockType_LOCK_TYPE_SHARED { return errtypes.NotSupported("shared lock not yet implemented") } @@ -991,6 +1087,9 @@ func (fs *eosfs) Unlock(ctx context.Context, ref *provider.Reference, lock *prov } func (fs *eosfs) AddGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "AddGrant") + defer span.End() + fn, auth, err := fs.resolveRefAndGetAuth(ctx, ref) if err != nil { return err @@ -1018,6 +1117,9 @@ func (fs *eosfs) AddGrant(ctx context.Context, ref *provider.Reference, g *provi } func (fs *eosfs) DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DenyGrant") + defer span.End() + fn, auth, err := fs.resolveRefAndGetAuth(ctx, ref) if err != nil { return err @@ -1049,6 +1151,9 @@ func (fs *eosfs) DenyGrant(ctx context.Context, ref *provider.Reference, g *prov } func (fs *eosfs) getEosACL(ctx context.Context, g *provider.Grant) (*acl.Entry, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getEosACL") + defer span.End() + permissions, err := grants.GetACLPerm(g.Permissions) if err != nil { return nil, err @@ -1087,6 +1192,9 @@ func (fs *eosfs) getEosACL(ctx context.Context, g *provider.Grant) (*acl.Entry, } func (fs *eosfs) RemoveGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RemoveGrant") + defer span.End() + eosACLType, err := grants.GetACLType(g.Grantee.Type) if err != nil { return err @@ -1134,10 +1242,16 @@ func (fs *eosfs) RemoveGrant(ctx context.Context, ref *provider.Reference, g *pr } func (fs *eosfs) UpdateGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateGrant") + defer span.End() + return fs.AddGrant(ctx, ref, g) } func (fs *eosfs) ListGrants(ctx context.Context, ref *provider.Reference) ([]*provider.Grant, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListGrants") + defer span.End() + fn, auth, err := fs.resolveRefAndGetAuth(ctx, ref) if err != nil { return nil, err @@ -1186,6 +1300,9 @@ func (fs *eosfs) ListGrants(ctx context.Context, ref *provider.Reference) ([]*pr } func (fs *eosfs) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetMD") + defer span.End() + log := appctx.GetLogger(ctx) log.Info().Msg("eosfs: get md for ref:" + ref.String()) @@ -1249,6 +1366,9 @@ func (fs *eosfs) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []st } func (fs *eosfs) getMDShareFolder(ctx context.Context, p string, mdKeys []string) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getMDShareFolder") + defer span.End() + fn := fs.wrapShadow(ctx, p) u, err := getUser(ctx) @@ -1274,6 +1394,9 @@ func (fs *eosfs) getMDShareFolder(ctx context.Context, p string, mdKeys []string } func (fs *eosfs) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys []string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListFolder") + defer span.End() + p, err := fs.resolve(ctx, ref) if err != nil { return nil, errors.Wrap(err, "eosfs: error resolving reference") @@ -1287,6 +1410,9 @@ func (fs *eosfs) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys } func (fs *eosfs) listWithHome(ctx context.Context, p string) ([]*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listWithHome") + defer span.End() + if fs.isShareFolderRoot(ctx, p) { return fs.listShareFolderRoot(ctx, p) } @@ -1300,6 +1426,9 @@ func (fs *eosfs) listWithHome(ctx context.Context, p string) ([]*provider.Resour } func (fs *eosfs) listWithNominalHome(ctx context.Context, p string) (finfos []*provider.ResourceInfo, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listWithNominalHome") + defer span.End() + log := appctx.GetLogger(ctx) fn := fs.wrap(ctx, p) @@ -1338,6 +1467,9 @@ func (fs *eosfs) listWithNominalHome(ctx context.Context, p string) (finfos []*p } func (fs *eosfs) listShareFolderRoot(ctx context.Context, p string) (finfos []*provider.ResourceInfo, err error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "listShareFolderRoot") + defer span.End() + fn := fs.wrapShadow(ctx, p) u, err := getUser(ctx) @@ -1374,10 +1506,16 @@ func (fs *eosfs) listShareFolderRoot(ctx context.Context, p string) (finfos []*p // CreateStorageSpace creates a storage space func (fs *eosfs) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateStorageSpace") + defer span.End() + return nil, fmt.Errorf("unimplemented: CreateStorageSpace") } func (fs *eosfs) GetQuota(ctx context.Context, ref *provider.Reference) (uint64, uint64, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "GetQuota") + defer span.End() + u, err := getUser(ctx) if err != nil { return 0, 0, errors.Wrap(err, "eosfs: no user in ctx") @@ -1403,6 +1541,9 @@ func (fs *eosfs) GetQuota(ctx context.Context, ref *provider.Reference) (uint64, } func (fs *eosfs) GetHome(ctx context.Context) (string, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "GetHome") + defer span.End() + if !fs.conf.EnableHome { return "", errtypes.NotSupported("eosfs: get home not supported") } @@ -1412,6 +1553,9 @@ func (fs *eosfs) GetHome(ctx context.Context) (string, error) { } func (fs *eosfs) createShadowHome(ctx context.Context) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "createShadowHome") + defer span.End() + u, err := getUser(ctx) if err != nil { return errors.Wrap(err, "eosfs: no user in ctx") @@ -1441,6 +1585,9 @@ func (fs *eosfs) createShadowHome(ctx context.Context) error { } func (fs *eosfs) createNominalHome(ctx context.Context) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "createNominalHome") + defer span.End() + home := fs.wrap(ctx, "/") u, err := getUser(ctx) @@ -1492,6 +1639,9 @@ func (fs *eosfs) createNominalHome(ctx context.Context) error { } func (fs *eosfs) CreateHome(ctx context.Context) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateHome") + defer span.End() + if !fs.conf.EnableHome { return errtypes.NotSupported("eosfs: create home not supported") } @@ -1508,6 +1658,9 @@ func (fs *eosfs) CreateHome(ctx context.Context) error { } func (fs *eosfs) createUserDir(ctx context.Context, u *userpb.User, path string, recursiveAttr bool) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "createUserDir") + defer span.End() + rootAuth, err := fs.getRootAuth(ctx) if err != nil { return nil @@ -1568,6 +1721,9 @@ func (fs *eosfs) createUserDir(ctx context.Context, u *userpb.User, path string, } func (fs *eosfs) CreateDir(ctx context.Context, ref *provider.Reference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateDir") + defer span.End() + log := appctx.GetLogger(ctx) p, err := fs.resolve(ctx, ref) if err != nil { @@ -1596,6 +1752,9 @@ func (fs *eosfs) CreateDir(ctx context.Context, ref *provider.Reference) error { // TouchFile as defined in the storage.FS interface func (fs *eosfs) TouchFile(ctx context.Context, ref *provider.Reference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "TouchFile") + defer span.End() + log := appctx.GetLogger(ctx) fn, auth, err := fs.resolveRefAndGetAuth(ctx, ref) @@ -1608,6 +1767,9 @@ func (fs *eosfs) TouchFile(ctx context.Context, ref *provider.Reference) error { } func (fs *eosfs) CreateReference(ctx context.Context, p string, targetURI *url.URL) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "CreateReference") + defer span.End() + // TODO(labkode): for the time being we only allow creating references // in the virtual share folder to not pollute the nominal user tree. if !fs.isShareFolder(ctx, p) { @@ -1656,6 +1818,9 @@ func (fs *eosfs) CreateReference(ctx context.Context, p string, targetURI *url.U } func (fs *eosfs) Delete(ctx context.Context, ref *provider.Reference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Delete") + defer span.End() + p, err := fs.resolve(ctx, ref) if err != nil { return errors.Wrap(err, "eosfs: error resolving reference") @@ -1680,6 +1845,9 @@ func (fs *eosfs) Delete(ctx context.Context, ref *provider.Reference) error { } func (fs *eosfs) deleteShadow(ctx context.Context, p string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "deleteShadow") + defer span.End() + if fs.isShareFolderRoot(ctx, p) { return errtypes.PermissionDenied("eosfs: cannot delete the virtual share folder") } @@ -1702,6 +1870,9 @@ func (fs *eosfs) deleteShadow(ctx context.Context, p string) error { } func (fs *eosfs) Move(ctx context.Context, oldRef, newRef *provider.Reference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Move") + defer span.End() + oldPath, err := fs.resolve(ctx, oldRef) if err != nil { return errors.Wrap(err, "eosfs: error resolving reference") @@ -1732,6 +1903,9 @@ func (fs *eosfs) Move(ctx context.Context, oldRef, newRef *provider.Reference) e } func (fs *eosfs) moveShadow(ctx context.Context, oldPath, newPath string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "moveShadow") + defer span.End() + if fs.isShareFolderRoot(ctx, oldPath) || fs.isShareFolderRoot(ctx, newPath) { return errtypes.PermissionDenied("eosfs: cannot move/rename the virtual share folder") } @@ -1760,6 +1934,9 @@ func (fs *eosfs) moveShadow(ctx context.Context, oldPath, newPath string) error } func (fs *eosfs) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "Download") + defer span.End() + fn, auth, err := fs.resolveRefForbidShareFolder(ctx, ref) if err != nil { return nil, err @@ -1769,6 +1946,9 @@ func (fs *eosfs) Download(ctx context.Context, ref *provider.Reference) (io.Read } func (fs *eosfs) ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListRevisions") + defer span.End() + var auth eosclient.Authorization var fn string var err error @@ -1812,6 +1992,9 @@ func (fs *eosfs) ListRevisions(ctx context.Context, ref *provider.Reference) ([] } func (fs *eosfs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DownloadRevision") + defer span.End() + var auth eosclient.Authorization var fn string var err error @@ -1845,6 +2028,9 @@ func (fs *eosfs) DownloadRevision(ctx context.Context, ref *provider.Reference, } func (fs *eosfs) RestoreRevision(ctx context.Context, ref *provider.Reference, revisionKey string) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreRevision") + defer span.End() + var auth eosclient.Authorization var fn string var err error @@ -1878,10 +2064,16 @@ func (fs *eosfs) RestoreRevision(ctx context.Context, ref *provider.Reference, r } func (fs *eosfs) PurgeRecycleItem(ctx context.Context, basePath, key, relativePath string) error { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "PurgeRecycleItem") + defer span.End() + return errtypes.NotSupported("eosfs: operation not supported") } func (fs *eosfs) EmptyRecycle(ctx context.Context) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "EmptyRecycle") + defer span.End() + u, err := getUser(ctx) if err != nil { return errors.Wrap(err, "eosfs: no user in ctx") @@ -1895,6 +2087,9 @@ func (fs *eosfs) EmptyRecycle(ctx context.Context) error { } func (fs *eosfs) ListRecycle(ctx context.Context, basePath, key, relativePath string) ([]*provider.RecycleItem, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "ListRecycle") + defer span.End() + var auth eosclient.Authorization if !fs.conf.EnableHome && fs.conf.AllowPathRecycleOperations && basePath != "/" { @@ -1946,6 +2141,9 @@ func (fs *eosfs) ListRecycle(ctx context.Context, basePath, key, relativePath st } func (fs *eosfs) RestoreRecycleItem(ctx context.Context, basePath, key, relativePath string, restoreRef *provider.Reference) error { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "RestoreRecycleItem") + defer span.End() + var auth eosclient.Authorization if !fs.conf.EnableHome && fs.conf.AllowPathRecycleOperations && basePath != "/" { @@ -1980,15 +2178,24 @@ func (fs *eosfs) RestoreRecycleItem(ctx context.Context, basePath, key, relative } func (fs *eosfs) ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter) ([]*provider.StorageSpace, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "ListStorageSpaces") + defer span.End() + return nil, errtypes.NotSupported("list storage spaces") } // UpdateStorageSpace updates a storage space func (fs *eosfs) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) { + _, span := tracing.SpanStartFromContext(ctx, tracerName, "UpdateStorageSpace") + defer span.End() + return nil, errtypes.NotSupported("update storage space") } func (fs *eosfs) convertToRecycleItem(ctx context.Context, eosDeletedItem *eosclient.DeletedEntry) (*provider.RecycleItem, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convertToRecycleItem") + defer span.End() + path, err := fs.unwrap(ctx, eosDeletedItem.RestorePath) if err != nil { return nil, err @@ -2009,6 +2216,9 @@ func (fs *eosfs) convertToRecycleItem(ctx context.Context, eosDeletedItem *eoscl } func (fs *eosfs) convertToRevision(ctx context.Context, eosFileInfo *eosclient.FileInfo) (*provider.FileVersion, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convertToRevision") + defer span.End() + md, err := fs.convertToResourceInfo(ctx, eosFileInfo) if err != nil { return nil, err @@ -2023,10 +2233,16 @@ func (fs *eosfs) convertToRevision(ctx context.Context, eosFileInfo *eosclient.F } func (fs *eosfs) convertToResourceInfo(ctx context.Context, eosFileInfo *eosclient.FileInfo) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convertToResourceInfo") + defer span.End() + return fs.convert(ctx, eosFileInfo) } func (fs *eosfs) convertToFileReference(ctx context.Context, eosFileInfo *eosclient.FileInfo) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convertToFileReference") + defer span.End() + info, err := fs.convert(ctx, eosFileInfo) if err != nil { return nil, err @@ -2042,6 +2258,9 @@ func (fs *eosfs) convertToFileReference(ctx context.Context, eosFileInfo *eoscli // permissionSet returns the permission set for the current user func (fs *eosfs) permissionSet(ctx context.Context, eosFileInfo *eosclient.FileInfo, owner *userpb.UserId) *provider.ResourcePermissions { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "permissionSet") + defer span.End() + u, ok := ctxpkg.ContextGetUser(ctx) if !ok || u.Id == nil { return &provider.ResourcePermissions{ @@ -2121,6 +2340,9 @@ func mergePermissions(l *provider.ResourcePermissions, r *provider.ResourcePermi } func (fs *eosfs) convert(ctx context.Context, eosFileInfo *eosclient.FileInfo) (*provider.ResourceInfo, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "convert") + defer span.End() + path, err := fs.unwrap(ctx, eosFileInfo.File) if err != nil { return nil, err @@ -2211,13 +2433,16 @@ func (fs *eosfs) extractUIDAndGID(u *userpb.User) (eosclient.Authorization, erro } func (fs *eosfs) getUIDGateway(ctx context.Context, u *userpb.UserId) (eosclient.Authorization, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getUIDGateway") + defer span.End() + log := appctx.GetLogger(ctx) if userIDInterface, err := fs.userIDCache.Get(u.OpaqueId); err == nil { log.Debug().Msg("eosfs: found cached user " + u.OpaqueId) return fs.extractUIDAndGID(userIDInterface.(*userpb.User)) } - client, err := pool.GetGatewayServiceClient(pool.Endpoint(fs.conf.GatewaySvc)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(fs.conf.GatewaySvc)) if err != nil { return eosclient.Authorization{}, errors.Wrap(err, "eosfs: error getting gateway grpc client") } @@ -2239,6 +2464,9 @@ func (fs *eosfs) getUIDGateway(ctx context.Context, u *userpb.UserId) (eosclient } func (fs *eosfs) getUserIDGateway(ctx context.Context, uid string) (*userpb.UserId, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getUserIDGateway") + defer span.End() + log := appctx.GetLogger(ctx) // Handle the case of root if uid == "0" { @@ -2251,7 +2479,7 @@ func (fs *eosfs) getUserIDGateway(ctx context.Context, uid string) (*userpb.User } log.Debug().Msg("eosfs: retrieving user from gateway for uid " + uid) - client, err := pool.GetGatewayServiceClient(pool.Endpoint(fs.conf.GatewaySvc)) + client, err := pool.GetGatewayServiceClient(ctx, pool.Endpoint(fs.conf.GatewaySvc)) if err != nil { return nil, errors.Wrap(err, "eosfs: error getting gateway grpc client") } @@ -2278,6 +2506,9 @@ func (fs *eosfs) getUserIDGateway(ctx context.Context, uid string) (*userpb.User } func (fs *eosfs) getUserAuth(ctx context.Context, u *userpb.User, fn string) (eosclient.Authorization, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getUserAuth") + defer span.End() + if fs.conf.ForceSingleUserMode { if fs.singleUserAuth.Role.UID != "" && fs.singleUserAuth.Role.GID != "" { return fs.singleUserAuth, nil @@ -2296,6 +2527,9 @@ func (fs *eosfs) getUserAuth(ctx context.Context, u *userpb.User, fn string) (eo } func (fs *eosfs) getEOSToken(ctx context.Context, u *userpb.User, fn string) (eosclient.Authorization, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getEOSToken") + defer span.End() + if fn == "" { return eosclient.Authorization{}, errtypes.BadRequest("eosfs: path cannot be empty") } @@ -2348,6 +2582,9 @@ func (fs *eosfs) getEOSToken(ctx context.Context, u *userpb.User, fn string) (eo } func (fs *eosfs) getRootAuth(ctx context.Context) (eosclient.Authorization, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "getRootAuth") + defer span.End() + if fs.conf.ForceSingleUserMode { if fs.singleUserAuth.Role.UID != "" && fs.singleUserAuth.Role.GID != "" { return fs.singleUserAuth, nil diff --git a/pkg/token/manager/demo/demo.go b/pkg/token/manager/demo/demo.go index a200de0898..b02bc1460c 100644 --- a/pkg/token/manager/demo/demo.go +++ b/pkg/token/manager/demo/demo.go @@ -28,9 +28,12 @@ import ( user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" "github.com/cs3org/reva/pkg/token" "github.com/cs3org/reva/pkg/token/manager/registry" + "github.com/cs3org/reva/pkg/tracing" "github.com/pkg/errors" ) +const tracerName = "demo" + func init() { registry.Register("demo", New) } @@ -49,6 +52,9 @@ type claims struct { } func (m *manager) MintToken(ctx context.Context, u *user.User, scope map[string]*auth.Scope) (string, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "MintToken") + defer span.End() + token, err := encode(&claims{u, scope}) if err != nil { return "", errors.Wrap(err, "error encoding user") @@ -57,6 +63,9 @@ func (m *manager) MintToken(ctx context.Context, u *user.User, scope map[string] } func (m *manager) DismantleToken(ctx context.Context, token string) (*user.User, map[string]*auth.Scope, error) { + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "DismantleToken") + defer span.End() + c, err := decode(token) if err != nil { return nil, nil, errors.Wrap(err, "error decoding claims") diff --git a/pkg/trace/trace.go b/pkg/trace/trace.go deleted file mode 100644 index a20a9994ec..0000000000 --- a/pkg/trace/trace.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2018-2021 CERN -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// In applying this license, CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -package trace - -import ( - "fmt" - "net/url" - "strings" - - "go.opentelemetry.io/otel/exporters/jaeger" - "go.opentelemetry.io/otel/propagation" - "go.opentelemetry.io/otel/sdk/resource" - sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.4.0" - "go.opentelemetry.io/otel/trace" -) - -var ( - // Propagator is the default Reva propagator. - Propagator = propagation.NewCompositeTextMapPropagator(propagation.Baggage{}, propagation.TraceContext{}) - - // Provider is the default Reva tracer provider. - Provider = trace.NewNoopTracerProvider() -) - -// SetTraceProvider sets the TracerProvider at a package level. -func SetTraceProvider(collectorEndpoint string, agentEndpoint, serviceName string) { - // default to 'reva' as service name if not set - if serviceName == "" { - serviceName = "reva" - } - - var exp *jaeger.Exporter - var err error - - if agentEndpoint != "" { - var agentHost string - var agentPort string - - agentHost, agentPort, err = parseAgentConfig(agentEndpoint) - if err != nil { - panic(err) - } - - exp, err = jaeger.New( - jaeger.WithAgentEndpoint( - jaeger.WithAgentHost(agentHost), - jaeger.WithAgentPort(agentPort), - ), - ) - if err != nil { - panic(err) - } - } - - if collectorEndpoint != "" { - exp, err = jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(collectorEndpoint))) - if err != nil { - panic(err) - } - } - - Provider = sdktrace.NewTracerProvider( - sdktrace.WithBatcher(exp), - sdktrace.WithResource(resource.NewWithAttributes( - semconv.SchemaURL, - semconv.ServiceNameKey.String(serviceName), - )), - ) -} - -func parseAgentConfig(ae string) (string, string, error) { - u, err := url.Parse(ae) - // as per url.go: - // [...] Trying to parse a hostname and path - // without a scheme is invalid but may not necessarily return an - // error, due to parsing ambiguities. - if err == nil && u.Hostname() != "" && u.Port() != "" { - return u.Hostname(), u.Port(), nil - } - - p := strings.Split(ae, ":") - if len(p) != 2 { - return "", "", fmt.Errorf(fmt.Sprintf("invalid agent endpoint `%s`. expected format: `hostname:port`", ae)) - } - - switch { - case p[0] == "" && p[1] == "": // case ae = ":" - return "", "", fmt.Errorf(fmt.Sprintf("invalid agent endpoint `%s`. expected format: `hostname:port`", ae)) - case p[0] == "": - return "", "", fmt.Errorf(fmt.Sprintf("invalid agent endpoint `%s`. expected format: `hostname:port`", ae)) - } - return p[0], p[1], nil -} diff --git a/pkg/tracing/config.go b/pkg/tracing/config.go new file mode 100644 index 0000000000..ae1546ac82 --- /dev/null +++ b/pkg/tracing/config.go @@ -0,0 +1,35 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package tracing + +import ( + "github.com/mitchellh/mapstructure" +) + +type Config struct { + Agent string `mapstructure:"agent"` + Collector string `mapstructure:"collector"` +} + +func newConfig(v interface{}) (*Config, error) { + log.Info().Msg("decoding configuration") + c := &Config{} + err := mapstructure.Decode(v, c) + return c, err +} diff --git a/pkg/tracing/grpc.go b/pkg/tracing/grpc.go new file mode 100644 index 0000000000..eae05d03f0 --- /dev/null +++ b/pkg/tracing/grpc.go @@ -0,0 +1,95 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package tracing + +import ( + "context" + + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "go.opentelemetry.io/otel/trace" + "google.golang.org/grpc" +) + +type GrpcMiddlewarer interface { + SetInterceptors(name string) + UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) + StreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error +} + +type GrpcMiddleware struct { + unaryServerInterceptor grpc.UnaryServerInterceptor + streamServerInterceptor grpc.StreamServerInterceptor +} + +func (m *GrpcMiddleware) SetInterceptors(name string) { + log.Info().Msgf("setting interceptors for service \"%s\"", name) + tp := tr.tracerProvider(name) + m.unaryServerInterceptor = otelgrpc.UnaryServerInterceptor(otelgrpc.WithTracerProvider(tp), otelgrpc.WithPropagators(tr.prop)) + m.streamServerInterceptor = otelgrpc.StreamServerInterceptor(otelgrpc.WithTracerProvider(tp), otelgrpc.WithPropagators(tr.prop)) +} + +func (m *GrpcMiddleware) UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + if m.unaryServerInterceptor != nil { + return m.unaryServerInterceptor(ctx, req, info, handler) + } + return handler(ctx, req) +} + +func (m *GrpcMiddleware) StreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + if m.streamServerInterceptor != nil { + return m.streamServerInterceptor(srv, ss, info, handler) + } + return handler(srv, ss) +} + +func UnaryServerInterceptor() grpc.UnaryServerInterceptor { + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + if m, ok := info.Server.(GrpcMiddlewarer); ok { + return m.UnaryServerInterceptor(ctx, req, info, handler) + } + return handler(ctx, req) + } +} + +func StreamServerInterceptor() grpc.StreamServerInterceptor { + return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + if m, ok := srv.(GrpcMiddlewarer); ok { + return m.StreamServerInterceptor(srv, ss, info, handler) + } + return handler(srv, ss) + } +} + +func UnaryClientInterceptor() grpc.UnaryClientInterceptor { + return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + span := trace.SpanFromContext(ctx) + tp := span.TracerProvider() + interceptor := otelgrpc.UnaryClientInterceptor(otelgrpc.WithTracerProvider(tp), otelgrpc.WithPropagators(tr.prop)) + return interceptor(ctx, method, req, reply, cc, invoker, opts...) + } +} + +func StreamClientInterceptor() grpc.StreamClientInterceptor { + return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { + span := trace.SpanFromContext(ctx) + tp := span.TracerProvider() + interceptor := otelgrpc.StreamClientInterceptor(otelgrpc.WithTracerProvider(tp), otelgrpc.WithPropagators(tr.prop)) + return interceptor(ctx, desc, cc, method, streamer, opts...) + } +} diff --git a/pkg/tracing/http.go b/pkg/tracing/http.go new file mode 100644 index 0000000000..146db15bbb --- /dev/null +++ b/pkg/tracing/http.go @@ -0,0 +1,82 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package tracing + +import ( + "net/http" + + "github.com/cs3org/reva/pkg/rhttp/utils" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" +) + +type HttpMiddlewarer interface { + SetMiddleware(name string, prefix string) + Middleware(h http.Handler) http.Handler +} + +type HttpMiddleware struct { + middleware func(http.Handler) http.Handler +} + +func (m *HttpMiddleware) SetMiddleware(name string, prefix string) { + m.middleware = func(h http.Handler) http.Handler { + return otelhttp.NewHandler(h, prefix, + otelhttp.WithTracerProvider(tr.tracerProvider(name)), + otelhttp.WithPropagators(tr.prop), + ) + } +} + +func (m *HttpMiddleware) Middleware(h http.Handler) http.Handler { + return m.middleware(h) +} + +func Middleware(h http.Handler, ms map[string]HttpMiddlewarer) http.Handler { + handlers := map[string]http.Handler{} + for prefix, m := range ms { + handlers[prefix] = m.Middleware(h) + } + + noopHandler := otelhttp.NewHandler(h, "", + otelhttp.WithTracerProvider(tr.noop), + otelhttp.WithPropagators(tr.prop), + ) + + handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if h, ok := handlers[r.URL.Path]; ok { + h.ServeHTTP(w, r) + return + } + + var match string + for prefix := range handlers { + if utils.UrlHasPrefix(r.URL.Path, prefix) && len(prefix) > len(match) { + match = prefix + } + } + + if h, ok := handlers[match]; ok { + h.ServeHTTP(w, r) + return + } + + noopHandler.ServeHTTP(w, r) + }) + return http.Handler(handlerFunc) +} diff --git a/pkg/tracing/init.go b/pkg/tracing/init.go new file mode 100644 index 0000000000..fd633a80f0 --- /dev/null +++ b/pkg/tracing/init.go @@ -0,0 +1,112 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package tracing + +import ( + "fmt" + "net" + "sync" + + jaegerExporter "go.opentelemetry.io/otel/exporters/jaeger" +) + +var initOnce sync.Once + +func Init(v interface{}, l ...LoggerOption) { + initOnce.Do(func() { + initLogger(l...) + log.Info().Msg("initializing tracing") + + c, err := newConfig(v) + if err != nil { + log.Error().Err(err).Msgf("error initializing tracing") + return + } + + var endpointOption jaegerExporter.EndpointOption + if c.Collector != "" && c.Agent != "" { + err := fmt.Errorf("more than one tracing endpoint option provided - agent: \"%s\", collector: \"%s\"", c.Agent, c.Collector) + log.Error().Err(err).Msg("error initializing tracing") + return + } else if c.Agent != "" { + // Endpoint option to create a Jaeger exporter that sends spans to the Jaeger Agent + // https://pkg.go.dev/go.opentelemetry.io/otel/exporters/jaeger#WithAgentEndpoint + endpointOption, err = withAgentEndpoint(c.Agent) + if err != nil { + log.Error().Err(err).Msgf("error initializing tracing") + return + } + } else if c.Collector != "" { + // Endpoint option to create a Jaeger exporter that sends spans + // directly to the Jaeger Collector (without a Jaeger Agent in the middle) + // https://pkg.go.dev/go.opentelemetry.io/otel/exporters/jaeger#WithCollectorEndpoint + endpointOption = withCollectorEndpoint(c.Collector) + } else { + log.Warn().Msg("tracing disabled - using NoopExporter") + return + } + + log.Info().Msg("creating jaegerExporter") + exp, err := jaegerExporter.New(endpointOption) + if err != nil { + log.Error().Err(err).Msgf("error initializing tracing") + return + } + tr.exp = exp + }) +} + +func withAgentEndpoint(agent string) (jaegerExporter.EndpointOption, error) { + log.Info().Msgf("creating jaegerExporter.EndpointOption for agent \"%s\"", agent) + + var options []jaegerExporter.AgentEndpointOption + if agent != "" { + host, port, err := net.SplitHostPort(agent) + if err != nil { + log.Error().Err(err).Msgf("error creating jaegerExporter.EndpointOption for agent \"%s\"", agent) + return nil, err + } + // If the Jaeger Agent host address is not provided, "localhost" is used by default + // https://github.com/open-telemetry/opentelemetry-go/blob/a50cf6aadd582f9760c578e2c4b5230b6c30913d/exporters/jaeger/uploader.go#L61 + if host != "" { + option := jaegerExporter.WithAgentHost(host) + options = append(options, option) + } + // If the Jaeger Agent host port is not provided, "6831" is used by default + // https://github.com/open-telemetry/opentelemetry-go/blob/a50cf6aadd582f9760c578e2c4b5230b6c30913d/exporters/jaeger/uploader.go#L62 + if port != "" { + option := jaegerExporter.WithAgentPort(port) + options = append(options, option) + } + } + return jaegerExporter.WithAgentEndpoint(options...), nil +} + +func withCollectorEndpoint(collector string) jaegerExporter.EndpointOption { + log.Info().Msgf("creating jaegerExporter.EndpointOption for collector \"%s\"", collector) + + var options []jaegerExporter.CollectorEndpointOption + // If the Jaeger Collector URL is not provided, "http://localhost:14268/api/traces" is used by default + // https://pkg.go.dev/go.opentelemetry.io/otel/exporters/jaeger#WithCollectorEndpoint + if collector != "" { + option := jaegerExporter.WithEndpoint(collector) + options = append(options, option) + } + return jaegerExporter.WithCollectorEndpoint(options...) +} diff --git a/pkg/tracing/logger.go b/pkg/tracing/logger.go new file mode 100644 index 0000000000..32d2d51cbf --- /dev/null +++ b/pkg/tracing/logger.go @@ -0,0 +1,38 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package tracing + +import "github.com/rs/zerolog" + +var log = zerolog.Nop() + +type LoggerOption func() + +func WithLogger(l zerolog.Logger) LoggerOption { + return func() { + l.Info().Msg("setting logger") + log = l + } +} + +func initLogger(opts ...LoggerOption) { + for _, opt := range opts { + opt() + } +} diff --git a/pkg/tracing/span.go b/pkg/tracing/span.go new file mode 100644 index 0000000000..d4b4b23e09 --- /dev/null +++ b/pkg/tracing/span.go @@ -0,0 +1,53 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package tracing + +import ( + "context" + "net/http" + "sync" + + "go.opentelemetry.io/otel/trace" +) + +var mu sync.Mutex + +func spanStart(ctx context.Context, tp trace.TracerProvider, tracerName string, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { + mu.Lock() + defer mu.Unlock() + return tp.Tracer(tracerName).Start(ctx, spanName, opts...) +} + +func SpanStartFromContext(ctx context.Context, tracerName string, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { + span := trace.SpanFromContext(ctx) + tp := span.TracerProvider() + return spanStart(ctx, tp, tracerName, spanName, opts...) +} + +func SpanStartFromRequest(r *http.Request, tracerName string, spanName string, opts ...trace.SpanStartOption) (*http.Request, trace.Span) { + ctx := r.Context() + ctx, span := SpanStartFromContext(ctx, tracerName, spanName, opts...) + r = r.WithContext(ctx) + return r, span +} + +func SpanStart(ctx context.Context, serviceName string, tracerName string, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { + tp := tr.tracerProvider(serviceName) + return spanStart(ctx, tp, tracerName, spanName, opts...) +} diff --git a/pkg/tracing/tracing.go b/pkg/tracing/tracing.go new file mode 100644 index 0000000000..4c1c480ed8 --- /dev/null +++ b/pkg/tracing/tracing.go @@ -0,0 +1,88 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package tracing + +import ( + "os" + "sync" + + jaegerPropagator "go.opentelemetry.io/contrib/propagators/jaeger" + "go.opentelemetry.io/otel/sdk/resource" + tracesdk "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/sdk/trace/tracetest" + semconv "go.opentelemetry.io/otel/semconv/v1.10.0" + "go.opentelemetry.io/otel/trace" +) + +var tr *tracing + +type tracing struct { + exp tracesdk.SpanExporter + prop jaegerPropagator.Jaeger + noop trace.TracerProvider + reg sync.Map + mux sync.Mutex +} + +func init() { + tr = &tracing{ + noop: trace.NewNoopTracerProvider(), + exp: tracetest.NewNoopExporter(), + prop: jaegerPropagator.Jaeger{}, + } +} + +func (t *tracing) tracerProvider(name string) trace.TracerProvider { + t.mux.Lock() + defer t.mux.Unlock() + + if value, ok := t.reg.Load(name); ok { + if tp, ok := value.(trace.TracerProvider); ok { + return tp + } + } + + var tp = t.noop + + hostname, err := os.Hostname() + if err != nil { + t.reg.Store(name, tp) + return tp + } + + r, err := resource.Merge( + resource.Default(), + resource.NewWithAttributes( + semconv.SchemaURL, + semconv.ServiceNameKey.String(name), + semconv.HostNameKey.String(hostname), + ), + ) + if err != nil { + t.reg.Store(name, tp) + return tp + } + + tp = tracesdk.NewTracerProvider( + tracesdk.WithBatcher(t.exp), + tracesdk.WithResource(r), + ) + t.reg.Store(name, tp) + return tp +} diff --git a/pkg/utils/resourceid/owncloud_test.go b/pkg/utils/resourceid/owncloud_test.go index d23574ef58..8c8f928519 100644 --- a/pkg/utils/resourceid/owncloud_test.go +++ b/pkg/utils/resourceid/owncloud_test.go @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/tests/integration/grpc/storageprovider_test.go b/tests/integration/grpc/storageprovider_test.go index 5655369830..103026d9a8 100644 --- a/tests/integration/grpc/storageprovider_test.go +++ b/tests/integration/grpc/storageprovider_test.go @@ -33,6 +33,7 @@ import ( "github.com/cs3org/reva/pkg/storage/fs/ocis" "github.com/cs3org/reva/pkg/storage/fs/owncloud" jwt "github.com/cs3org/reva/pkg/token/manager/jwt" + "github.com/cs3org/reva/pkg/tracing" "github.com/cs3org/reva/tests/helpers" . "github.com/onsi/ginkgo" @@ -77,6 +78,8 @@ var _ = Describe("storage providers", func() { JustBeforeEach(func() { var err error ctx = context.Background() + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "JustBeforeEach") + defer span.End() // Add auth token tokenManager, err := jwt.New(map[string]interface{}{"secret": "changemeplease"}) @@ -91,7 +94,7 @@ var _ = Describe("storage providers", func() { revads, err = startRevads(dependencies, variables) Expect(err).ToNot(HaveOccurred()) - serviceClient, err = pool.GetStorageProviderServiceClient(pool.Endpoint(revads["storage"].GrpcAddress)) + serviceClient, err = pool.GetStorageProviderServiceClient(ctx, pool.Endpoint(revads["storage"].GrpcAddress)) Expect(err).ToNot(HaveOccurred()) }) diff --git a/tests/integration/grpc/userprovider_test.go b/tests/integration/grpc/userprovider_test.go index 14af27fde2..78693e2a16 100644 --- a/tests/integration/grpc/userprovider_test.go +++ b/tests/integration/grpc/userprovider_test.go @@ -27,12 +27,15 @@ import ( ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" jwt "github.com/cs3org/reva/pkg/token/manager/jwt" + "github.com/cs3org/reva/pkg/tracing" "google.golang.org/grpc/metadata" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) +const tracerName = "grpc_test" + var _ = Describe("user providers", func() { var ( dependencies map[string]string @@ -47,6 +50,8 @@ var _ = Describe("user providers", func() { JustBeforeEach(func() { var err error ctx = context.Background() + ctx, span := tracing.SpanStartFromContext(ctx, tracerName, "JustBeforeEach") + defer span.End() // Add auth token user := &userpb.User{ @@ -68,7 +73,7 @@ var _ = Describe("user providers", func() { revads, err = startRevads(dependencies, map[string]string{}) Expect(err).ToNot(HaveOccurred()) - serviceClient, err = pool.GetUserProviderServiceClient(pool.Endpoint(revads["users"].GrpcAddress)) + serviceClient, err = pool.GetUserProviderServiceClient(ctx, pool.Endpoint(revads["users"].GrpcAddress)) Expect(err).ToNot(HaveOccurred()) })