mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Query History: Remove migration (#67470)
This commit is contained in:
parent
91471ac7ae
commit
b5a2c3c7f5
@ -335,62 +335,3 @@ Status codes:
|
|||||||
- **200** – OK
|
- **200** – OK
|
||||||
- **401** – Unauthorized
|
- **401** – Unauthorized
|
||||||
- **500** – Internal error
|
- **500** – Internal error
|
||||||
|
|
||||||
## Migrate queries to Query history
|
|
||||||
|
|
||||||
`POST /api/query-history/migrate`
|
|
||||||
|
|
||||||
Migrates multiple queries in to query history.
|
|
||||||
|
|
||||||
**Example request:**
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /api/query-history HTTP/1.1
|
|
||||||
Accept: application/json
|
|
||||||
Content-Type: application/json
|
|
||||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
|
||||||
{
|
|
||||||
"queries": [
|
|
||||||
{
|
|
||||||
"datasourceUid": "PE1C5CBDA0504A6A3",
|
|
||||||
"queries": [
|
|
||||||
{
|
|
||||||
"refId": "A",
|
|
||||||
"key": "Q-87fed8e3-62ba-4eb2-8d2a-4129979bb4de-0",
|
|
||||||
"scenarioId": "csv_content",
|
|
||||||
"datasource": {
|
|
||||||
"type": "testdata",
|
|
||||||
"uid": "PD8C576611E62080A"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"starred": false,
|
|
||||||
"createdAt": 1643630762,
|
|
||||||
"comment": "debugging"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
JSON body schema:
|
|
||||||
|
|
||||||
- **queries** – JSON of query history items.
|
|
||||||
|
|
||||||
**Example response:**
|
|
||||||
|
|
||||||
```http
|
|
||||||
HTTP/1.1 200
|
|
||||||
Content-Type: application/json
|
|
||||||
{
|
|
||||||
"message": "Query history successfully migrated",
|
|
||||||
"totalCount": 105,
|
|
||||||
"starredCount": 10
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Status codes:
|
|
||||||
|
|
||||||
- **200** – OK
|
|
||||||
- **400** - Errors (invalid JSON, missing or invalid fields)
|
|
||||||
- **401** – Unauthorized
|
|
||||||
- **500** – Internal error
|
|
||||||
|
@ -20,8 +20,6 @@ func (s *QueryHistoryService) registerAPIEndpoints() {
|
|||||||
entities.Post("/star/:uid", middleware.ReqSignedIn, routing.Wrap(s.starHandler))
|
entities.Post("/star/:uid", middleware.ReqSignedIn, routing.Wrap(s.starHandler))
|
||||||
entities.Delete("/star/:uid", middleware.ReqSignedIn, routing.Wrap(s.unstarHandler))
|
entities.Delete("/star/:uid", middleware.ReqSignedIn, routing.Wrap(s.unstarHandler))
|
||||||
entities.Patch("/:uid", middleware.ReqSignedIn, routing.Wrap(s.patchCommentHandler))
|
entities.Patch("/:uid", middleware.ReqSignedIn, routing.Wrap(s.patchCommentHandler))
|
||||||
// Remove migrate endpoint in Grafana v10 as breaking change
|
|
||||||
entities.Post("/migrate", middleware.ReqSignedIn, routing.Wrap(s.migrateHandler))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,31 +187,6 @@ func (s *QueryHistoryService) unstarHandler(c *contextmodel.ReqContext) response
|
|||||||
return response.JSON(http.StatusOK, QueryHistoryResponse{Result: query})
|
return response.JSON(http.StatusOK, QueryHistoryResponse{Result: query})
|
||||||
}
|
}
|
||||||
|
|
||||||
// swagger:route POST /query-history/migrate query_history migrateQueries
|
|
||||||
//
|
|
||||||
// Migrate queries to query history.
|
|
||||||
//
|
|
||||||
// Adds multiple queries to query history.
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: getQueryHistoryMigrationResponse
|
|
||||||
// 400: badRequestError
|
|
||||||
// 401: unauthorisedError
|
|
||||||
// 500: internalServerError
|
|
||||||
func (s *QueryHistoryService) migrateHandler(c *contextmodel.ReqContext) response.Response {
|
|
||||||
cmd := MigrateQueriesToQueryHistoryCommand{}
|
|
||||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
|
||||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
totalCount, starredCount, err := s.MigrateQueriesToQueryHistory(c.Req.Context(), c.SignedInUser, cmd)
|
|
||||||
if err != nil {
|
|
||||||
return response.Error(http.StatusInternalServerError, "Failed to migrate query history", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.JSON(http.StatusOK, QueryHistoryMigrationResponse{Message: "Query history successfully migrated", TotalCount: totalCount, StarredCount: starredCount})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters starQuery patchQueryComment deleteQuery unstarQuery
|
// swagger:parameters starQuery patchQueryComment deleteQuery unstarQuery
|
||||||
type QueryHistoryByUID struct {
|
type QueryHistoryByUID struct {
|
||||||
// in:path
|
// in:path
|
||||||
@ -275,13 +248,6 @@ type PatchQueryCommentParams struct {
|
|||||||
Body PatchQueryCommentInQueryHistoryCommand `json:"body"`
|
Body PatchQueryCommentInQueryHistoryCommand `json:"body"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// swagger:parameters migrateQueries
|
|
||||||
type MigrateQueriesParams struct {
|
|
||||||
// in:body
|
|
||||||
// required:true
|
|
||||||
Body MigrateQueriesToQueryHistoryCommand `json:"body"`
|
|
||||||
}
|
|
||||||
|
|
||||||
//swagger:response getQueryHistorySearchResponse
|
//swagger:response getQueryHistorySearchResponse
|
||||||
type GetQueryHistorySearchResponse struct {
|
type GetQueryHistorySearchResponse struct {
|
||||||
// in: body
|
// in: body
|
||||||
@ -299,9 +265,3 @@ type GetQueryHistoryDeleteQueryResponse struct {
|
|||||||
// in: body
|
// in: body
|
||||||
Body QueryHistoryDeleteQueryResponse `json:"body"`
|
Body QueryHistoryDeleteQueryResponse `json:"body"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// swagger:response getQueryHistoryMigrationResponse
|
|
||||||
type GetQueryHistoryMigrationResponse struct {
|
|
||||||
// in: body
|
|
||||||
Body QueryHistoryMigrationResponse `json:"body"`
|
|
||||||
}
|
|
||||||
|
@ -2,7 +2,6 @@ package queryhistory
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/db"
|
"github.com/grafana/grafana/pkg/infra/db"
|
||||||
@ -271,65 +270,6 @@ func (s QueryHistoryService) unstarQuery(ctx context.Context, user *user.SignedI
|
|||||||
return dto, nil
|
return dto, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// migrateQueries adds multiple queries into query history
|
|
||||||
func (s QueryHistoryService) migrateQueries(ctx context.Context, usr *user.SignedInUser, cmd MigrateQueriesToQueryHistoryCommand) (int, int, error) {
|
|
||||||
queryHistories := make([]*QueryHistory, 0, len(cmd.Queries))
|
|
||||||
starredQueries := make([]*QueryHistoryStar, 0)
|
|
||||||
|
|
||||||
err := s.store.WithTransactionalDbSession(ctx, func(session *db.Session) error {
|
|
||||||
for _, query := range cmd.Queries {
|
|
||||||
uid := util.GenerateShortUID()
|
|
||||||
queryHistories = append(queryHistories, &QueryHistory{
|
|
||||||
OrgID: usr.OrgID,
|
|
||||||
UID: uid,
|
|
||||||
Queries: query.Queries,
|
|
||||||
DatasourceUID: query.DatasourceUID,
|
|
||||||
CreatedBy: usr.UserID,
|
|
||||||
CreatedAt: query.CreatedAt,
|
|
||||||
Comment: query.Comment,
|
|
||||||
})
|
|
||||||
|
|
||||||
if query.Starred {
|
|
||||||
starredQueries = append(starredQueries, &QueryHistoryStar{
|
|
||||||
UserID: usr.UserID,
|
|
||||||
QueryUID: uid,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
batchSize := 50
|
|
||||||
var err error
|
|
||||||
for i := 0; i < len(queryHistories); i += batchSize {
|
|
||||||
j := i + batchSize
|
|
||||||
if j > len(queryHistories) {
|
|
||||||
j = len(queryHistories)
|
|
||||||
}
|
|
||||||
_, err = session.InsertMulti(queryHistories[i:j])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(starredQueries); i += batchSize {
|
|
||||||
j := i + batchSize
|
|
||||||
if j > len(starredQueries) {
|
|
||||||
j = len(starredQueries)
|
|
||||||
}
|
|
||||||
_, err = session.InsertMulti(starredQueries[i:j])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, fmt.Errorf("failed to migrate query history: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return len(queryHistories), len(starredQueries), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s QueryHistoryService) deleteStaleQueries(ctx context.Context, olderThan int64) (int, error) {
|
func (s QueryHistoryService) deleteStaleQueries(ctx context.Context, olderThan int64) (int, error) {
|
||||||
var rowsCount int64
|
var rowsCount int64
|
||||||
|
|
||||||
|
@ -74,20 +74,6 @@ type QueryHistoryDeleteQueryResponse struct {
|
|||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type QueryToMigrate struct {
|
|
||||||
DatasourceUID string `json:"datasourceUid"`
|
|
||||||
Queries *simplejson.Json `json:"queries"`
|
|
||||||
CreatedAt int64 `json:"createdAt"`
|
|
||||||
Comment string `json:"comment"`
|
|
||||||
Starred bool `json:"starred"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueryHistoryMigrationResponse struct {
|
|
||||||
Message string `json:"message"`
|
|
||||||
TotalCount int `json:"totalCount"`
|
|
||||||
StarredCount int `json:"starredCount"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateQueryInQueryHistoryCommand is the command for adding query history
|
// CreateQueryInQueryHistoryCommand is the command for adding query history
|
||||||
// swagger:model
|
// swagger:model
|
||||||
type CreateQueryInQueryHistoryCommand struct {
|
type CreateQueryInQueryHistoryCommand struct {
|
||||||
@ -105,10 +91,3 @@ type PatchQueryCommentInQueryHistoryCommand struct {
|
|||||||
// Updated comment
|
// Updated comment
|
||||||
Comment string `json:"comment"`
|
Comment string `json:"comment"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MigrateQueriesToQueryHistoryCommand is the command used for migration of old queries into query history
|
|
||||||
// swagger:model
|
|
||||||
type MigrateQueriesToQueryHistoryCommand struct {
|
|
||||||
// Array of queries to store in query history.
|
|
||||||
Queries []QueryToMigrate `json:"queries"`
|
|
||||||
}
|
|
||||||
|
@ -35,7 +35,6 @@ type Service interface {
|
|||||||
PatchQueryCommentInQueryHistory(ctx context.Context, user *user.SignedInUser, UID string, cmd PatchQueryCommentInQueryHistoryCommand) (QueryHistoryDTO, error)
|
PatchQueryCommentInQueryHistory(ctx context.Context, user *user.SignedInUser, UID string, cmd PatchQueryCommentInQueryHistoryCommand) (QueryHistoryDTO, error)
|
||||||
StarQueryInQueryHistory(ctx context.Context, user *user.SignedInUser, UID string) (QueryHistoryDTO, error)
|
StarQueryInQueryHistory(ctx context.Context, user *user.SignedInUser, UID string) (QueryHistoryDTO, error)
|
||||||
UnstarQueryInQueryHistory(ctx context.Context, user *user.SignedInUser, UID string) (QueryHistoryDTO, error)
|
UnstarQueryInQueryHistory(ctx context.Context, user *user.SignedInUser, UID string) (QueryHistoryDTO, error)
|
||||||
MigrateQueriesToQueryHistory(ctx context.Context, user *user.SignedInUser, cmd MigrateQueriesToQueryHistoryCommand) (int, int, error)
|
|
||||||
DeleteStaleQueriesInQueryHistory(ctx context.Context, olderThan int64) (int, error)
|
DeleteStaleQueriesInQueryHistory(ctx context.Context, olderThan int64) (int, error)
|
||||||
EnforceRowLimitInQueryHistory(ctx context.Context, limit int, starredQueries bool) (int, error)
|
EnforceRowLimitInQueryHistory(ctx context.Context, limit int, starredQueries bool) (int, error)
|
||||||
}
|
}
|
||||||
@ -72,10 +71,6 @@ func (s QueryHistoryService) UnstarQueryInQueryHistory(ctx context.Context, user
|
|||||||
return s.unstarQuery(ctx, user, UID)
|
return s.unstarQuery(ctx, user, UID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s QueryHistoryService) MigrateQueriesToQueryHistory(ctx context.Context, user *user.SignedInUser, cmd MigrateQueriesToQueryHistoryCommand) (int, int, error) {
|
|
||||||
return s.migrateQueries(ctx, user, cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s QueryHistoryService) DeleteStaleQueriesInQueryHistory(ctx context.Context, olderThan int64) (int, error) {
|
func (s QueryHistoryService) DeleteStaleQueriesInQueryHistory(ctx context.Context, olderThan int64) (int, error) {
|
||||||
return s.deleteStaleQueries(ctx, olderThan)
|
return s.deleteStaleQueries(ctx, olderThan)
|
||||||
}
|
}
|
||||||
|
@ -1,120 +0,0 @@
|
|||||||
package queryhistory
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIntegrationMigrateQueriesToQueryHistory(t *testing.T) {
|
|
||||||
if testing.Short() {
|
|
||||||
t.Skip("skipping integration test")
|
|
||||||
}
|
|
||||||
testScenario(t, "When users tries to migrate 1 query in query history it should succeed",
|
|
||||||
func(t *testing.T, sc scenarioContext) {
|
|
||||||
command := MigrateQueriesToQueryHistoryCommand{
|
|
||||||
Queries: []QueryToMigrate{
|
|
||||||
{
|
|
||||||
DatasourceUID: "NCzh67i",
|
|
||||||
Queries: simplejson.NewFromAny(map[string]interface{}{
|
|
||||||
"expr": "test",
|
|
||||||
}),
|
|
||||||
Comment: "",
|
|
||||||
Starred: false,
|
|
||||||
CreatedAt: sc.service.now().Unix(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
|
||||||
resp := sc.service.migrateHandler(sc.reqContext)
|
|
||||||
var response QueryHistoryMigrationResponse
|
|
||||||
err := json.Unmarshal(resp.Body(), &response)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 200, resp.Status())
|
|
||||||
require.Equal(t, "Query history successfully migrated", response.Message)
|
|
||||||
require.Equal(t, 1, response.TotalCount)
|
|
||||||
require.Equal(t, 0, response.StarredCount)
|
|
||||||
})
|
|
||||||
|
|
||||||
testScenario(t, "When users tries to migrate multiple queries in query history it should succeed",
|
|
||||||
func(t *testing.T, sc scenarioContext) {
|
|
||||||
command := MigrateQueriesToQueryHistoryCommand{
|
|
||||||
Queries: []QueryToMigrate{
|
|
||||||
{
|
|
||||||
DatasourceUID: "NCzh67i",
|
|
||||||
Queries: simplejson.NewFromAny(map[string]interface{}{
|
|
||||||
"expr": "test1",
|
|
||||||
}),
|
|
||||||
Comment: "",
|
|
||||||
Starred: false,
|
|
||||||
CreatedAt: sc.service.now().Unix(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
DatasourceUID: "NCzh67i",
|
|
||||||
Queries: simplejson.NewFromAny(map[string]interface{}{
|
|
||||||
"expr": "test2",
|
|
||||||
}),
|
|
||||||
Comment: "",
|
|
||||||
Starred: false,
|
|
||||||
CreatedAt: sc.service.now().Unix() - int64(100),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
DatasourceUID: "ABch68f",
|
|
||||||
Queries: simplejson.NewFromAny(map[string]interface{}{
|
|
||||||
"expr": "test3",
|
|
||||||
}),
|
|
||||||
Comment: "",
|
|
||||||
Starred: false,
|
|
||||||
CreatedAt: sc.service.now().Unix() - int64(1000),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
|
||||||
resp := sc.service.migrateHandler(sc.reqContext)
|
|
||||||
var response QueryHistoryMigrationResponse
|
|
||||||
err := json.Unmarshal(resp.Body(), &response)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 200, resp.Status())
|
|
||||||
require.Equal(t, "Query history successfully migrated", response.Message)
|
|
||||||
require.Equal(t, 3, response.TotalCount)
|
|
||||||
require.Equal(t, 0, response.StarredCount)
|
|
||||||
})
|
|
||||||
|
|
||||||
testScenario(t, "When users tries to migrate starred and not starred query in query history it should succeed",
|
|
||||||
func(t *testing.T, sc scenarioContext) {
|
|
||||||
command := MigrateQueriesToQueryHistoryCommand{
|
|
||||||
Queries: []QueryToMigrate{
|
|
||||||
{
|
|
||||||
DatasourceUID: "NCzh67i",
|
|
||||||
Queries: simplejson.NewFromAny(map[string]interface{}{
|
|
||||||
"expr": "test1",
|
|
||||||
}),
|
|
||||||
Comment: "",
|
|
||||||
Starred: true,
|
|
||||||
CreatedAt: sc.service.now().Unix(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
DatasourceUID: "NCzh67i",
|
|
||||||
Queries: simplejson.NewFromAny(map[string]interface{}{
|
|
||||||
"expr": "test2",
|
|
||||||
}),
|
|
||||||
Comment: "",
|
|
||||||
Starred: false,
|
|
||||||
CreatedAt: sc.service.now().Unix() - int64(100),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
|
||||||
resp := sc.service.migrateHandler(sc.reqContext)
|
|
||||||
var response QueryHistoryMigrationResponse
|
|
||||||
err := json.Unmarshal(resp.Body(), &response)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 200, resp.Status())
|
|
||||||
require.Equal(t, "Query history successfully migrated", response.Message)
|
|
||||||
require.Equal(t, 2, response.TotalCount)
|
|
||||||
require.Equal(t, 1, response.StarredCount)
|
|
||||||
})
|
|
||||||
}
|
|
@ -7736,40 +7736,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/query-history/migrate": {
|
|
||||||
"post": {
|
|
||||||
"description": "Adds multiple queries to query history.",
|
|
||||||
"tags": [
|
|
||||||
"query_history"
|
|
||||||
],
|
|
||||||
"summary": "Migrate queries to query history.",
|
|
||||||
"operationId": "migrateQueries",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "body",
|
|
||||||
"in": "body",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/MigrateQueriesToQueryHistoryCommand"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "#/responses/getQueryHistoryMigrationResponse"
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"$ref": "#/responses/badRequestError"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "#/responses/unauthorisedError"
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"$ref": "#/responses/internalServerError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/query-history/star/{query_history_uid}": {
|
"/query-history/star/{query_history_uid}": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "Adds star to query in query history as specified by the UID.",
|
"description": "Adds star to query in query history as specified by the UID.",
|
||||||
@ -15042,19 +15008,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"MigrateQueriesToQueryHistoryCommand": {
|
|
||||||
"description": "MigrateQueriesToQueryHistoryCommand is the command used for migration of old queries into query history",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"queries": {
|
|
||||||
"description": "Array of queries to store in query history.",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/QueryToMigrate"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"MoveFolderCommand": {
|
"MoveFolderCommand": {
|
||||||
"description": "MoveFolderCommand captures the information required by the folder service\nto move a folder.",
|
"description": "MoveFolderCommand captures the information required by the folder service\nto move a folder.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -16406,22 +16359,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"QueryHistoryMigrationResponse": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"message": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"starredCount": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int64"
|
|
||||||
},
|
|
||||||
"totalCount": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int64"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"QueryHistoryPreference": {
|
"QueryHistoryPreference": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -16554,27 +16491,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"QueryToMigrate": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"comment": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int64"
|
|
||||||
},
|
|
||||||
"datasourceUid": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"queries": {
|
|
||||||
"$ref": "#/definitions/Json"
|
|
||||||
},
|
|
||||||
"starred": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"QuotaDTO": {
|
"QuotaDTO": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -173,18 +173,6 @@ describe('RichHistoryRemoteStorage', () => {
|
|||||||
} as Partial<UserPreferencesDTO>);
|
} as Partial<UserPreferencesDTO>);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('migrates provided rich history items', async () => {
|
|
||||||
const { richHistoryQuery, dto } = setup();
|
|
||||||
fetchMock.mockReturnValue(of({}));
|
|
||||||
await storage.migrate([richHistoryQuery]);
|
|
||||||
expect(fetchMock).toBeCalledWith({
|
|
||||||
url: '/api/query-history/migrate',
|
|
||||||
method: 'POST',
|
|
||||||
data: { queries: [dto] },
|
|
||||||
showSuccessAlert: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('stars query history items', async () => {
|
it('stars query history items', async () => {
|
||||||
const { richHistoryQuery, dto } = setup();
|
const { richHistoryQuery, dto } = setup();
|
||||||
postMock.mockResolvedValue({
|
postMock.mockResolvedValue({
|
||||||
|
@ -8,7 +8,7 @@ import { PreferencesService } from '../services/PreferencesService';
|
|||||||
import { RichHistorySearchFilters, RichHistorySettings, SortOrder } from '../utils/richHistoryTypes';
|
import { RichHistorySearchFilters, RichHistorySettings, SortOrder } from '../utils/richHistoryTypes';
|
||||||
|
|
||||||
import RichHistoryStorage, { RichHistoryStorageWarningDetails } from './RichHistoryStorage';
|
import RichHistoryStorage, { RichHistoryStorageWarningDetails } from './RichHistoryStorage';
|
||||||
import { fromDTO, toDTO } from './remoteStorageConverter';
|
import { fromDTO } from './remoteStorageConverter';
|
||||||
|
|
||||||
export type RichHistoryRemoteStorageDTO = {
|
export type RichHistoryRemoteStorageDTO = {
|
||||||
uid: string;
|
uid: string;
|
||||||
@ -19,18 +19,6 @@ export type RichHistoryRemoteStorageDTO = {
|
|||||||
queries: DataQuery[];
|
queries: DataQuery[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type RichHistoryRemoteStorageMigrationDTO = {
|
|
||||||
datasourceUid: string;
|
|
||||||
queries: DataQuery[];
|
|
||||||
createdAt: number;
|
|
||||||
starred: boolean;
|
|
||||||
comment: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type RichHistoryRemoteStorageMigrationPayloadDTO = {
|
|
||||||
queries: RichHistoryRemoteStorageMigrationDTO[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type RichHistoryRemoteStorageResultsPayloadDTO = {
|
type RichHistoryRemoteStorageResultsPayloadDTO = {
|
||||||
result: {
|
result: {
|
||||||
queryHistory: RichHistoryRemoteStorageDTO[];
|
queryHistory: RichHistoryRemoteStorageDTO[];
|
||||||
@ -122,21 +110,6 @@ export default class RichHistoryRemoteStorage implements RichHistoryStorage {
|
|||||||
}
|
}
|
||||||
return fromDTO(dto.result);
|
return fromDTO(dto.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal Used only for migration purposes. Will be removed in future.
|
|
||||||
*/
|
|
||||||
async migrate(richHistory: RichHistoryQuery[]) {
|
|
||||||
const data: RichHistoryRemoteStorageMigrationPayloadDTO = { queries: richHistory.map(toDTO) };
|
|
||||||
await lastValueFrom(
|
|
||||||
getBackendSrv().fetch({
|
|
||||||
url: '/api/query-history/migrate',
|
|
||||||
method: 'POST',
|
|
||||||
data,
|
|
||||||
showSuccessAlert: false,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildQueryParams(filters: RichHistorySearchFilters): string {
|
function buildQueryParams(filters: RichHistorySearchFilters): string {
|
||||||
|
@ -96,5 +96,4 @@ export const RICH_HISTORY_SETTING_KEYS = {
|
|||||||
starredTabAsFirstTab: 'grafana.explore.richHistory.starredTabAsFirstTab',
|
starredTabAsFirstTab: 'grafana.explore.richHistory.starredTabAsFirstTab',
|
||||||
activeDatasourceOnly: 'grafana.explore.richHistory.activeDatasourceOnly',
|
activeDatasourceOnly: 'grafana.explore.richHistory.activeDatasourceOnly',
|
||||||
datasourceFilters: 'grafana.explore.richHistory.datasourceFilters',
|
datasourceFilters: 'grafana.explore.richHistory.datasourceFilters',
|
||||||
migrated: 'grafana.explore.richHistory.migrated',
|
|
||||||
};
|
};
|
||||||
|
@ -13,9 +13,7 @@ import {
|
|||||||
createQueryHeading,
|
createQueryHeading,
|
||||||
deleteAllFromRichHistory,
|
deleteAllFromRichHistory,
|
||||||
deleteQueryInRichHistory,
|
deleteQueryInRichHistory,
|
||||||
migrateQueryHistoryFromLocalStorage,
|
|
||||||
SortOrder,
|
SortOrder,
|
||||||
LocalStorageMigrationStatus,
|
|
||||||
} from './richHistory';
|
} from './richHistory';
|
||||||
|
|
||||||
const richHistoryStorageMock: RichHistoryStorage = {} as RichHistoryStorage;
|
const richHistoryStorageMock: RichHistoryStorage = {} as RichHistoryStorage;
|
||||||
@ -179,35 +177,6 @@ describe('richHistory', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('migration', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
richHistoryRemoteStorageMock.migrate.mockReset();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('migrates history', async () => {
|
|
||||||
const history = { richHistory: [{ id: 'test' }, { id: 'test2' }], total: 2 };
|
|
||||||
|
|
||||||
richHistoryLocalStorageMock.getRichHistory.mockReturnValue(history);
|
|
||||||
const migrationResult = await migrateQueryHistoryFromLocalStorage();
|
|
||||||
expect(richHistoryRemoteStorageMock.migrate).toBeCalledWith(history.richHistory);
|
|
||||||
expect(migrationResult.status).toBe(LocalStorageMigrationStatus.Successful);
|
|
||||||
expect(migrationResult.error).toBeUndefined();
|
|
||||||
});
|
|
||||||
it('does not migrate if there are no entries', async () => {
|
|
||||||
richHistoryLocalStorageMock.getRichHistory.mockReturnValue({ richHistory: [] });
|
|
||||||
const migrationResult = await migrateQueryHistoryFromLocalStorage();
|
|
||||||
expect(richHistoryRemoteStorageMock.migrate).not.toBeCalled();
|
|
||||||
expect(migrationResult.status).toBe(LocalStorageMigrationStatus.NotNeeded);
|
|
||||||
expect(migrationResult.error).toBeUndefined();
|
|
||||||
});
|
|
||||||
it('propagates thrown errors', async () => {
|
|
||||||
richHistoryLocalStorageMock.getRichHistory.mockRejectedValue(new Error('migration failed'));
|
|
||||||
const migrationResult = await migrateQueryHistoryFromLocalStorage();
|
|
||||||
expect(migrationResult.status).toBe(LocalStorageMigrationStatus.Failed);
|
|
||||||
expect(migrationResult.error?.message).toBe('migration failed');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('mapNumbertoTimeInSlider', () => {
|
describe('mapNumbertoTimeInSlider', () => {
|
||||||
it('should correctly map number to value', () => {
|
it('should correctly map number to value', () => {
|
||||||
const value = mapNumbertoTimeInSlider(25);
|
const value = mapNumbertoTimeInSlider(25);
|
||||||
|
@ -4,17 +4,11 @@ import { DataQuery, DataSourceApi, dateTimeFormat, ExploreUrlState, urlUtil } fr
|
|||||||
import { serializeStateToUrlParam } from '@grafana/data/src/utils/url';
|
import { serializeStateToUrlParam } from '@grafana/data/src/utils/url';
|
||||||
import { getDataSourceSrv } from '@grafana/runtime';
|
import { getDataSourceSrv } from '@grafana/runtime';
|
||||||
import { notifyApp } from 'app/core/actions';
|
import { notifyApp } from 'app/core/actions';
|
||||||
import {
|
import { createErrorNotification, createWarningNotification } from 'app/core/copy/appNotification';
|
||||||
createErrorNotification,
|
|
||||||
createSuccessNotification,
|
|
||||||
createWarningNotification,
|
|
||||||
} from 'app/core/copy/appNotification';
|
|
||||||
import { dispatch } from 'app/store/store';
|
import { dispatch } from 'app/store/store';
|
||||||
import { RichHistoryQuery } from 'app/types/explore';
|
import { RichHistoryQuery } from 'app/types/explore';
|
||||||
|
|
||||||
import { config } from '../config';
|
import { config } from '../config';
|
||||||
import RichHistoryLocalStorage from '../history/RichHistoryLocalStorage';
|
|
||||||
import RichHistoryRemoteStorage from '../history/RichHistoryRemoteStorage';
|
|
||||||
import {
|
import {
|
||||||
RichHistoryResults,
|
RichHistoryResults,
|
||||||
RichHistoryServiceError,
|
RichHistoryServiceError,
|
||||||
@ -134,43 +128,6 @@ export async function deleteQueryInRichHistory(id: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum LocalStorageMigrationStatus {
|
|
||||||
Successful = 'successful',
|
|
||||||
Failed = 'failed',
|
|
||||||
NotNeeded = 'not-needed',
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LocalStorageMigrationResult {
|
|
||||||
status: LocalStorageMigrationStatus;
|
|
||||||
error?: Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function migrateQueryHistoryFromLocalStorage(): Promise<LocalStorageMigrationResult> {
|
|
||||||
const richHistoryLocalStorage = new RichHistoryLocalStorage();
|
|
||||||
const richHistoryRemoteStorage = new RichHistoryRemoteStorage();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { richHistory } = await richHistoryLocalStorage.getRichHistory({
|
|
||||||
datasourceFilters: [],
|
|
||||||
from: 0,
|
|
||||||
search: '',
|
|
||||||
sortOrder: SortOrder.Descending,
|
|
||||||
starred: false,
|
|
||||||
to: 14,
|
|
||||||
});
|
|
||||||
if (richHistory.length === 0) {
|
|
||||||
return { status: LocalStorageMigrationStatus.NotNeeded };
|
|
||||||
}
|
|
||||||
await richHistoryRemoteStorage.migrate(richHistory);
|
|
||||||
dispatch(notifyApp(createSuccessNotification('Query history successfully migrated from local storage')));
|
|
||||||
return { status: LocalStorageMigrationStatus.Successful };
|
|
||||||
} catch (error) {
|
|
||||||
const errorToThrow = error instanceof Error ? error : new Error('Uknown error occurred.');
|
|
||||||
dispatch(notifyApp(createWarningNotification(`Query history migration failed. ${errorToThrow.message}`)));
|
|
||||||
return { status: LocalStorageMigrationStatus.Failed, error: errorToThrow };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createUrlFromRichHistory = (query: RichHistoryQuery) => {
|
export const createUrlFromRichHistory = (query: RichHistoryQuery) => {
|
||||||
const exploreState: ExploreUrlState = {
|
const exploreState: ExploreUrlState = {
|
||||||
/* Default range, as we are not saving timerange in rich history */
|
/* Default range, as we are not saving timerange in rich history */
|
||||||
|
@ -61,7 +61,6 @@ function setup(queries: DataQuery[]) {
|
|||||||
right: undefined,
|
right: undefined,
|
||||||
richHistoryStorageFull: false,
|
richHistoryStorageFull: false,
|
||||||
richHistoryLimitExceededWarningShown: false,
|
richHistoryLimitExceededWarningShown: false,
|
||||||
richHistoryMigrationFailed: false,
|
|
||||||
};
|
};
|
||||||
const store = configureStore({ explore: initialState, user: { orgId: 1 } as UserState });
|
const store = configureStore({ explore: initialState, user: { orgId: 1 } as UserState });
|
||||||
|
|
||||||
|
@ -22,8 +22,6 @@ import { lastUsedDatasourceKeyForOrgId } from 'app/core/utils/explore';
|
|||||||
import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
|
import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
|
||||||
import { configureStore } from 'app/store/configureStore';
|
import { configureStore } from 'app/store/configureStore';
|
||||||
|
|
||||||
import { RICH_HISTORY_KEY, RichHistoryLocalStorageDTO } from '../../../../core/history/RichHistoryLocalStorage';
|
|
||||||
import { RICH_HISTORY_SETTING_KEYS } from '../../../../core/history/richHistoryLocalStorageUtils';
|
|
||||||
import { LokiDatasource } from '../../../../plugins/datasource/loki/datasource';
|
import { LokiDatasource } from '../../../../plugins/datasource/loki/datasource';
|
||||||
import { LokiQuery } from '../../../../plugins/datasource/loki/types';
|
import { LokiQuery } from '../../../../plugins/datasource/loki/types';
|
||||||
import { ExploreId } from '../../../../types';
|
import { ExploreId } from '../../../../types';
|
||||||
@ -196,18 +194,3 @@ export const withinExplore = (exploreId: ExploreId) => {
|
|||||||
const container = screen.getAllByTestId('data-testid Explore');
|
const container = screen.getAllByTestId('data-testid Explore');
|
||||||
return within(container[exploreId === ExploreId.left ? 0 : 1]);
|
return within(container[exploreId === ExploreId.left ? 0 : 1]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const localStorageHasAlreadyBeenMigrated = () => {
|
|
||||||
window.localStorage.setItem(RICH_HISTORY_SETTING_KEYS.migrated, 'true');
|
|
||||||
};
|
|
||||||
|
|
||||||
export const setupLocalStorageRichHistory = (dsName: string) => {
|
|
||||||
const richHistoryDTO: RichHistoryLocalStorageDTO = {
|
|
||||||
ts: Date.now(),
|
|
||||||
datasourceName: dsName,
|
|
||||||
starred: true,
|
|
||||||
comment: '',
|
|
||||||
queries: [{ refId: 'A' }],
|
|
||||||
};
|
|
||||||
window.localStorage.setItem(RICH_HISTORY_KEY, JSON.stringify([richHistoryDTO]));
|
|
||||||
};
|
|
||||||
|
@ -31,13 +31,7 @@ import {
|
|||||||
switchToQueryHistoryTab,
|
switchToQueryHistoryTab,
|
||||||
} from './helper/interactions';
|
} from './helper/interactions';
|
||||||
import { makeLogsQueryResponse } from './helper/query';
|
import { makeLogsQueryResponse } from './helper/query';
|
||||||
import {
|
import { setupExplore, tearDown, waitForExplore } from './helper/setup';
|
||||||
localStorageHasAlreadyBeenMigrated,
|
|
||||||
setupExplore,
|
|
||||||
setupLocalStorageRichHistory,
|
|
||||||
tearDown,
|
|
||||||
waitForExplore,
|
|
||||||
} from './helper/setup';
|
|
||||||
|
|
||||||
const fetchMock = jest.fn();
|
const fetchMock = jest.fn();
|
||||||
const postMock = jest.fn();
|
const postMock = jest.fn();
|
||||||
@ -225,56 +219,8 @@ describe('Explore: Query History', () => {
|
|||||||
assertDataSourceFilterVisibility(false);
|
assertDataSourceFilterVisibility(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('local storage migration', () => {
|
|
||||||
it('does not migrate if query history is not enabled', async () => {
|
|
||||||
config.queryHistoryEnabled = false;
|
|
||||||
const { datasources } = setupExplore();
|
|
||||||
setupLocalStorageRichHistory('loki');
|
|
||||||
(datasources.loki.query as jest.Mock).mockReturnValueOnce(makeLogsQueryResponse());
|
|
||||||
getMock.mockReturnValue({ result: { queryHistory: [] } });
|
|
||||||
await waitForExplore();
|
|
||||||
|
|
||||||
await openQueryHistory();
|
|
||||||
expect(postMock).not.toBeCalledWith('/api/query-history/migrate', { queries: [] });
|
|
||||||
expect(reportInteractionMock).toBeCalledWith('grafana_explore_query_history_opened', {
|
|
||||||
queryHistoryEnabled: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('migrates query history from local storage', async () => {
|
|
||||||
config.queryHistoryEnabled = true;
|
|
||||||
const { datasources } = setupExplore();
|
|
||||||
setupLocalStorageRichHistory('loki');
|
|
||||||
(datasources.loki.query as jest.Mock).mockReturnValueOnce(makeLogsQueryResponse());
|
|
||||||
fetchMock.mockReturnValue(of({ data: { result: { queryHistory: [] } } }));
|
|
||||||
await waitForExplore();
|
|
||||||
|
|
||||||
await openQueryHistory();
|
|
||||||
expect(fetchMock).toBeCalledWith(
|
|
||||||
expect.objectContaining({
|
|
||||||
url: expect.stringMatching('/api/query-history/migrate'),
|
|
||||||
data: { queries: [expect.objectContaining({ datasourceUid: 'loki-uid' })] },
|
|
||||||
})
|
|
||||||
);
|
|
||||||
fetchMock.mockReset();
|
|
||||||
fetchMock.mockReturnValue(of({ data: { result: { queryHistory: [] } } }));
|
|
||||||
|
|
||||||
await closeQueryHistory();
|
|
||||||
await openQueryHistory();
|
|
||||||
expect(fetchMock).not.toBeCalledWith(
|
|
||||||
expect.objectContaining({
|
|
||||||
url: expect.stringMatching('/api/query-history/migrate'),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
expect(reportInteractionMock).toBeCalledWith('grafana_explore_query_history_opened', {
|
|
||||||
queryHistoryEnabled: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('pagination', async () => {
|
it('pagination', async () => {
|
||||||
config.queryHistoryEnabled = true;
|
config.queryHistoryEnabled = true;
|
||||||
localStorageHasAlreadyBeenMigrated();
|
|
||||||
const { datasources } = setupExplore();
|
const { datasources } = setupExplore();
|
||||||
(datasources.loki.query as jest.Mock).mockReturnValueOnce(makeLogsQueryResponse());
|
(datasources.loki.query as jest.Mock).mockReturnValueOnce(makeLogsQueryResponse());
|
||||||
fetchMock.mockReturnValue(
|
fetchMock.mockReturnValue(
|
||||||
|
@ -1,18 +1,13 @@
|
|||||||
import { AnyAction, createAction } from '@reduxjs/toolkit';
|
import { AnyAction, createAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import { HistoryItem } from '@grafana/data';
|
import { HistoryItem } from '@grafana/data';
|
||||||
import { config, logError } from '@grafana/runtime';
|
|
||||||
import { DataQuery } from '@grafana/schema';
|
import { DataQuery } from '@grafana/schema';
|
||||||
import { RICH_HISTORY_SETTING_KEYS } from 'app/core/history/richHistoryLocalStorageUtils';
|
|
||||||
import store from 'app/core/store';
|
|
||||||
import {
|
import {
|
||||||
addToRichHistory,
|
addToRichHistory,
|
||||||
deleteAllFromRichHistory,
|
deleteAllFromRichHistory,
|
||||||
deleteQueryInRichHistory,
|
deleteQueryInRichHistory,
|
||||||
getRichHistory,
|
getRichHistory,
|
||||||
getRichHistorySettings,
|
getRichHistorySettings,
|
||||||
LocalStorageMigrationStatus,
|
|
||||||
migrateQueryHistoryFromLocalStorage,
|
|
||||||
updateCommentInRichHistory,
|
updateCommentInRichHistory,
|
||||||
updateRichHistorySettings,
|
updateRichHistorySettings,
|
||||||
updateStarredInRichHistory,
|
updateStarredInRichHistory,
|
||||||
@ -24,7 +19,6 @@ import { RichHistorySearchFilters, RichHistorySettings } from '../../../core/uti
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
richHistoryLimitExceededAction,
|
richHistoryLimitExceededAction,
|
||||||
richHistoryMigrationFailedAction,
|
|
||||||
richHistorySearchFiltersUpdatedAction,
|
richHistorySearchFiltersUpdatedAction,
|
||||||
richHistorySettingsUpdatedAction,
|
richHistorySettingsUpdatedAction,
|
||||||
richHistoryStorageFullAction,
|
richHistoryStorageFullAction,
|
||||||
@ -173,21 +167,6 @@ export const clearRichHistoryResults = (exploreId: ExploreId): ThunkResult<void>
|
|||||||
*/
|
*/
|
||||||
export const initRichHistory = (): ThunkResult<void> => {
|
export const initRichHistory = (): ThunkResult<void> => {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const queriesMigrated = store.getBool(RICH_HISTORY_SETTING_KEYS.migrated, false);
|
|
||||||
const migrationFailedDuringThisSession = getState().explore.richHistoryMigrationFailed;
|
|
||||||
|
|
||||||
// Query history migration should always be successful, but in case of unexpected errors we ensure
|
|
||||||
// the migration attempt happens only once per session, and the user is informed about the failure
|
|
||||||
// in a way that can help with potential investigation.
|
|
||||||
if (config.queryHistoryEnabled && !queriesMigrated && !migrationFailedDuringThisSession) {
|
|
||||||
const migrationResult = await migrateQueryHistoryFromLocalStorage();
|
|
||||||
if (migrationResult.status === LocalStorageMigrationStatus.Failed) {
|
|
||||||
dispatch(richHistoryMigrationFailedAction());
|
|
||||||
logError(migrationResult.error!, { explore: { event: 'QueryHistoryMigrationFailed' } });
|
|
||||||
} else {
|
|
||||||
store.set(RICH_HISTORY_SETTING_KEYS.migrated, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let settings = getState().explore.richHistorySettings;
|
let settings = getState().explore.richHistorySettings;
|
||||||
if (!settings) {
|
if (!settings) {
|
||||||
settings = await getRichHistorySettings();
|
settings = await getRichHistorySettings();
|
||||||
|
@ -31,7 +31,6 @@ export const richHistoryUpdatedAction = createAction<{ richHistoryResults: RichH
|
|||||||
);
|
);
|
||||||
export const richHistoryStorageFullAction = createAction('explore/richHistoryStorageFullAction');
|
export const richHistoryStorageFullAction = createAction('explore/richHistoryStorageFullAction');
|
||||||
export const richHistoryLimitExceededAction = createAction('explore/richHistoryLimitExceededAction');
|
export const richHistoryLimitExceededAction = createAction('explore/richHistoryLimitExceededAction');
|
||||||
export const richHistoryMigrationFailedAction = createAction('explore/richHistoryMigrationFailedAction');
|
|
||||||
|
|
||||||
export const richHistorySettingsUpdatedAction = createAction<RichHistorySettings>('explore/richHistorySettingsUpdated');
|
export const richHistorySettingsUpdatedAction = createAction<RichHistorySettings>('explore/richHistorySettingsUpdated');
|
||||||
export const richHistorySearchFiltersUpdatedAction = createAction<{
|
export const richHistorySearchFiltersUpdatedAction = createAction<{
|
||||||
@ -175,7 +174,6 @@ export const initialExploreState: ExploreState = {
|
|||||||
correlations: undefined,
|
correlations: undefined,
|
||||||
richHistoryStorageFull: false,
|
richHistoryStorageFull: false,
|
||||||
richHistoryLimitExceededWarningShown: false,
|
richHistoryLimitExceededWarningShown: false,
|
||||||
richHistoryMigrationFailed: false,
|
|
||||||
largerExploreId: undefined,
|
largerExploreId: undefined,
|
||||||
maxedExploreId: undefined,
|
maxedExploreId: undefined,
|
||||||
evenSplitPanes: true,
|
evenSplitPanes: true,
|
||||||
@ -256,13 +254,6 @@ export const exploreReducer = (state = initialExploreState, action: AnyAction):
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (richHistoryMigrationFailedAction.match(action)) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
richHistoryMigrationFailed: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resetExploreAction.match(action)) {
|
if (resetExploreAction.match(action)) {
|
||||||
const leftState = state[ExploreId.left];
|
const leftState = state[ExploreId.left];
|
||||||
const rightState = state[ExploreId.right];
|
const rightState = state[ExploreId.right];
|
||||||
|
@ -65,11 +65,6 @@ export interface ExploreState {
|
|||||||
*/
|
*/
|
||||||
richHistoryLimitExceededWarningShown: boolean;
|
richHistoryLimitExceededWarningShown: boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* True if a warning message about failed rich history has been shown already in this session.
|
|
||||||
*/
|
|
||||||
richHistoryMigrationFailed: boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* On a split manual resize, we calculate which pane is larger, or if they are roughly the same size. If undefined, it is not split or they are roughly the same size
|
* On a split manual resize, we calculate which pane is larger, or if they are roughly the same size. If undefined, it is not split or they are roughly the same size
|
||||||
*/
|
*/
|
||||||
|
@ -6109,19 +6109,6 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"MigrateQueriesToQueryHistoryCommand": {
|
|
||||||
"description": "MigrateQueriesToQueryHistoryCommand is the command used for migration of old queries into query history",
|
|
||||||
"properties": {
|
|
||||||
"queries": {
|
|
||||||
"description": "Array of queries to store in query history.",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/QueryToMigrate"
|
|
||||||
},
|
|
||||||
"type": "array"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"MoveFolderCommand": {
|
"MoveFolderCommand": {
|
||||||
"description": "MoveFolderCommand captures the information required by the folder service\nto move a folder.",
|
"description": "MoveFolderCommand captures the information required by the folder service\nto move a folder.",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -7472,22 +7459,6 @@
|
|||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"QueryHistoryMigrationResponse": {
|
|
||||||
"properties": {
|
|
||||||
"message": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"starredCount": {
|
|
||||||
"format": "int64",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"totalCount": {
|
|
||||||
"format": "int64",
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"QueryHistoryPreference": {
|
"QueryHistoryPreference": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"homeTab": {
|
"homeTab": {
|
||||||
@ -19262,41 +19233,6 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/query-history/migrate": {
|
|
||||||
"post": {
|
|
||||||
"description": "Adds multiple queries to query history.",
|
|
||||||
"operationId": "migrateQueries",
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/MigrateQueriesToQueryHistoryCommand"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"x-originalParamName": "body"
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "#/components/responses/getQueryHistoryMigrationResponse"
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"$ref": "#/components/responses/badRequestError"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "#/components/responses/unauthorisedError"
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"$ref": "#/components/responses/internalServerError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"summary": "Migrate queries to query history.",
|
|
||||||
"tags": [
|
|
||||||
"query_history"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/query-history/star/{query_history_uid}": {
|
"/query-history/star/{query_history_uid}": {
|
||||||
"delete": {
|
"delete": {
|
||||||
"description": "Removes star from query in query history as specified by the UID.",
|
"description": "Removes star from query in query history as specified by the UID.",
|
||||||
|
Loading…
Reference in New Issue
Block a user