Query history: Add from and to parameters (#48212)
* Query history: Add from and to parameters * Update docs/sources/http_api/query_history.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/http_api/query_history.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/http_api/query_history.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Implement Grafana relative time range Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com>
This commit is contained in:
co-authored by
achatterjee-grafana
parent
17eca4505c
commit
b92fe0e0f5
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/tsdb/legacydata"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
@@ -39,6 +40,8 @@ func (s *QueryHistoryService) createHandler(c *models.ReqContext) response.Respo
|
||||
}
|
||||
|
||||
func (s *QueryHistoryService) searchHandler(c *models.ReqContext) response.Response {
|
||||
timeRange := legacydata.NewDataTimeRange(c.Query("from"), c.Query("to"))
|
||||
|
||||
query := SearchInQueryHistoryQuery{
|
||||
DatasourceUIDs: c.QueryStrings("datasourceUid"),
|
||||
SearchString: c.Query("searchString"),
|
||||
@@ -46,6 +49,8 @@ func (s *QueryHistoryService) searchHandler(c *models.ReqContext) response.Respo
|
||||
Sort: c.Query("sort"),
|
||||
Page: c.QueryInt("page"),
|
||||
Limit: c.QueryInt("limit"),
|
||||
From: timeRange.GetFromAsSecondsEpoch(),
|
||||
To: timeRange.GetToAsSecondsEpoch(),
|
||||
}
|
||||
|
||||
result, err := s.SearchInQueryHistory(c.Req.Context(), c.SignedInUser, query)
|
||||
|
||||
@@ -2,7 +2,6 @@ package queryhistory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -47,8 +46,8 @@ func (s QueryHistoryService) searchQueries(ctx context.Context, user *models.Sig
|
||||
var dtos []QueryHistoryDTO
|
||||
var allQueries []interface{}
|
||||
|
||||
if len(query.DatasourceUIDs) == 0 {
|
||||
return QueryHistorySearchResult{}, errors.New("no selected data source for query history search")
|
||||
if query.To <= 0 {
|
||||
query.To = time.Now().Unix()
|
||||
}
|
||||
|
||||
if query.Page <= 0 {
|
||||
|
||||
@@ -41,6 +41,8 @@ type SearchInQueryHistoryQuery struct {
|
||||
Sort string `json:"sort"`
|
||||
Page int `json:"page"`
|
||||
Limit int `json:"limit"`
|
||||
From int64 `json:"from"`
|
||||
To int64 `json:"to"`
|
||||
}
|
||||
|
||||
type PatchQueryCommentInQueryHistoryCommand struct {
|
||||
|
||||
@@ -5,18 +5,14 @@ package queryhistory
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetQueriesFromQueryHistory(t *testing.T) {
|
||||
testScenario(t, "When users tries to get query without datasourceUid, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
require.Equal(t, 500, resp.Status())
|
||||
})
|
||||
|
||||
testScenario(t, "When users tries to get query in empty query history, it should return empty result",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", "test")
|
||||
@@ -39,6 +35,16 @@ func TestGetQueriesFromQueryHistory(t *testing.T) {
|
||||
require.Equal(t, 1, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries without datasourceUid, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 3, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries with datasourceUid, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", sc.initialResult.Result.DatasourceUID)
|
||||
@@ -77,7 +83,7 @@ func TestGetQueriesFromQueryHistory(t *testing.T) {
|
||||
require.Equal(t, 0, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries with multiple datasourceUid, it should return correct queries",
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries with multiple datasourceUid, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", testDsUID1)
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", testDsUID2)
|
||||
@@ -114,4 +120,146 @@ func TestGetQueriesFromQueryHistory(t *testing.T) {
|
||||
require.Equal(t, 2, response.Result.TotalCount)
|
||||
require.Equal(t, true, response.Result.QueryHistory[0].Starred)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using from filter, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("from", strconv.FormatInt(time.Now().UnixMilli()-60*1000, 10))
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 3, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using relative from filter, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("from", "now-1m")
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 3, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using from filter, it should return no queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("from", strconv.FormatInt(time.Now().UnixMilli()+60*1000, 10))
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 0, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using from filter, it should return no queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("from", "now+1m")
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 0, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using to filter, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("to", strconv.FormatInt(time.Now().UnixMilli(), 10))
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 3, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using to filter, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("to", "now")
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 3, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using to filter, it should return no queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("to", strconv.FormatInt(time.Now().UnixMilli()-60*1000, 10))
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 0, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using to filter, it should return no queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("to", "now-1m")
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 0, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using from and to filter, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("to", strconv.FormatInt(time.Now().UnixMilli(), 10))
|
||||
sc.reqContext.Req.Form.Add("from", strconv.FormatInt(time.Now().UnixMilli()-60*1000, 10))
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 3, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using from and to filter with other filters, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("to", strconv.FormatInt(time.Now().UnixMilli(), 10))
|
||||
sc.reqContext.Req.Form.Add("from", strconv.FormatInt(time.Now().UnixMilli()-60*1000, 10))
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", testDsUID1)
|
||||
sc.reqContext.Req.Form.Add("searchString", "2")
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 2, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using from and to filter with other filters, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("to", "now")
|
||||
sc.reqContext.Req.Form.Add("from", "now-1m")
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", testDsUID1)
|
||||
sc.reqContext.Req.Form.Add("searchString", "2")
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 2, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries using from and to filter with other filters, it should return no query",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("to", strconv.FormatInt(time.Now().UnixMilli()-60, 10))
|
||||
sc.reqContext.Req.Form.Add("from", strconv.FormatInt(time.Now().UnixMilli()+60, 10))
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", testDsUID1)
|
||||
sc.reqContext.Req.Form.Add("searchString", "2")
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 0, response.Result.TotalCount)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -23,12 +23,16 @@ func writeStarredSQL(query SearchInQueryHistoryQuery, sqlStore *sqlstore.SQLStor
|
||||
}
|
||||
|
||||
func writeFiltersSQL(query SearchInQueryHistoryQuery, user *models.SignedInUser, sqlStore *sqlstore.SQLStore, builder *sqlstore.SQLBuilder) {
|
||||
params := []interface{}{user.OrgId, user.UserId, "%" + query.SearchString + "%", "%" + query.SearchString + "%"}
|
||||
for _, uid := range query.DatasourceUIDs {
|
||||
params = append(params, uid)
|
||||
}
|
||||
params := []interface{}{user.OrgId, user.UserId, query.From, query.To, "%" + query.SearchString + "%", "%" + query.SearchString + "%"}
|
||||
var sql bytes.Buffer
|
||||
sql.WriteString(" WHERE query_history.org_id = ? AND query_history.created_by = ? AND (query_history.queries " + sqlStore.Dialect.LikeStr() + " ? OR query_history.comment " + sqlStore.Dialect.LikeStr() + " ?) AND query_history.datasource_uid IN (? " + strings.Repeat(",?", len(query.DatasourceUIDs)-1) + ") ")
|
||||
sql.WriteString(" WHERE query_history.org_id = ? AND query_history.created_by = ? AND query_history.created_at >= ? AND query_history.created_at <= ? AND (query_history.queries " + sqlStore.Dialect.LikeStr() + " ? OR query_history.comment " + sqlStore.Dialect.LikeStr() + " ?) ")
|
||||
|
||||
if len(query.DatasourceUIDs) > 0 {
|
||||
for _, uid := range query.DatasourceUIDs {
|
||||
params = append(params, uid)
|
||||
}
|
||||
sql.WriteString(" AND query_history.datasource_uid IN (? " + strings.Repeat(",?", len(query.DatasourceUIDs)-1) + ") ")
|
||||
}
|
||||
builder.Write(sql.String(), params...)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user