diff --git a/pkg/api/quota.go b/pkg/api/quota.go index 42be8ac2a54..58ff3b11ca6 100644 --- a/pkg/api/quota.go +++ b/pkg/api/quota.go @@ -47,7 +47,9 @@ func (hs *HTTPServer) GetOrgQuotas(c *contextmodel.ReqContext) response.Response } func (hs *HTTPServer) getOrgQuotasHelper(c *contextmodel.ReqContext, orgID int64) response.Response { - q, err := hs.QuotaService.GetQuotasByScope(c.Req.Context(), quota.OrgScope, orgID) + ctx, span := hs.tracer.Start(c.Req.Context(), "api.getOrgQuotasHelper") + defer span.End() + q, err := hs.QuotaService.GetQuotasByScope(ctx, quota.OrgScope, orgID) if err != nil { return response.ErrOrFallback(http.StatusInternalServerError, "failed to get quota", err) } @@ -70,6 +72,8 @@ func (hs *HTTPServer) getOrgQuotasHelper(c *contextmodel.ReqContext, orgID int64 // 404: notFoundError // 500: internalServerError func (hs *HTTPServer) UpdateOrgQuota(c *contextmodel.ReqContext) response.Response { + ctx, span := hs.tracer.Start(c.Req.Context(), "api.UpdateOrgQuota") + defer span.End() cmd := quota.UpdateQuotaCmd{} var err error if err := web.Bind(c.Req, &cmd); err != nil { @@ -81,7 +85,7 @@ func (hs *HTTPServer) UpdateOrgQuota(c *contextmodel.ReqContext) response.Respon } cmd.Target = web.Params(c.Req)[":target"] - if err := hs.QuotaService.Update(c.Req.Context(), &cmd); err != nil { + if err := hs.QuotaService.Update(ctx, &cmd); err != nil { return response.ErrOrFallback(http.StatusInternalServerError, "Failed to update org quotas", err) } return response.Success("Organization quota updated") @@ -114,12 +118,14 @@ func (hs *HTTPServer) UpdateOrgQuota(c *contextmodel.ReqContext) response.Respon // 404: notFoundError // 500: internalServerError func (hs *HTTPServer) GetUserQuotas(c *contextmodel.ReqContext) response.Response { + ctx, span := hs.tracer.Start(c.Req.Context(), "api.GetUserQuotas") + defer span.End() id, err := strconv.ParseInt(web.Params(c.Req)[":id"], 10, 64) if err != nil { return response.Err(quota.ErrBadRequest.Errorf("id is invalid: %w", err)) } - q, err := hs.QuotaService.GetQuotasByScope(c.Req.Context(), quota.UserScope, id) + q, err := hs.QuotaService.GetQuotasByScope(ctx, quota.UserScope, id) if err != nil { return response.ErrOrFallback(http.StatusInternalServerError, "Failed to get org quotas", err) } @@ -143,6 +149,8 @@ func (hs *HTTPServer) GetUserQuotas(c *contextmodel.ReqContext) response.Respons // 404: notFoundError // 500: internalServerError func (hs *HTTPServer) UpdateUserQuota(c *contextmodel.ReqContext) response.Response { + ctx, span := hs.tracer.Start(c.Req.Context(), "api.UpdateUserQuota") + defer span.End() cmd := quota.UpdateQuotaCmd{} var err error if err := web.Bind(c.Req, &cmd); err != nil { @@ -154,7 +162,7 @@ func (hs *HTTPServer) UpdateUserQuota(c *contextmodel.ReqContext) response.Respo } cmd.Target = web.Params(c.Req)[":target"] - if err := hs.QuotaService.Update(c.Req.Context(), &cmd); err != nil { + if err := hs.QuotaService.Update(ctx, &cmd); err != nil { return response.ErrOrFallback(http.StatusInternalServerError, "Failed to update org quotas", err) } return response.Success("Organization quota updated") diff --git a/pkg/services/quota/quotaimpl/quota.go b/pkg/services/quota/quotaimpl/quota.go index 16a4f16a949..e8867ad38e8 100644 --- a/pkg/services/quota/quotaimpl/quota.go +++ b/pkg/services/quota/quotaimpl/quota.go @@ -4,6 +4,7 @@ import ( "context" "sync" + "go.opentelemetry.io/otel" "golang.org/x/sync/errgroup" "github.com/grafana/grafana/pkg/infra/db" @@ -13,6 +14,10 @@ import ( "github.com/grafana/grafana/pkg/setting" ) +// tracer is the global tracer for the quota service. Tracer pulls the globally +// initialized tracer from the opentelemetry package. +var tracer = otel.Tracer("github.com/grafana/grafana/pkg/services/quota/quotaimpl/service") + type serviceDisabled struct { } @@ -81,16 +86,20 @@ func (s *service) QuotaReached(c *contextmodel.ReqContext, targetSrv quota.Targe if c == nil { return false, nil } + ctx, span := tracer.Start(c.Req.Context(), "quota-service.QuotaReached") + defer span.End() params := "a.ScopeParameters{} if c.IsSignedIn { params.OrgID = c.SignedInUser.GetOrgID() params.UserID = c.UserID } - return s.CheckQuotaReached(c.Req.Context(), targetSrv, params) + return s.CheckQuotaReached(ctx, targetSrv, params) } func (s *service) GetQuotasByScope(ctx context.Context, scope quota.Scope, id int64) ([]quota.QuotaDTO, error) { + ctx, span := tracer.Start(ctx, "quota-service.GetQuotasByScope") + defer span.End() if err := scope.Validate(); err != nil { return nil, err } @@ -104,10 +113,7 @@ func (s *service) GetQuotasByScope(ctx context.Context, scope quota.Scope, id in scopeParams.UserID = id } - c, err := s.getContext(ctx) - if err != nil { - return nil, err - } + c := quota.FromContext(ctx, s.targetToSrv) customLimits, err := s.store.Get(c, &scopeParams) if err != nil { return nil, err @@ -160,6 +166,8 @@ func (s *service) GetQuotasByScope(ctx context.Context, scope quota.Scope, id in } func (s *service) Update(ctx context.Context, cmd *quota.UpdateQuotaCmd) error { + ctx, span := tracer.Start(ctx, "quota-service.Update") + defer span.End() targetFound := false knownTargets, err := s.defaultLimits.Targets() if err != nil { @@ -175,16 +183,15 @@ func (s *service) Update(ctx context.Context, cmd *quota.UpdateQuotaCmd) error { return quota.ErrInvalidTarget.Errorf("unknown quota target: %s", cmd.Target) } - c, err := s.getContext(ctx) - if err != nil { - return err - } + c := quota.FromContext(ctx, s.targetToSrv) return s.store.Update(c, cmd) } // CheckQuotaReached check that quota is reached for a target. If ScopeParameters are not defined, only global scope is checked func (s *service) CheckQuotaReached(ctx context.Context, targetSrv quota.TargetSrv, scopeParams *quota.ScopeParameters) (bool, error) { - targetSrvLimits, err := s.getOverridenLimits(ctx, targetSrv, scopeParams) + ctx, span := tracer.Start(ctx, "quota-service.CheckQuotaReached") + defer span.End() + targetSrvLimits, err := s.getOverriddenLimits(ctx, targetSrv, scopeParams) if err != nil { return false, err } @@ -233,10 +240,9 @@ func (s *service) CheckQuotaReached(ctx context.Context, targetSrv quota.TargetS } func (s *service) DeleteQuotaForUser(ctx context.Context, userID int64) error { - c, err := s.getContext(ctx) - if err != nil { - return err - } + ctx, span := tracer.Start(ctx, "quota-service.DeleteQuotaForUser") + defer span.End() + c := quota.FromContext(ctx, s.targetToSrv) return s.store.DeleteByUser(c, userID) } @@ -296,13 +302,12 @@ func (s *service) getReporters() <-chan reporter { return ch } -func (s *service) getOverridenLimits(ctx context.Context, targetSrv quota.TargetSrv, scopeParams *quota.ScopeParameters) (map[quota.Tag]int64, error) { +func (s *service) getOverriddenLimits(ctx context.Context, targetSrv quota.TargetSrv, scopeParams *quota.ScopeParameters) (map[quota.Tag]int64, error) { + ctx, span := tracer.Start(ctx, "quota-service.getOverriddenLimits") + defer span.End() targetSrvLimits := make(map[quota.Tag]int64) - c, err := s.getContext(ctx) - if err != nil { - return nil, err - } + c := quota.FromContext(ctx, s.targetToSrv) customLimits, err := s.store.Get(c, scopeParams) if err != nil { return targetSrvLimits, err @@ -331,6 +336,8 @@ func (s *service) getOverridenLimits(ctx context.Context, targetSrv quota.Target } func (s *service) getUsage(ctx context.Context, scopeParams *quota.ScopeParameters) (*quota.Map, error) { + ctx, span := tracer.Start(ctx, "quota-service.getUsage") + defer span.End() usage := "a.Map{} g, ctx := errgroup.WithContext(ctx) @@ -352,7 +359,3 @@ func (s *service) getUsage(ctx context.Context, scopeParams *quota.ScopeParamete return usage, nil } - -func (s *service) getContext(ctx context.Context) (quota.Context, error) { - return quota.FromContext(ctx, s.targetToSrv), nil -}