Alerting: update rule versions on folder move (#88376)

* Alerting: update rule versions on folder move (#88361)
* Add tracing to folder.Move and folder.Update
This commit is contained in:
Alexander Akhmetov
2024-08-13 12:26:26 +02:00
committed by GitHub
parent 8044cb50f1
commit b2eeb0dd6e
21 changed files with 196 additions and 57 deletions
+50 -9
View File
@@ -13,6 +13,8 @@ import (
"github.com/grafana/dskit/concurrency"
"github.com/prometheus/client_golang/prometheus"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"golang.org/x/exp/slices"
"github.com/grafana/grafana/pkg/apimachinery/identity"
@@ -20,6 +22,7 @@ import (
"github.com/grafana/grafana/pkg/events"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
@@ -44,12 +47,14 @@ type Service struct {
dashboardFolderStore folder.FolderStore
features featuremgmt.FeatureToggles
accessControl accesscontrol.AccessControl
// bus is currently used to publish event in case of title change
// bus is currently used to publish event in case of folder full path change.
// For example when a folder is moved to another folder or when a folder is renamed.
bus bus.Bus
mutex sync.RWMutex
registry map[string]folder.RegistryService
metrics *foldersMetrics
tracer tracing.Tracer
}
func ProvideService(
@@ -61,6 +66,7 @@ func ProvideService(
features featuremgmt.FeatureToggles,
supportBundles supportbundles.Service,
r prometheus.Registerer,
tracer tracing.Tracer,
) folder.Service {
store := ProvideStore(db)
srv := &Service{
@@ -74,6 +80,7 @@ func ProvideService(
db: db,
registry: make(map[string]folder.RegistryService),
metrics: newFoldersMetrics(r),
tracer: tracer,
}
srv.DBMigration(db)
@@ -655,6 +662,9 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
}
func (s *Service) Update(ctx context.Context, cmd *folder.UpdateFolderCommand) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.Update")
defer span.End()
if cmd.SignedInUser == nil {
return nil, folder.ErrBadRequest.Errorf("missing signed in user")
}
@@ -679,14 +689,8 @@ func (s *Service) Update(ctx context.Context, cmd *folder.UpdateFolderCommand) (
if cmd.NewTitle != nil {
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Folder).Inc()
if err := s.bus.Publish(ctx, &events.FolderTitleUpdated{
Timestamp: foldr.Updated,
Title: foldr.Title,
ID: dashFolder.ID, // nolint:staticcheck
UID: dashFolder.UID,
OrgID: cmd.OrgID,
}); err != nil {
s.log.ErrorContext(ctx, "failed to publish FolderTitleUpdated event", "folder", foldr.Title, "user", cmd.SignedInUser.GetID(), "error", err)
if err := s.publishFolderFullPathUpdatedEvent(ctx, foldr.Updated, cmd.OrgID, cmd.UID); err != nil {
return err
}
}
@@ -873,6 +877,9 @@ func (s *Service) legacyDelete(ctx context.Context, cmd *folder.DeleteFolderComm
}
func (s *Service) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.Move")
defer span.End()
if cmd.SignedInUser == nil {
return nil, folder.ErrBadRequest.Errorf("missing signed in user")
}
@@ -947,6 +954,10 @@ func (s *Service) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*fol
return folder.ErrInternal.Errorf("failed to move legacy folder: %w", err)
}
if err := s.publishFolderFullPathUpdatedEvent(ctx, f.Updated, cmd.OrgID, cmd.UID); err != nil {
return err
}
return nil
}); err != nil {
return nil, err
@@ -954,6 +965,36 @@ func (s *Service) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*fol
return f, nil
}
func (s *Service) publishFolderFullPathUpdatedEvent(ctx context.Context, timestamp time.Time, orgID int64, folderUID string) error {
ctx, span := s.tracer.Start(ctx, "folder.publishFolderFullPathUpdatedEvent")
defer span.End()
descFolders, err := s.store.GetDescendants(ctx, orgID, folderUID)
if err != nil {
s.log.ErrorContext(ctx, "Failed to get descendants of the folder", "folderUID", folderUID, "orgID", orgID, "error", err)
return err
}
uids := make([]string, 0, len(descFolders)+1)
uids = append(uids, folderUID)
for _, f := range descFolders {
uids = append(uids, f.UID)
}
span.AddEvent("found folder descendants", trace.WithAttributes(
attribute.Int64("folders", int64(len(uids))),
))
if err := s.bus.Publish(ctx, &events.FolderFullPathUpdated{
Timestamp: timestamp,
UIDs: uids,
OrgID: orgID,
}); err != nil {
s.log.ErrorContext(ctx, "Failed to publish FolderFullPathUpdated event", "folderUID", folderUID, "orgID", orgID, "descendantsUIDs", uids, "error", err)
return err
}
return nil
}
func (s *Service) canMove(ctx context.Context, cmd *folder.MoveFolderCommand) (bool, error) {
// Check that the user is allowed to move the folder to the destination folder
var evaluator accesscontrol.Evaluator