mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Major refactorings around searching, moved to seperate package, trying to move stuff out of models package, extend search support searching different types of entities and different types of dashboards, #960
This commit is contained in:
@@ -1,134 +0,0 @@
|
||||
package search
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/log"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
type JsonDashIndex struct {
|
||||
path string
|
||||
orgsIds []int64
|
||||
items []*JsonDashIndexItem
|
||||
}
|
||||
|
||||
type JsonDashIndexItem struct {
|
||||
TitleLower string
|
||||
TagsCsv string
|
||||
Path string
|
||||
Dashboard *m.Dashboard
|
||||
}
|
||||
|
||||
func NewJsonDashIndex(path string, orgIds string) *JsonDashIndex {
|
||||
log.Info("Creating json dashboard index for path: ", path)
|
||||
|
||||
index := JsonDashIndex{}
|
||||
index.path = path
|
||||
index.updateIndex()
|
||||
return &index
|
||||
}
|
||||
|
||||
func (index *JsonDashIndex) Search(query *Query) ([]*m.DashboardSearchHit, error) {
|
||||
results := make([]*m.DashboardSearchHit, 0)
|
||||
|
||||
for _, item := range index.items {
|
||||
if len(results) > query.Limit {
|
||||
break
|
||||
}
|
||||
|
||||
// filter out results with tag filter
|
||||
if query.Tag != "" {
|
||||
if !strings.Contains(item.TagsCsv, query.Tag) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// add results with matchig title filter
|
||||
if strings.Contains(item.TitleLower, query.Title) {
|
||||
results = append(results, &m.DashboardSearchHit{
|
||||
Type: m.DashTypeJson,
|
||||
Title: item.Dashboard.Title,
|
||||
Tags: item.Dashboard.GetTags(),
|
||||
Uri: "file/" + item.Path,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (index *JsonDashIndex) GetDashboard(path string) *m.Dashboard {
|
||||
for _, item := range index.items {
|
||||
if item.Path == path {
|
||||
return item.Dashboard
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (index *JsonDashIndex) updateIndex() error {
|
||||
|
||||
index.items = make([]*JsonDashIndexItem, 0)
|
||||
|
||||
visitor := func(path string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if f.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if strings.HasSuffix(f.Name(), ".json") {
|
||||
err = index.loadDashboardIntoCache(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := filepath.Walk(index.path, visitor); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (index *JsonDashIndex) loadDashboardIntoCache(filename string) error {
|
||||
dash, err := loadDashboardFromFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
index.items = append(index.items, dash)
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadDashboardFromFile(filename string) (*JsonDashIndexItem, error) {
|
||||
reader, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
jsonParser := json.NewDecoder(reader)
|
||||
var data map[string]interface{}
|
||||
|
||||
if err := jsonParser.Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stat, _ := os.Stat(filename)
|
||||
|
||||
item := &JsonDashIndexItem{}
|
||||
item.Dashboard = m.NewDashboardFromJson(data)
|
||||
item.TitleLower = strings.ToLower(item.Dashboard.Title)
|
||||
item.TagsCsv = strings.Join(item.Dashboard.GetTags(), ",")
|
||||
item.Path = stat.Name()
|
||||
|
||||
return item, nil
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package search
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestJsonDashIndex(t *testing.T) {
|
||||
|
||||
Convey("Given the json dash index", t, func() {
|
||||
index := NewJsonDashIndex("../../../public/dashboards/", "*")
|
||||
|
||||
Convey("Should be able to update index", func() {
|
||||
err := index.updateIndex()
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("Should be able to search index", func() {
|
||||
res, err := index.Search(&Query{Title: "", Tag: "", Limit: 20})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(len(res), ShouldEqual, 3)
|
||||
})
|
||||
|
||||
Convey("Should be able to search index by title", func() {
|
||||
res, err := index.Search(&Query{Title: "home", Tag: "", Limit: 20})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(len(res), ShouldEqual, 1)
|
||||
So(res[0].Title, ShouldEqual, "Home")
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package search
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
type Query struct {
|
||||
Title string
|
||||
Tag string
|
||||
OrgId int64
|
||||
UserId int64
|
||||
Limit int
|
||||
IsStarred bool
|
||||
|
||||
Result []*m.DashboardSearchHit
|
||||
}
|
||||
|
||||
var jsonDashIndex *JsonDashIndex
|
||||
|
||||
func Init() {
|
||||
bus.AddHandler("search", searchHandler)
|
||||
|
||||
jsonIndexCfg, _ := setting.Cfg.GetSection("dashboards.json")
|
||||
jsonIndexEnabled := jsonIndexCfg.Key("enabled").MustBool(false)
|
||||
|
||||
if jsonIndexEnabled {
|
||||
jsonFilesPath := jsonIndexCfg.Key("path").String()
|
||||
if !filepath.IsAbs(jsonFilesPath) {
|
||||
jsonFilesPath = filepath.Join(setting.HomePath, jsonFilesPath)
|
||||
}
|
||||
|
||||
orgIds := jsonIndexCfg.Key("org_ids").String()
|
||||
jsonDashIndex = NewJsonDashIndex(jsonFilesPath, orgIds)
|
||||
}
|
||||
}
|
||||
|
||||
func searchHandler(query *Query) error {
|
||||
hits := make([]*m.DashboardSearchHit, 0)
|
||||
|
||||
dashQuery := m.SearchDashboardsQuery{
|
||||
Title: query.Title,
|
||||
Tag: query.Tag,
|
||||
UserId: query.UserId,
|
||||
Limit: query.Limit,
|
||||
IsStarred: query.IsStarred,
|
||||
OrgId: query.OrgId,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&dashQuery); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hits = append(hits, dashQuery.Result...)
|
||||
|
||||
if jsonDashIndex != nil {
|
||||
jsonHits, err := jsonDashIndex.Search(query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hits = append(hits, jsonHits...)
|
||||
}
|
||||
|
||||
if err := setIsStarredFlagOnSearchResults(query.UserId, hits); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query.Result = hits
|
||||
return nil
|
||||
}
|
||||
|
||||
func setIsStarredFlagOnSearchResults(userId int64, hits []*m.DashboardSearchHit) error {
|
||||
query := m.GetUserStarsQuery{UserId: userId}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, dash := range hits {
|
||||
if _, exists := query.Result[dash.Id]; exists {
|
||||
dash.IsStarred = true
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetDashboardFromJsonIndex(filename string) *m.Dashboard {
|
||||
if jsonDashIndex == nil {
|
||||
return nil
|
||||
}
|
||||
return jsonDashIndex.GetDashboard(filename)
|
||||
}
|
||||
Reference in New Issue
Block a user