chore(folders): add extended tracing to the folders service (#103007)

pull/103344/head
Jean-Philippe Quéméner 3 months ago committed by GitHub
parent 4fffc3adaf
commit f4ae8516bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 66
      pkg/services/folder/folderimpl/folder.go
  2. 1
      pkg/services/folder/folderimpl/folder_test.go
  3. 44
      pkg/services/folder/folderimpl/folder_unifiedstorage.go
  4. 3
      pkg/services/folder/folderimpl/folder_unifiedstorage_test.go

@ -203,6 +203,8 @@ func (s *Service) DBMigration(db db.DB) {
} }
func (s *Service) CountFoldersInOrg(ctx context.Context, orgID int64) (int64, error) { func (s *Service) CountFoldersInOrg(ctx context.Context, orgID int64) (int64, error) {
ctx, span := s.tracer.Start(ctx, "folder.CountFoldersInOrg")
defer span.End()
if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
return s.unifiedStore.CountInOrg(ctx, orgID) return s.unifiedStore.CountInOrg(ctx, orgID)
} }
@ -211,17 +213,20 @@ func (s *Service) CountFoldersInOrg(ctx context.Context, orgID int64) (int64, er
} }
func (s *Service) SearchFolders(ctx context.Context, q folder.SearchFoldersQuery) (model.HitList, error) { func (s *Service) SearchFolders(ctx context.Context, q folder.SearchFoldersQuery) (model.HitList, error) {
ctx, span := s.tracer.Start(ctx, "folder.SearchFolders")
defer span.End()
if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
// TODO: // TODO:
// - implement filtering by alerting folders and k6 folders (see the dashboards store `FindDashboards` method for reference) // - implement filtering by alerting folders and k6 folders (see the dashboards store `FindDashboards` method for reference)
// - implement fallback on search client in unistore to go to legacy store (will need to read from dashboard store) // - implement fallback on search client in unistore to go to legacy store (will need to read from dashboard store)
return s.searchFoldersFromApiServer(ctx, q) return s.searchFoldersFromApiServer(ctx, q)
} }
return nil, fmt.Errorf("cannot be called on the legacy folder service") return nil, fmt.Errorf("cannot be called on the legacy folder service")
} }
func (s *Service) GetFolders(ctx context.Context, q folder.GetFoldersQuery) ([]*folder.Folder, error) { func (s *Service) GetFolders(ctx context.Context, q folder.GetFoldersQuery) ([]*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.GetFolders")
defer span.End()
if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
return s.getFoldersFromApiServer(ctx, q) return s.getFoldersFromApiServer(ctx, q)
} }
@ -229,6 +234,8 @@ func (s *Service) GetFolders(ctx context.Context, q folder.GetFoldersQuery) ([]*
} }
func (s *Service) GetFoldersLegacy(ctx context.Context, q folder.GetFoldersQuery) ([]*folder.Folder, error) { func (s *Service) GetFoldersLegacy(ctx context.Context, q folder.GetFoldersQuery) ([]*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.GetFoldersLegacy")
defer span.End()
if q.SignedInUser == nil { if q.SignedInUser == nil {
return nil, folder.ErrBadRequest.Errorf("missing signed in user") return nil, folder.ErrBadRequest.Errorf("missing signed in user")
} }
@ -281,6 +288,8 @@ func (s *Service) GetFoldersLegacy(ctx context.Context, q folder.GetFoldersQuery
} }
func (s *Service) Get(ctx context.Context, q *folder.GetFolderQuery) (*folder.Folder, error) { func (s *Service) Get(ctx context.Context, q *folder.GetFolderQuery) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.Get")
defer span.End()
if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
return s.getFromApiServer(ctx, q) return s.getFromApiServer(ctx, q)
} }
@ -288,6 +297,8 @@ func (s *Service) Get(ctx context.Context, q *folder.GetFolderQuery) (*folder.Fo
} }
func (s *Service) GetLegacy(ctx context.Context, q *folder.GetFolderQuery) (*folder.Folder, error) { func (s *Service) GetLegacy(ctx context.Context, q *folder.GetFolderQuery) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.GetLegacy")
defer span.End()
if q.SignedInUser == nil { if q.SignedInUser == nil {
return nil, folder.ErrBadRequest.Errorf("missing signed in user") return nil, folder.ErrBadRequest.Errorf("missing signed in user")
} }
@ -343,6 +354,8 @@ func (s *Service) GetLegacy(ctx context.Context, q *folder.GetFolderQuery) (*fol
} }
func (s *Service) setFullpath(ctx context.Context, f *folder.Folder, user identity.Requester, forceLegacy bool) (*folder.Folder, error) { func (s *Service) setFullpath(ctx context.Context, f *folder.Folder, user identity.Requester, forceLegacy bool) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.setFullpath")
defer span.End()
// #TODO is some kind of intermediate conversion required as is the case with user id where // #TODO is some kind of intermediate conversion required as is the case with user id where
// it gets parsed using UserIdentifier(). Also is there some kind of validation taking place as // it gets parsed using UserIdentifier(). Also is there some kind of validation taking place as
// part of the parsing? // part of the parsing?
@ -386,6 +399,8 @@ func (s *Service) setFullpath(ctx context.Context, f *folder.Folder, user identi
} }
func (s *Service) GetChildren(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) { func (s *Service) GetChildren(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) {
ctx, span := s.tracer.Start(ctx, "folder.GetChildren")
defer span.End()
if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
return s.getChildrenFromApiServer(ctx, q) return s.getChildrenFromApiServer(ctx, q)
} }
@ -393,6 +408,8 @@ func (s *Service) GetChildren(ctx context.Context, q *folder.GetChildrenQuery) (
} }
func (s *Service) GetChildrenLegacy(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) { func (s *Service) GetChildrenLegacy(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) {
ctx, span := s.tracer.Start(ctx, "folder.GetChildrenLegacy")
defer span.End()
defer func(t time.Time) { defer func(t time.Time) {
parent := q.UID parent := q.UID
if q.UID != folder.SharedWithMeFolderUID { if q.UID != folder.SharedWithMeFolderUID {
@ -466,6 +483,8 @@ func (s *Service) GetChildrenLegacy(ctx context.Context, q *folder.GetChildrenQu
} }
func (s *Service) getRootFolders(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) { func (s *Service) getRootFolders(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) {
ctx, span := s.tracer.Start(ctx, "folder.getRootFolders")
defer span.End()
permissions := q.SignedInUser.GetPermissions() permissions := q.SignedInUser.GetPermissions()
var folderPermissions []string var folderPermissions []string
if q.Permission == dashboardaccess.PERMISSION_EDIT { if q.Permission == dashboardaccess.PERMISSION_EDIT {
@ -535,6 +554,8 @@ func (s *Service) getRootFolders(ctx context.Context, q *folder.GetChildrenQuery
// GetSharedWithMe returns folders available to user, which cannot be accessed from the root folders // GetSharedWithMe returns folders available to user, which cannot be accessed from the root folders
func (s *Service) GetSharedWithMe(ctx context.Context, q *folder.GetChildrenQuery, forceLegacy bool) ([]*folder.FolderReference, error) { func (s *Service) GetSharedWithMe(ctx context.Context, q *folder.GetChildrenQuery, forceLegacy bool) ([]*folder.FolderReference, error) {
ctx, span := s.tracer.Start(ctx, "folder.GetSharedWithMe")
defer span.End()
start := time.Now() start := time.Now()
availableNonRootFolders, err := s.getAvailableNonRootFolders(ctx, q, forceLegacy) availableNonRootFolders, err := s.getAvailableNonRootFolders(ctx, q, forceLegacy)
if err != nil { if err != nil {
@ -558,6 +579,8 @@ func (s *Service) GetSharedWithMe(ctx context.Context, q *folder.GetChildrenQuer
} }
func (s *Service) getAvailableNonRootFolders(ctx context.Context, q *folder.GetChildrenQuery, forceLegacy bool) ([]*folder.Folder, error) { func (s *Service) getAvailableNonRootFolders(ctx context.Context, q *folder.GetChildrenQuery, forceLegacy bool) ([]*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.getAvailableNonRootFolders")
defer span.End()
permissions := q.SignedInUser.GetPermissions() permissions := q.SignedInUser.GetPermissions()
var folderPermissions []string var folderPermissions []string
if q.Permission == dashboardaccess.PERMISSION_EDIT { if q.Permission == dashboardaccess.PERMISSION_EDIT {
@ -624,6 +647,8 @@ func (s *Service) deduplicateAvailableFolders(ctx context.Context, folders []*fo
foldersRef[i] = f.ToFolderReference() foldersRef[i] = f.ToFolderReference()
} }
_, span := s.tracer.Start(ctx, "folder.deduplicateAvailableFolders")
defer span.End()
allFolders := append(foldersRef, rootFolders...) allFolders := append(foldersRef, rootFolders...)
foldersDedup := make([]*folder.FolderReference, 0) foldersDedup := make([]*folder.FolderReference, 0)
@ -661,6 +686,8 @@ func (s *Service) deduplicateAvailableFolders(ctx context.Context, folders []*fo
} }
func (s *Service) GetParents(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) { func (s *Service) GetParents(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.GetParents")
defer span.End()
if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
return s.getParentsFromApiServer(ctx, q) return s.getParentsFromApiServer(ctx, q)
} }
@ -668,6 +695,8 @@ func (s *Service) GetParents(ctx context.Context, q folder.GetParentsQuery) ([]*
} }
func (s *Service) GetParentsLegacy(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) { func (s *Service) GetParentsLegacy(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.GetParentsLegacy")
defer span.End()
if !s.features.IsEnabled(ctx, featuremgmt.FlagNestedFolders) || q.UID == accesscontrol.GeneralFolderUID { if !s.features.IsEnabled(ctx, featuremgmt.FlagNestedFolders) || q.UID == accesscontrol.GeneralFolderUID {
return nil, nil return nil, nil
} }
@ -801,6 +830,8 @@ func (s *Service) CreateLegacy(ctx context.Context, cmd *folder.CreateFolderComm
} }
func (s *Service) Update(ctx context.Context, cmd *folder.UpdateFolderCommand) (*folder.Folder, error) { 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 s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
return s.updateOnApiServer(ctx, cmd) return s.updateOnApiServer(ctx, cmd)
} }
@ -808,7 +839,7 @@ func (s *Service) Update(ctx context.Context, cmd *folder.UpdateFolderCommand) (
} }
func (s *Service) UpdateLegacy(ctx context.Context, cmd *folder.UpdateFolderCommand) (*folder.Folder, error) { func (s *Service) UpdateLegacy(ctx context.Context, cmd *folder.UpdateFolderCommand) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.Update") ctx, span := s.tracer.Start(ctx, "folder.UpdateLegacy")
defer span.End() defer span.End()
if cmd.SignedInUser == nil { if cmd.SignedInUser == nil {
@ -863,6 +894,8 @@ func (s *Service) UpdateLegacy(ctx context.Context, cmd *folder.UpdateFolderComm
} }
func (s *Service) legacyUpdate(ctx context.Context, cmd *folder.UpdateFolderCommand) (*folder.Folder, error) { func (s *Service) legacyUpdate(ctx context.Context, cmd *folder.UpdateFolderCommand) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.legacyUpdate")
defer span.End()
query := dashboards.GetDashboardQuery{OrgID: cmd.OrgID, UID: cmd.UID} query := dashboards.GetDashboardQuery{OrgID: cmd.OrgID, UID: cmd.UID}
queryResult, err := s.dashboardStore.GetDashboard(ctx, &query) queryResult, err := s.dashboardStore.GetDashboard(ctx, &query)
if err != nil { if err != nil {
@ -940,6 +973,8 @@ func prepareForUpdate(dashFolder *dashboards.Dashboard, orgId int64, userId int6
} }
func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) error { func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
ctx, span := s.tracer.Start(ctx, "folder.Delete")
defer span.End()
if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
return s.deleteFromApiServer(ctx, cmd) return s.deleteFromApiServer(ctx, cmd)
} }
@ -947,6 +982,8 @@ func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) e
} }
func (s *Service) DeleteLegacy(ctx context.Context, cmd *folder.DeleteFolderCommand) error { func (s *Service) DeleteLegacy(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
ctx, span := s.tracer.Start(ctx, "folder.DeleteLegacy")
defer span.End()
if cmd.SignedInUser == nil { if cmd.SignedInUser == nil {
return folder.ErrBadRequest.Errorf("missing signed in user") return folder.ErrBadRequest.Errorf("missing signed in user")
} }
@ -1015,6 +1052,8 @@ func (s *Service) DeleteLegacy(ctx context.Context, cmd *folder.DeleteFolderComm
} }
func (s *Service) deleteChildrenInFolder(ctx context.Context, orgID int64, folderUIDs []string, user identity.Requester) error { func (s *Service) deleteChildrenInFolder(ctx context.Context, orgID int64, folderUIDs []string, user identity.Requester) error {
ctx, span := s.tracer.Start(ctx, "folder.deleteChildrenInFolder")
defer span.End()
for _, v := range s.registry { for _, v := range s.registry {
if err := v.DeleteInFolders(ctx, orgID, folderUIDs, user); err != nil { if err := v.DeleteInFolders(ctx, orgID, folderUIDs, user); err != nil {
return err return err
@ -1024,6 +1063,8 @@ func (s *Service) deleteChildrenInFolder(ctx context.Context, orgID int64, folde
} }
func (s *Service) legacyDelete(ctx context.Context, cmd *folder.DeleteFolderCommand, folderUIDs []string) error { func (s *Service) legacyDelete(ctx context.Context, cmd *folder.DeleteFolderCommand, folderUIDs []string) error {
ctx, span := s.tracer.Start(ctx, "folder.legacyDelete")
defer span.End()
// We need a list of dashboard uids inside the folder to delete related public dashboards // We need a list of dashboard uids inside the folder to delete related public dashboards
dashes, err := s.dashboardStore.FindDashboards(ctx, &dashboards.FindPersistedDashboardsQuery{ dashes, err := s.dashboardStore.FindDashboards(ctx, &dashboards.FindPersistedDashboardsQuery{
SignedInUser: cmd.SignedInUser, SignedInUser: cmd.SignedInUser,
@ -1060,6 +1101,8 @@ func (s *Service) legacyDelete(ctx context.Context, cmd *folder.DeleteFolderComm
} }
func (s *Service) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*folder.Folder, error) { 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 s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
return s.moveOnApiServer(ctx, cmd) return s.moveOnApiServer(ctx, cmd)
} }
@ -1067,7 +1110,7 @@ func (s *Service) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*fol
} }
func (s *Service) MoveLegacy(ctx context.Context, cmd *folder.MoveFolderCommand) (*folder.Folder, error) { func (s *Service) MoveLegacy(ctx context.Context, cmd *folder.MoveFolderCommand) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.Move") ctx, span := s.tracer.Start(ctx, "folder.MoveLegacy")
defer span.End() defer span.End()
if cmd.SignedInUser == nil { if cmd.SignedInUser == nil {
@ -1180,6 +1223,8 @@ func (s *Service) publishFolderFullPathUpdatedEvent(ctx context.Context, timesta
} }
func (s *Service) canMove(ctx context.Context, cmd *folder.MoveFolderCommand) (bool, error) { func (s *Service) canMove(ctx context.Context, cmd *folder.MoveFolderCommand) (bool, error) {
ctx, span := s.tracer.Start(ctx, "folder.canMove")
defer span.End()
// Check that the user is allowed to move the folder to the destination folder // Check that the user is allowed to move the folder to the destination folder
var evaluator accesscontrol.Evaluator var evaluator accesscontrol.Evaluator
parentUID := cmd.NewParentUID parentUID := cmd.NewParentUID
@ -1228,6 +1273,8 @@ func (s *Service) canMove(ctx context.Context, cmd *folder.MoveFolderCommand) (b
} }
func (s *Service) getFolderAndParentUIDScopes(ctx context.Context, folderUID string, orgID int64) ([]string, error) { func (s *Service) getFolderAndParentUIDScopes(ctx context.Context, folderUID string, orgID int64) ([]string, error) {
ctx, span := s.tracer.Start(ctx, "folder.getFolderAndParentUIDScopes")
defer span.End()
folderAndParentUIDScopes := []string{dashboards.ScopeFoldersProvider.GetResourceScopeUID(folderUID)} folderAndParentUIDScopes := []string{dashboards.ScopeFoldersProvider.GetResourceScopeUID(folderUID)}
if folderUID == folder.GeneralFolderUID { if folderUID == folder.GeneralFolderUID {
return folderAndParentUIDScopes, nil return folderAndParentUIDScopes, nil
@ -1247,6 +1294,8 @@ func (s *Service) getFolderAndParentUIDScopes(ctx context.Context, folderUID str
// its descendant folders (folders which are nested within it either directly or indirectly) from // its descendant folders (folders which are nested within it either directly or indirectly) from
// the folder store and returns the UIDs for all its descendants. // the folder store and returns the UIDs for all its descendants.
func (s *Service) nestedFolderDelete(ctx context.Context, cmd *folder.DeleteFolderCommand) ([]string, error) { func (s *Service) nestedFolderDelete(ctx context.Context, cmd *folder.DeleteFolderCommand) ([]string, error) {
ctx, span := s.tracer.Start(ctx, "folder.nestedFolderDelete")
defer span.End()
descendantUIDs := []string{} descendantUIDs := []string{}
if cmd.SignedInUser == nil { if cmd.SignedInUser == nil {
return descendantUIDs, folder.ErrBadRequest.Errorf("missing signed in user") return descendantUIDs, folder.ErrBadRequest.Errorf("missing signed in user")
@ -1281,6 +1330,8 @@ func (s *Service) nestedFolderDelete(ctx context.Context, cmd *folder.DeleteFold
} }
func (s *Service) GetDescendantCounts(ctx context.Context, q *folder.GetDescendantCountsQuery) (folder.DescendantCounts, error) { func (s *Service) GetDescendantCounts(ctx context.Context, q *folder.GetDescendantCountsQuery) (folder.DescendantCounts, error) {
ctx, span := s.tracer.Start(ctx, "folder.GetDescendantCounts")
defer span.End()
if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) { if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
return s.getDescendantCountsFromApiServer(ctx, q) return s.getDescendantCountsFromApiServer(ctx, q)
} }
@ -1289,6 +1340,8 @@ func (s *Service) GetDescendantCounts(ctx context.Context, q *folder.GetDescenda
} }
func (s *Service) GetDescendantCountsLegacy(ctx context.Context, q *folder.GetDescendantCountsQuery) (folder.DescendantCounts, error) { func (s *Service) GetDescendantCountsLegacy(ctx context.Context, q *folder.GetDescendantCountsQuery) (folder.DescendantCounts, error) {
ctx, span := s.tracer.Start(ctx, "folder.GetDescendantCountsLegacy")
defer span.End()
if q.SignedInUser == nil { if q.SignedInUser == nil {
return nil, folder.ErrBadRequest.Errorf("missing signed-in user") return nil, folder.ErrBadRequest.Errorf("missing signed-in user")
} }
@ -1327,6 +1380,9 @@ func (s *Service) GetDescendantCountsLegacy(ctx context.Context, q *folder.GetDe
// buildSaveDashboardCommand is a simplified version on DashboardServiceImpl.buildSaveDashboardCommand // buildSaveDashboardCommand is a simplified version on DashboardServiceImpl.buildSaveDashboardCommand
// keeping only the meaningful functionality for folders // keeping only the meaningful functionality for folders
func (s *Service) buildSaveDashboardCommand(ctx context.Context, dto *dashboards.SaveDashboardDTO) (*dashboards.SaveDashboardCommand, error) { func (s *Service) buildSaveDashboardCommand(ctx context.Context, dto *dashboards.SaveDashboardDTO) (*dashboards.SaveDashboardCommand, error) {
ctx, span := s.tracer.Start(ctx, "folder.buildSaveDashboardCommand")
defer span.End()
dash := dto.Dashboard dash := dto.Dashboard
dash.OrgID = dto.OrgID dash.OrgID = dto.OrgID
@ -1468,6 +1524,8 @@ func getGuardianForSavePermissionCheck(ctx context.Context, d *dashboards.Dashbo
} }
func (s *Service) nestedFolderCreate(ctx context.Context, cmd *folder.CreateFolderCommand) (*folder.Folder, error) { func (s *Service) nestedFolderCreate(ctx context.Context, cmd *folder.CreateFolderCommand) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.nestedFolderCreate")
defer span.End()
if cmd.ParentUID != "" { if cmd.ParentUID != "" {
if err := s.validateParent(ctx, cmd.OrgID, cmd.ParentUID, cmd.UID); err != nil { if err := s.validateParent(ctx, cmd.OrgID, cmd.ParentUID, cmd.UID); err != nil {
return nil, err return nil, err
@ -1477,6 +1535,8 @@ func (s *Service) nestedFolderCreate(ctx context.Context, cmd *folder.CreateFold
} }
func (s *Service) validateParent(ctx context.Context, orgID int64, parentUID string, UID string) error { func (s *Service) validateParent(ctx context.Context, orgID int64, parentUID string, UID string) error {
ctx, span := s.tracer.Start(ctx, "folder.validateParent")
defer span.End()
ancestors, err := s.store.GetParents(ctx, folder.GetParentsQuery{UID: parentUID, OrgID: orgID}) ancestors, err := s.store.GetParents(ctx, folder.GetParentsQuery{UID: parentUID, OrgID: orgID})
if err != nil { if err != nil {
return fmt.Errorf("failed to get parents: %w", err) return fmt.Errorf("failed to get parents: %w", err)

@ -1875,6 +1875,7 @@ func TestFolderServiceGetFolder(t *testing.T) {
accessControl: ac, accessControl: ac,
registry: make(map[string]folder.RegistryService), registry: make(map[string]folder.RegistryService),
metrics: newFoldersMetrics(nil), metrics: newFoldersMetrics(nil),
tracer: tracing.NewNoopTracerService(),
} }
} }

@ -12,6 +12,8 @@ import (
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"k8s.io/apimachinery/pkg/selection" "k8s.io/apimachinery/pkg/selection"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils" "github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/apis/folder/v0alpha1" "github.com/grafana/grafana/pkg/apis/folder/v0alpha1"
@ -29,12 +31,14 @@ import (
"github.com/grafana/grafana/pkg/services/store/entity" "github.com/grafana/grafana/pkg/services/store/entity"
"github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/resource"
"github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
const folderSearchLimit = 100000 const folderSearchLimit = 100000
func (s *Service) getFoldersFromApiServer(ctx context.Context, q folder.GetFoldersQuery) ([]*folder.Folder, error) { func (s *Service) getFoldersFromApiServer(ctx context.Context, q folder.GetFoldersQuery) ([]*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.getFoldersFromApiServer")
defer span.End()
if q.SignedInUser == nil { if q.SignedInUser == nil {
return nil, folder.ErrBadRequest.Errorf("missing signed in user") return nil, folder.ErrBadRequest.Errorf("missing signed in user")
} }
@ -73,6 +77,9 @@ func (s *Service) getFoldersFromApiServer(ctx context.Context, q folder.GetFolde
} }
func (s *Service) getFromApiServer(ctx context.Context, q *folder.GetFolderQuery) (*folder.Folder, error) { func (s *Service) getFromApiServer(ctx context.Context, q *folder.GetFolderQuery) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.getFromApiServer")
defer span.End()
if q.SignedInUser == nil { if q.SignedInUser == nil {
return nil, folder.ErrBadRequest.Errorf("missing signed in user") return nil, folder.ErrBadRequest.Errorf("missing signed in user")
} }
@ -154,6 +161,9 @@ func (s *Service) getFromApiServer(ctx context.Context, q *folder.GetFolderQuery
// searchFoldesFromApiServer uses the search grpc connection to search folders and returns the hit list // searchFoldesFromApiServer uses the search grpc connection to search folders and returns the hit list
func (s *Service) searchFoldersFromApiServer(ctx context.Context, query folder.SearchFoldersQuery) (model.HitList, error) { func (s *Service) searchFoldersFromApiServer(ctx context.Context, query folder.SearchFoldersQuery) (model.HitList, error) {
ctx, span := s.tracer.Start(ctx, "folder.searchFoldersFromApiServer")
defer span.End()
if query.OrgID == 0 { if query.OrgID == 0 {
requester, err := identity.GetRequester(ctx) requester, err := identity.GetRequester(ctx)
if err != nil { if err != nil {
@ -233,6 +243,9 @@ func (s *Service) searchFoldersFromApiServer(ctx context.Context, query folder.S
} }
func (s *Service) getFolderByIDFromApiServer(ctx context.Context, id int64, orgID int64) (*folder.Folder, error) { func (s *Service) getFolderByIDFromApiServer(ctx context.Context, id int64, orgID int64) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.getFolderByIDFromApiServer")
defer span.End()
if id == 0 { if id == 0 {
return &folder.GeneralFolder, nil return &folder.GeneralFolder, nil
} }
@ -286,6 +299,9 @@ func (s *Service) getFolderByIDFromApiServer(ctx context.Context, id int64, orgI
} }
func (s *Service) getFolderByTitleFromApiServer(ctx context.Context, orgID int64, title string, parentUID *string) (*folder.Folder, error) { func (s *Service) getFolderByTitleFromApiServer(ctx context.Context, orgID int64, title string, parentUID *string) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.getFolderByTitleFromApiServer")
defer span.End()
if title == "" { if title == "" {
return nil, dashboards.ErrFolderTitleEmpty return nil, dashboards.ErrFolderTitleEmpty
} }
@ -343,6 +359,8 @@ func (s *Service) getFolderByTitleFromApiServer(ctx context.Context, orgID int64
} }
func (s *Service) getChildrenFromApiServer(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) { func (s *Service) getChildrenFromApiServer(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) {
ctx, span := s.tracer.Start(ctx, "folder.getChildrenFromApiServer")
defer span.End()
defer func(t time.Time) { defer func(t time.Time) {
parent := q.UID parent := q.UID
if q.UID != folder.SharedWithMeFolderUID { if q.UID != folder.SharedWithMeFolderUID {
@ -397,6 +415,8 @@ func (s *Service) getChildrenFromApiServer(ctx context.Context, q *folder.GetChi
} }
func (s *Service) getRootFoldersFromApiServer(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) { func (s *Service) getRootFoldersFromApiServer(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) {
ctx, span := s.tracer.Start(ctx, "folder.getRootFoldersFromApiServer")
defer span.End()
permissions := q.SignedInUser.GetPermissions() permissions := q.SignedInUser.GetPermissions()
var folderPermissions []string var folderPermissions []string
if q.Permission == dashboardaccess.PERMISSION_EDIT { if q.Permission == dashboardaccess.PERMISSION_EDIT {
@ -438,6 +458,9 @@ func (s *Service) getRootFoldersFromApiServer(ctx context.Context, q *folder.Get
} }
func (s *Service) getParentsFromApiServer(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) { func (s *Service) getParentsFromApiServer(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.getParentsFromApiServer")
defer span.End()
if q.UID == accesscontrol.GeneralFolderUID { if q.UID == accesscontrol.GeneralFolderUID {
return nil, nil return nil, nil
} }
@ -449,6 +472,9 @@ func (s *Service) getParentsFromApiServer(ctx context.Context, q folder.GetParen
} }
func (s *Service) createOnApiServer(ctx context.Context, cmd *folder.CreateFolderCommand) (*folder.Folder, error) { func (s *Service) createOnApiServer(ctx context.Context, cmd *folder.CreateFolderCommand) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.createOnApiServer")
defer span.End()
if cmd.SignedInUser == nil || cmd.SignedInUser.IsNil() { if cmd.SignedInUser == nil || cmd.SignedInUser.IsNil() {
return nil, folder.ErrBadRequest.Errorf("missing signed in user") return nil, folder.ErrBadRequest.Errorf("missing signed in user")
} }
@ -514,7 +540,7 @@ func (s *Service) createOnApiServer(ctx context.Context, cmd *folder.CreateFolde
} }
func (s *Service) updateOnApiServer(ctx context.Context, cmd *folder.UpdateFolderCommand) (*folder.Folder, error) { func (s *Service) updateOnApiServer(ctx context.Context, cmd *folder.UpdateFolderCommand) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.Update") ctx, span := s.tracer.Start(ctx, "folder.updateOnApiServer")
defer span.End() defer span.End()
if cmd.SignedInUser == nil { if cmd.SignedInUser == nil {
@ -586,6 +612,9 @@ func (s *Service) updateOnApiServer(ctx context.Context, cmd *folder.UpdateFolde
} }
func (s *Service) deleteFromApiServer(ctx context.Context, cmd *folder.DeleteFolderCommand) error { func (s *Service) deleteFromApiServer(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
ctx, span := s.tracer.Start(ctx, "folder.deleteFromApiServer")
defer span.End()
if cmd.SignedInUser == nil { if cmd.SignedInUser == nil {
return folder.ErrBadRequest.Errorf("missing signed in user") return folder.ErrBadRequest.Errorf("missing signed in user")
} }
@ -689,7 +718,7 @@ func (s *Service) deleteFromApiServer(ctx context.Context, cmd *folder.DeleteFol
} }
func (s *Service) moveOnApiServer(ctx context.Context, cmd *folder.MoveFolderCommand) (*folder.Folder, error) { func (s *Service) moveOnApiServer(ctx context.Context, cmd *folder.MoveFolderCommand) (*folder.Folder, error) {
ctx, span := s.tracer.Start(ctx, "folder.Move") ctx, span := s.tracer.Start(ctx, "folder.moveOnApiServer")
defer span.End() defer span.End()
if cmd.SignedInUser == nil { if cmd.SignedInUser == nil {
@ -795,6 +824,9 @@ func (s *Service) publishFolderFullPathUpdatedEventViaApiServer(ctx context.Cont
} }
func (s *Service) canMoveViaApiServer(ctx context.Context, cmd *folder.MoveFolderCommand) (bool, error) { func (s *Service) canMoveViaApiServer(ctx context.Context, cmd *folder.MoveFolderCommand) (bool, error) {
ctx, span := s.tracer.Start(ctx, "folder.canMoveViaApiServer")
defer span.End()
// Check that the user is allowed to move the folder to the destination folder // Check that the user is allowed to move the folder to the destination folder
var evaluator accesscontrol.Evaluator var evaluator accesscontrol.Evaluator
parentUID := cmd.NewParentUID parentUID := cmd.NewParentUID
@ -843,6 +875,9 @@ func (s *Service) canMoveViaApiServer(ctx context.Context, cmd *folder.MoveFolde
} }
func (s *Service) getFolderAndParentUIDScopesViaApiServer(ctx context.Context, folderUID string, orgID int64) ([]string, error) { func (s *Service) getFolderAndParentUIDScopesViaApiServer(ctx context.Context, folderUID string, orgID int64) ([]string, error) {
ctx, span := s.tracer.Start(ctx, "folder.getFolderAndParentUIDScopesViaApiServer")
defer span.End()
folderAndParentUIDScopes := []string{dashboards.ScopeFoldersProvider.GetResourceScopeUID(folderUID)} folderAndParentUIDScopes := []string{dashboards.ScopeFoldersProvider.GetResourceScopeUID(folderUID)}
if folderUID == folder.GeneralFolderUID { if folderUID == folder.GeneralFolderUID {
return folderAndParentUIDScopes, nil return folderAndParentUIDScopes, nil
@ -859,6 +894,9 @@ func (s *Service) getFolderAndParentUIDScopesViaApiServer(ctx context.Context, f
} }
func (s *Service) getDescendantCountsFromApiServer(ctx context.Context, q *folder.GetDescendantCountsQuery) (folder.DescendantCounts, error) { func (s *Service) getDescendantCountsFromApiServer(ctx context.Context, q *folder.GetDescendantCountsQuery) (folder.DescendantCounts, error) {
ctx, span := s.tracer.Start(ctx, "folder.getDescendantCountsFromApiServer")
defer span.End()
if q.SignedInUser == nil { if q.SignedInUser == nil {
return nil, folder.ErrBadRequest.Errorf("missing signed-in user") return nil, folder.ErrBadRequest.Errorf("missing signed-in user")
} }

@ -530,6 +530,7 @@ func TestSearchFoldersFromApiServer(t *testing.T) {
k8sclient: fakeK8sClient, k8sclient: fakeK8sClient,
features: featuremgmt.WithFeatures(featuremgmt.FlagKubernetesClientDashboardsFolders), features: featuremgmt.WithFeatures(featuremgmt.FlagKubernetesClientDashboardsFolders),
unifiedStore: folderStore, unifiedStore: folderStore,
tracer: tracing.NewNoopTracerService(),
} }
user := &user.SignedInUser{OrgID: 1} user := &user.SignedInUser{OrgID: 1}
ctx := identity.WithRequester(context.Background(), user) ctx := identity.WithRequester(context.Background(), user)
@ -774,6 +775,7 @@ func TestGetFoldersFromApiServer(t *testing.T) {
k8sclient: fakeK8sClient, k8sclient: fakeK8sClient,
features: featuremgmt.WithFeatures(featuremgmt.FlagKubernetesClientDashboardsFolders), features: featuremgmt.WithFeatures(featuremgmt.FlagKubernetesClientDashboardsFolders),
unifiedStore: folderStore, unifiedStore: folderStore,
tracer: tracing.NewNoopTracerService(),
} }
user := &user.SignedInUser{OrgID: 1} user := &user.SignedInUser{OrgID: 1}
ctx := identity.WithRequester(context.Background(), user) ctx := identity.WithRequester(context.Background(), user)
@ -865,6 +867,7 @@ func TestDeleteFoldersFromApiServer(t *testing.T) {
publicDashboardService: publicDashboardFakeService, publicDashboardService: publicDashboardFakeService,
registry: make(map[string]folder.RegistryService), registry: make(map[string]folder.RegistryService),
features: featuremgmt.WithFeatures(featuremgmt.FlagKubernetesClientDashboardsFolders), features: featuremgmt.WithFeatures(featuremgmt.FlagKubernetesClientDashboardsFolders),
tracer: tracing.NewNoopTracerService(),
} }
user := &user.SignedInUser{OrgID: 1} user := &user.SignedInUser{OrgID: 1}
ctx := identity.WithRequester(context.Background(), user) ctx := identity.WithRequester(context.Background(), user)

Loading…
Cancel
Save