From 02cfd4664861848a97ee694304a340a8c8febe35 Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Mon, 29 Jul 2024 11:17:20 +0300 Subject: [PATCH] Add go traces regions and tasks Signed-off-by: Alex Vanin --- api/handler/put.go | 7 ++++++ api/middleware/auth.go | 10 ++++++++ api/middleware/policy.go | 4 ++++ api/middleware/tracing.go | 7 ++++++ api/router.go | 9 ++++++++ internal/frostfs/frostfs.go | 28 +++++++++++++++++++++++ internal/frostfs/services/pool_wrapper.go | 22 ++++++++++++++++++ 7 files changed, 87 insertions(+) diff --git a/api/handler/put.go b/api/handler/put.go index 94cc0f35..bed8f57f 100644 --- a/api/handler/put.go +++ b/api/handler/put.go @@ -12,6 +12,7 @@ import ( "net" "net/http" "net/url" + "runtime/trace" "strconv" "strings" "time" @@ -182,6 +183,12 @@ type createBucketParams struct { } func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) { + if trace.IsEnabled() { + pctx, task := trace.NewTask(r.Context(), "PutObjectHandler") + defer task.End() + r = r.WithContext(pctx) + } + var ( err error cannedACLStatus = aclHeadersStatus(r) diff --git a/api/middleware/auth.go b/api/middleware/auth.go index c5318ca8..a92b33d4 100644 --- a/api/middleware/auth.go +++ b/api/middleware/auth.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "runtime/trace" "time" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" @@ -48,6 +49,8 @@ var ErrNoAuthorizationHeader = errors.New("no authorization header") func Auth(center Center, log *zap.Logger) Func { return func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + reg := trace.StartRegion(r.Context(), "handler:auth") + ctx := r.Context() reqInfo := GetReqInfo(ctx) reqInfo.User = "anon" @@ -64,6 +67,7 @@ func Auth(center Center, log *zap.Logger) Func { if _, wrErr := WriteErrorResponse(w, GetReqInfo(r.Context()), err); wrErr != nil { reqLogOrDefault(ctx, log).Error(logs.FailedToWriteResponse, zap.Error(wrErr)) } + reg.End() return } } else { @@ -75,6 +79,8 @@ func Auth(center Center, log *zap.Logger) Func { reqLogOrDefault(ctx, log).Debug(logs.SuccessfulAuth, zap.String("accessKeyID", box.AuthHeaders.AccessKeyID)) } + reg.End() + h.ServeHTTP(w, r.WithContext(ctx)) }) } @@ -87,11 +93,13 @@ type FrostFSIDValidator interface { func FrostfsIDValidation(frostfsID FrostFSIDValidator, log *zap.Logger) Func { return func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + reg := trace.StartRegion(r.Context(), "handler:ffsid") ctx := r.Context() bd, err := GetBoxData(ctx) if err != nil || bd.Gate.BearerToken == nil { reqLogOrDefault(ctx, log).Debug(logs.AnonRequestSkipFrostfsIDValidation) h.ServeHTTP(w, r) + reg.End() return } @@ -100,9 +108,11 @@ func FrostfsIDValidation(frostfsID FrostFSIDValidator, log *zap.Logger) Func { if _, wrErr := WriteErrorResponse(w, GetReqInfo(r.Context()), err); wrErr != nil { reqLogOrDefault(ctx, log).Error(logs.FailedToWriteResponse, zap.Error(wrErr)) } + reg.End() return } + reg.End() h.ServeHTTP(w, r) }) } diff --git a/api/middleware/policy.go b/api/middleware/policy.go index eaf9ffe8..22a9d323 100644 --- a/api/middleware/policy.go +++ b/api/middleware/policy.go @@ -8,6 +8,7 @@ import ( "io" "net/http" "net/url" + "runtime/trace" "strings" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" @@ -83,6 +84,7 @@ type PolicyConfig struct { func PolicyCheck(cfg PolicyConfig) Func { return func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + reg := trace.StartRegion(r.Context(), "handler:policy") ctx := r.Context() if err := policyCheck(r, cfg); err != nil { reqLogOrDefault(ctx, cfg.Log).Error(logs.PolicyValidationFailed, zap.Error(err)) @@ -90,9 +92,11 @@ func PolicyCheck(cfg PolicyConfig) Func { if _, wrErr := WriteErrorResponse(w, GetReqInfo(ctx), err); wrErr != nil { reqLogOrDefault(ctx, cfg.Log).Error(logs.FailedToWriteResponse, zap.Error(wrErr)) } + reg.End() return } + reg.End() h.ServeHTTP(w, r) }) } diff --git a/api/middleware/tracing.go b/api/middleware/tracing.go index 7597700e..2c268481 100644 --- a/api/middleware/tracing.go +++ b/api/middleware/tracing.go @@ -3,6 +3,7 @@ package middleware import ( "context" "net/http" + gotrace "runtime/trace" "sync" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -16,6 +17,12 @@ import ( func Tracing() Func { return func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if gotrace.IsEnabled() { + pctx, task := gotrace.NewTask(r.Context(), "request") + defer task.End() + r = r.WithContext(pctx) + } + appCtx, span := StartHTTPServerSpan(r, "REQUEST S3") reqInfo := GetReqInfo(r.Context()) reqInfo.TraceID = span.SpanContext().TraceID().String() diff --git a/api/router.go b/api/router.go index 0f86e2e5..20e9bf36 100644 --- a/api/router.go +++ b/api/router.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "runtime/trace" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" @@ -154,6 +155,14 @@ func NewRouter(cfg Config) *chi.Mux { })) defaultRouter := chi.NewRouter() + defaultRouter.Use(func(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + reg := trace.StartRegion(r.Context(), "handler:s3") + defer reg.End() + handler.ServeHTTP(w, r) + }) + }) + defaultRouter.Mount(fmt.Sprintf("/{%s}", s3middleware.BucketURLPrm), bucketRouter(cfg.Handler, cfg.Log)) defaultRouter.Get("/", named("ListBuckets", cfg.Handler.ListBucketsHandler)) attachErrorHandler(defaultRouter) diff --git a/internal/frostfs/frostfs.go b/internal/frostfs/frostfs.go index af2f5368..5f43b988 100644 --- a/internal/frostfs/frostfs.go +++ b/internal/frostfs/frostfs.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "math" + "runtime/trace" "strconv" "time" @@ -53,6 +54,9 @@ func NewFrostFS(p *pool.Pool, key *keys.PrivateKey) *FrostFS { // TimeToEpoch implements frostfs.FrostFS interface method. func (x *FrostFS) TimeToEpoch(ctx context.Context, now, futureTime time.Time) (uint64, uint64, error) { + reg := trace.StartRegion(ctx, "ffs:TimeToEpoch") + defer reg.End() + dur := futureTime.Sub(now) if dur < 0 { return 0, 0, fmt.Errorf("time '%s' must be in the future (after %s)", @@ -89,6 +93,9 @@ func (x *FrostFS) TimeToEpoch(ctx context.Context, now, futureTime time.Time) (u // Container implements frostfs.FrostFS interface method. func (x *FrostFS) Container(ctx context.Context, layerPrm layer.PrmContainer) (*container.Container, error) { + reg := trace.StartRegion(ctx, "ffs:Container") + defer reg.End() + prm := pool.PrmContainerGet{ ContainerID: layerPrm.ContainerID, Session: layerPrm.SessionToken, @@ -104,6 +111,9 @@ func (x *FrostFS) Container(ctx context.Context, layerPrm layer.PrmContainer) (* // CreateContainer implements frostfs.FrostFS interface method. func (x *FrostFS) CreateContainer(ctx context.Context, prm layer.PrmContainerCreate) (*layer.ContainerCreateResult, error) { + reg := trace.StartRegion(ctx, "ffs:CreateContainer") + defer reg.End() + var cnr container.Container cnr.Init() cnr.SetPlacementPolicy(prm.Policy) @@ -152,6 +162,9 @@ func (x *FrostFS) CreateContainer(ctx context.Context, prm layer.PrmContainerCre // UserContainers implements frostfs.FrostFS interface method. func (x *FrostFS) UserContainers(ctx context.Context, layerPrm layer.PrmUserContainers) ([]cid.ID, error) { + reg := trace.StartRegion(ctx, "ffs:UserContainers") + defer reg.End() + prm := pool.PrmContainerList{ OwnerID: layerPrm.UserID, Session: layerPrm.SessionToken, @@ -163,6 +176,9 @@ func (x *FrostFS) UserContainers(ctx context.Context, layerPrm layer.PrmUserCont // DeleteContainer implements frostfs.FrostFS interface method. func (x *FrostFS) DeleteContainer(ctx context.Context, id cid.ID, token *session.Container) error { + reg := trace.StartRegion(ctx, "ffs:DeleteContainer") + defer reg.End() + prm := pool.PrmContainerDelete{ContainerID: id, Session: token, WaitParams: &x.await} err := x.pool.DeleteContainer(ctx, prm) @@ -171,6 +187,9 @@ func (x *FrostFS) DeleteContainer(ctx context.Context, id cid.ID, token *session // CreateObject implements frostfs.FrostFS interface method. func (x *FrostFS) CreateObject(ctx context.Context, prm layer.PrmObjectCreate) (oid.ID, error) { + reg := trace.StartRegion(ctx, "ffs:CreateObject") + defer reg.End() + attrNum := len(prm.Attributes) + 1 // + creation time if prm.Filepath != "" { @@ -261,6 +280,9 @@ func (x payloadReader) Read(p []byte) (int, error) { // ReadObject implements frostfs.FrostFS interface method. func (x *FrostFS) ReadObject(ctx context.Context, prm layer.PrmObjectRead) (*layer.ObjectPart, error) { + reg := trace.StartRegion(ctx, "ffs:ReadObject") + defer reg.End() + var addr oid.Address addr.SetContainer(prm.Container) addr.SetObject(prm.Object) @@ -346,6 +368,9 @@ func (x *FrostFS) ReadObject(ctx context.Context, prm layer.PrmObjectRead) (*lay // DeleteObject implements frostfs.FrostFS interface method. func (x *FrostFS) DeleteObject(ctx context.Context, prm layer.PrmObjectDelete) error { + reg := trace.StartRegion(ctx, "ffs:DeleteObject") + defer reg.End() + var addr oid.Address addr.SetContainer(prm.Container) addr.SetObject(prm.Object) @@ -365,6 +390,9 @@ func (x *FrostFS) DeleteObject(ctx context.Context, prm layer.PrmObjectDelete) e // SearchObjects implements frostfs.FrostFS interface method. func (x *FrostFS) SearchObjects(ctx context.Context, prm layer.PrmObjectSearch) ([]oid.ID, error) { + reg := trace.StartRegion(ctx, "ffs:SearchObject") + defer reg.End() + filters := object.NewSearchFilters() filters.AddRootFilter() diff --git a/internal/frostfs/services/pool_wrapper.go b/internal/frostfs/services/pool_wrapper.go index a1ee1981..7e0588cd 100644 --- a/internal/frostfs/services/pool_wrapper.go +++ b/internal/frostfs/services/pool_wrapper.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "runtime/trace" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware" @@ -78,6 +79,9 @@ func NewPoolWrapper(p *treepool.Pool) *PoolWrapper { } func (w *PoolWrapper) GetNodes(ctx context.Context, prm *tree.GetNodesParams) ([]tree.NodeResponse, error) { + reg := trace.StartRegion(ctx, "tree:GetNodes") + defer reg.End() + poolPrm := treepool.GetNodesParams{ CID: prm.BktInfo.CID, TreeID: prm.TreeID, @@ -103,6 +107,9 @@ func (w *PoolWrapper) GetNodes(ctx context.Context, prm *tree.GetNodesParams) ([ } func (w *PoolWrapper) GetSubTree(ctx context.Context, bktInfo *data.BucketInfo, treeID string, rootID []uint64, depth uint32) ([]tree.NodeResponse, error) { + reg := trace.StartRegion(ctx, "tree:GetSubTree") + defer reg.End() + poolPrm := treepool.GetSubTreeParams{ CID: bktInfo.CID, TreeID: treeID, @@ -177,6 +184,9 @@ func (s *SubTreeStreamImpl) Next() (tree.NodeResponse, error) { } func (w *PoolWrapper) GetSubTreeStream(ctx context.Context, bktInfo *data.BucketInfo, treeID string, rootID []uint64, depth uint32) (tree.SubTreeStream, error) { + reg := trace.StartRegion(ctx, "tree:GetSubTreeStream") + defer reg.End() + poolPrm := treepool.GetSubTreeParams{ CID: bktInfo.CID, TreeID: treeID, @@ -206,6 +216,9 @@ func (w *PoolWrapper) GetSubTreeStream(ctx context.Context, bktInfo *data.Bucket } func (w *PoolWrapper) AddNode(ctx context.Context, bktInfo *data.BucketInfo, treeID string, parent uint64, meta map[string]string) (uint64, error) { + reg := trace.StartRegion(ctx, "tree:AddNode") + defer reg.End() + nodeID, err := w.p.AddNode(ctx, treepool.AddNodeParams{ CID: bktInfo.CID, TreeID: treeID, @@ -217,6 +230,9 @@ func (w *PoolWrapper) AddNode(ctx context.Context, bktInfo *data.BucketInfo, tre } func (w *PoolWrapper) AddNodeByPath(ctx context.Context, bktInfo *data.BucketInfo, treeID string, path []string, meta map[string]string) (uint64, error) { + reg := trace.StartRegion(ctx, "tree:AddNodeByPath") + defer reg.End() + nodeID, err := w.p.AddNodeByPath(ctx, treepool.AddNodeByPathParams{ CID: bktInfo.CID, TreeID: treeID, @@ -229,6 +245,9 @@ func (w *PoolWrapper) AddNodeByPath(ctx context.Context, bktInfo *data.BucketInf } func (w *PoolWrapper) MoveNode(ctx context.Context, bktInfo *data.BucketInfo, treeID string, nodeID, parentID uint64, meta map[string]string) error { + reg := trace.StartRegion(ctx, "tree:MoveNode") + defer reg.End() + return handleError(w.p.MoveNode(ctx, treepool.MoveNodeParams{ CID: bktInfo.CID, TreeID: treeID, @@ -240,6 +259,9 @@ func (w *PoolWrapper) MoveNode(ctx context.Context, bktInfo *data.BucketInfo, tr } func (w *PoolWrapper) RemoveNode(ctx context.Context, bktInfo *data.BucketInfo, treeID string, nodeID uint64) error { + reg := trace.StartRegion(ctx, "tree:RemoveNode") + defer reg.End() + return handleError(w.p.RemoveNode(ctx, treepool.RemoveNodeParams{ CID: bktInfo.CID, TreeID: treeID,