The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/pkg/services/search/service.go

140 lines
3.5 KiB

package search
import (
"context"
"sort"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/search/model"
"github.com/grafana/grafana/pkg/services/star"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
func ProvideService(cfg *setting.Cfg, sqlstore db.DB, starService star.Service, dashboardService dashboards.DashboardService) *SearchService {
s := &SearchService{
Cfg: cfg,
sortOptions: map[string]model.SortOption{
SortAlphaAsc.Name: SortAlphaAsc,
SortAlphaDesc.Name: SortAlphaDesc,
},
sqlstore: sqlstore,
starService: starService,
dashboardService: dashboardService,
}
return s
}
type Query struct {
Title string
Tags []string
OrgId int64
SignedInUser *user.SignedInUser
Limit int64
Page int64
IsStarred bool
Type string
DashboardUIDs []string
DashboardIds []int64
// Deprecated: use FolderUID instead
FolderIds []int64
FolderUIDs []string
Permission dashboards.PermissionType
Sort string
}
type Service interface {
SearchHandler(context.Context, *Query) (model.HitList, error)
SortOptions() []model.SortOption
}
type SearchService struct {
Cfg *setting.Cfg
sortOptions map[string]model.SortOption
sqlstore db.DB
starService star.Service
dashboardService dashboards.DashboardService
}
func (s *SearchService) SearchHandler(ctx context.Context, query *Query) (model.HitList, error) {
starredQuery := star.GetUserStarsQuery{
UserID: query.SignedInUser.UserID,
}
staredDashIDs, err := s.starService.GetByUser(ctx, &starredQuery)
if err != nil {
return nil, err
}
// No starred dashboards will be found
if query.IsStarred && len(staredDashIDs.UserStars) == 0 {
return model.HitList{}, nil
}
// filter by starred dashboard IDs when starred dashboards are requested and no UID or ID filters are specified to improve query performance
if query.IsStarred && len(query.DashboardIds) == 0 && len(query.DashboardUIDs) == 0 {
for id := range staredDashIDs.UserStars {
query.DashboardIds = append(query.DashboardIds, id)
}
}
dashboardQuery := dashboards.FindPersistedDashboardsQuery{
Title: query.Title,
SignedInUser: query.SignedInUser,
DashboardUIDs: query.DashboardUIDs,
DashboardIds: query.DashboardIds,
Type: query.Type,
FolderIds: query.FolderIds, // nolint:staticcheck
FolderUIDs: query.FolderUIDs,
Tags: query.Tags,
Limit: query.Limit,
Page: query.Page,
Permission: query.Permission,
}
if sortOpt, exists := s.sortOptions[query.Sort]; exists {
dashboardQuery.Sort = sortOpt
}
hits, err := s.dashboardService.SearchDashboards(ctx, &dashboardQuery)
if err != nil {
return nil, err
}
if query.Sort == "" {
hits = sortedHits(hits)
}
// set starred dashboards
for _, dashboard := range hits {
if _, ok := staredDashIDs.UserStars[dashboard.ID]; ok {
dashboard.IsStarred = true
}
}
// filter for starred dashboards if requested
if !query.IsStarred {
return hits, nil
}
result := model.HitList{}
for _, dashboard := range hits {
if dashboard.IsStarred {
result = append(result, dashboard)
}
}
return result, nil
}
func sortedHits(unsorted model.HitList) model.HitList {
hits := make(model.HitList, 0)
hits = append(hits, unsorted...)
sort.Sort(hits)
for _, hit := range hits {
sort.Strings(hit.Tags)
}
return hits
}