Dashboard Provisioning: Reduce db load (#106114)

This commit is contained in:
Stephanie Hingtgen
2025-05-29 09:39:07 +03:00
committed by GitHub
parent 3de80ec3d7
commit ab99211b40
11 changed files with 491 additions and 351 deletions
@@ -231,21 +231,8 @@ func (c *DashboardSearchClient) Search(ctx context.Context, req *resourcepb.Reso
query.ManagerIdentity = vals[0]
}
}
searchFields := resource.StandardSearchFields()
columns := []*resourcepb.ResourceTableColumnDefinition{
searchFields.Field(resource.SEARCH_FIELD_TITLE),
searchFields.Field(resource.SEARCH_FIELD_FOLDER),
searchFields.Field(resource.SEARCH_FIELD_TAGS),
searchFields.Field(resource.SEARCH_FIELD_LEGACY_ID),
}
if sortByField != "" {
columns = append(columns, &resourcepb.ResourceTableColumnDefinition{
Name: sortByField,
Type: resourcepb.ResourceTableColumnDefinition_INT64,
})
}
columns := c.getColumns(sortByField, query)
list := &resourcepb.ResourceSearchResponse{
Results: &resourcepb.ResourceTable{
Columns: columns,
@@ -254,48 +241,71 @@ func (c *DashboardSearchClient) Search(ctx context.Context, req *resourcepb.Reso
// if we are querying for provisioning information, we need to use a different
// legacy sql query, since legacy search does not support this
if query.ManagerIdentity != "" || len(query.ManagerIdentityNotIn) > 0 {
if query.ManagerIdentity != "" || len(query.ManagerIdentityNotIn) > 0 || query.ManagedBy != "" {
if query.ManagedBy == utils.ManagerKindUnknown {
return nil, fmt.Errorf("query by manager identity also requires manager.kind parameter")
}
var dashes []*dashboards.Dashboard
if query.ManagedBy == utils.ManagerKindPlugin {
dashes, err = c.dashboardStore.GetDashboardsByPluginID(ctx, &dashboards.GetDashboardsByPluginIDQuery{
PluginID: query.ManagerIdentity,
OrgID: user.GetOrgID(),
})
} else if query.ManagerIdentity != "" {
dashes, err = c.dashboardStore.GetProvisionedDashboardsByName(ctx, query.ManagerIdentity, user.GetOrgID())
} else if len(query.ManagerIdentityNotIn) > 0 {
dashes, err = c.dashboardStore.GetOrphanedProvisionedDashboards(ctx, query.ManagerIdentityNotIn, user.GetOrgID())
}
if err != nil {
return nil, err
}
for _, dashboard := range dashes {
cells := [][]byte{
[]byte(dashboard.Title),
[]byte(dashboard.FolderUID),
[]byte("[]"), // no tags retrieved for provisioned dashboards
[]byte(strconv.FormatInt(dashboard.ID, 10)),
// for plugin and orphaned dashboards, we will only return the manager kind alongside the regular search response
if query.ManagedBy == utils.ManagerKindPlugin || len(query.ManagerIdentityNotIn) > 0 {
var dashes []*dashboards.Dashboard
if query.ManagedBy == utils.ManagerKindPlugin {
dashes, err = c.dashboardStore.GetDashboardsByPluginID(ctx, &dashboards.GetDashboardsByPluginIDQuery{
PluginID: query.ManagerIdentity,
OrgID: user.GetOrgID(),
})
} else {
dashes, err = c.dashboardStore.GetOrphanedProvisionedDashboards(ctx, query.ManagerIdentityNotIn, user.GetOrgID())
}
if err != nil {
return nil, err
}
if sortByField != "" {
cells = append(cells, []byte("0"))
for _, dashboard := range dashes {
list.Results.Rows = append(list.Results.Rows, &resourcepb.ResourceTableRow{
Key: getResourceKey(&dashboards.DashboardSearchProjection{
UID: dashboard.UID,
}, req.Options.Key.Namespace),
Cells: c.createProvisioningCells(dashboard, query),
})
}
list.TotalHits = int64(len(list.Results.Rows))
return list, nil
}
// for classic FP, we will return the regular search response alongside all the data in the dashboard_provisioning table
provisioningData := []*dashboards.DashboardProvisioningSearchResults{}
if query.ManagerIdentity == "" {
var data *dashboards.DashboardProvisioningSearchResults
if len(query.DashboardIds) > 0 {
data, err = c.dashboardStore.GetProvisionedDataByDashboardID(ctx, query.DashboardIds[0])
} else if len(query.DashboardUIDs) > 0 {
data, err = c.dashboardStore.GetProvisionedDataByDashboardUID(ctx, user.GetOrgID(), query.DashboardUIDs[0])
}
if err != nil {
return nil, err
}
if data != nil {
provisioningData = append(provisioningData, data)
}
} else {
provisioningData, err = c.dashboardStore.GetProvisionedDashboardsByName(ctx, query.ManagerIdentity, user.GetOrgID())
if err != nil {
return nil, err
}
}
for _, dashboard := range provisioningData {
list.Results.Rows = append(list.Results.Rows, &resourcepb.ResourceTableRow{
Key: getResourceKey(&dashboards.DashboardSearchProjection{
UID: dashboard.UID,
UID: dashboard.Dashboard.UID,
}, req.Options.Key.Namespace),
Cells: cells,
Cells: c.createDetailedProvisioningCells(dashboard, query),
})
}
list.TotalHits = int64(len(list.Results.Rows))
return list, nil
}
@@ -305,22 +315,11 @@ func (c *DashboardSearchClient) Search(ctx context.Context, req *resourcepb.Reso
}
for _, dashboard := range res {
tags, err := json.Marshal(dashboard.Tags)
cells, err := c.createBaseCells(dashboard, sortByField)
if err != nil {
return nil, err
}
cells := [][]byte{
[]byte(dashboard.Title),
[]byte(dashboard.FolderUID),
tags,
[]byte(strconv.FormatInt(dashboard.ID, 10)),
}
if sortByField != "" {
cells = append(cells, []byte(strconv.FormatInt(dashboard.SortMeta, 10)))
}
list.Results.Rows = append(list.Results.Rows, &resourcepb.ResourceTableRow{
Key: getResourceKey(&dashboard, req.Options.Key.Namespace),
Cells: cells,
@@ -391,3 +390,93 @@ func (c *DashboardSearchClient) GetStats(ctx context.Context, req *resourcepb.Re
},
}, nil
}
func (c *DashboardSearchClient) getColumns(sortByField string, query *dashboards.FindPersistedDashboardsQuery) []*resourcepb.ResourceTableColumnDefinition {
searchFields := resource.StandardSearchFields()
columns := []*resourcepb.ResourceTableColumnDefinition{
searchFields.Field(resource.SEARCH_FIELD_TITLE),
searchFields.Field(resource.SEARCH_FIELD_FOLDER),
searchFields.Field(resource.SEARCH_FIELD_TAGS),
searchFields.Field(resource.SEARCH_FIELD_LEGACY_ID),
}
if query.ManagerIdentity != "" || len(query.ManagerIdentityNotIn) > 0 || query.ManagedBy != "" {
columns = append(columns, &resourcepb.ResourceTableColumnDefinition{
Name: resource.SEARCH_FIELD_MANAGER_KIND,
Type: resourcepb.ResourceTableColumnDefinition_STRING,
})
if query.ManagedBy != utils.ManagerKindPlugin && len(query.ManagerIdentityNotIn) == 0 {
columns = append(columns, []*resourcepb.ResourceTableColumnDefinition{
{
Name: resource.SEARCH_FIELD_MANAGER_ID,
Type: resourcepb.ResourceTableColumnDefinition_STRING,
},
{
Name: resource.SEARCH_FIELD_SOURCE_PATH,
Type: resourcepb.ResourceTableColumnDefinition_STRING,
},
{
Name: resource.SEARCH_FIELD_SOURCE_CHECKSUM,
Type: resourcepb.ResourceTableColumnDefinition_STRING,
},
{
Name: resource.SEARCH_FIELD_SOURCE_TIME,
Type: resourcepb.ResourceTableColumnDefinition_STRING,
},
}...)
}
return columns
}
// cannot sort when querying provisioned dashboards
if sortByField != "" {
columns = append(columns, &resourcepb.ResourceTableColumnDefinition{
Name: sortByField,
Type: resourcepb.ResourceTableColumnDefinition_INT64,
})
}
return columns
}
func (c *DashboardSearchClient) createCommonCells(title, folderUID string, id int64, tags []byte) [][]byte {
return [][]byte{
[]byte(title),
[]byte(folderUID),
tags,
[]byte(strconv.FormatInt(id, 10)),
}
}
func (c *DashboardSearchClient) createBaseCells(dashboard dashboards.DashboardSearchProjection, sortByField string) ([][]byte, error) {
tags, err := json.Marshal(dashboard.Tags)
if err != nil {
return nil, err
}
cells := c.createCommonCells(dashboard.Title, dashboard.FolderUID, dashboard.ID, tags)
if sortByField != "" {
cells = append(cells, []byte(strconv.FormatInt(dashboard.SortMeta, 10)))
}
return cells, nil
}
func (c *DashboardSearchClient) createProvisioningCells(dashboard *dashboards.Dashboard, query *dashboards.FindPersistedDashboardsQuery) [][]byte {
cells := c.createCommonCells(dashboard.Title, dashboard.FolderUID, dashboard.ID, []byte("[]"))
return append(cells, []byte(query.ManagedBy))
}
func (c *DashboardSearchClient) createDetailedProvisioningCells(dashboard *dashboards.DashboardProvisioningSearchResults, query *dashboards.FindPersistedDashboardsQuery) [][]byte {
cells := c.createCommonCells(dashboard.Dashboard.Title, dashboard.Dashboard.FolderUID, dashboard.Dashboard.ID, []byte("[]"))
return append(cells,
[]byte(query.ManagedBy),
[]byte(dashboard.Provisioner),
[]byte(dashboard.ExternalID),
[]byte(dashboard.CheckSum),
[]byte(strconv.FormatInt(dashboard.ProvisionUpdate, 10)),
)
}
@@ -420,8 +420,12 @@ func TestDashboardSearchClient_Search(t *testing.T) {
})
t.Run("Should retrieve dashboards by provisioner name through a different function", func(t *testing.T) {
mockStore.On("GetProvisionedDashboardsByName", mock.Anything, "test", mock.Anything).Return([]*dashboards.Dashboard{
{UID: "uid", Title: "Test Dashboard", FolderUID: "folder1"},
mockStore.On("GetProvisionedDashboardsByName", mock.Anything, "test", mock.Anything).Return([]*dashboards.DashboardProvisioningSearchResults{
{
Dashboard: dashboards.Dashboard{UID: "uid", Title: "Test Dashboard", FolderUID: "folder1"},
ExternalID: "test",
Provisioner: string(utils.ManagerKindClassicFP), // nolint:staticcheck
},
}, nil).Once()
req := &resourcepb.ResourceSearchRequest{