mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugins: Introduce HTTP 207 Multi Status response to api/ds/query (#48550)
* feature toggles * return HTTP 207 from ds/query * add ft check * add API test * add 207 check for qr * change to OR * revert check * add explicit toggle check for cloudwatch * remove unused import * remove from defaults.ini * add status codes to md and update swagger * new fangled http api tests pattern * update swagger * Update docs/sources/http_api/data_source.md Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com> * add missing word and reformat Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com>
This commit is contained in:
parent
88eeb878a4
commit
4ecd57f49c
@ -691,6 +691,16 @@ In addition, specific properties of each data source should be added in a reques
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Status codes
|
||||||
|
|
||||||
|
| Code | Description |
|
||||||
|
| ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| 200 | All data source queries returned a successful response. |
|
||||||
|
| 400 | Bad request due to invalid JSON, missing content type, missing or invalid fields, etc. Or one or more data source queries were unsuccessful. Refer to the body for more details. |
|
||||||
|
| 403 | Access denied. |
|
||||||
|
| 404 | Either the data source or plugin required to fulfil the request could not be found. |
|
||||||
|
| 500 | Unexpected error. Refer to the body and/or server logs for more details. |
|
||||||
|
|
||||||
## Deprecated resources
|
## Deprecated resources
|
||||||
|
|
||||||
The following resources have been deprecated. They will be removed in a future release.
|
The following resources have been deprecated. They will be removed in a future release.
|
||||||
|
@ -58,4 +58,5 @@ export interface FeatureToggles {
|
|||||||
commandPalette?: boolean;
|
commandPalette?: boolean;
|
||||||
savedItems?: boolean;
|
savedItems?: boolean;
|
||||||
cloudWatchDynamicLabels?: boolean;
|
cloudWatchDynamicLabels?: boolean;
|
||||||
|
datasourceQueryMultiStatus?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
//
|
//
|
||||||
// Responses:
|
// Responses:
|
||||||
// 200: queryDataResponse
|
// 200: queryDataResponse
|
||||||
|
// 207: queryDataResponse
|
||||||
// 401: unauthorisedError
|
// 401: unauthorisedError
|
||||||
// 400: badRequestError
|
// 400: badRequestError
|
||||||
// 403: forbiddenError
|
// 403: forbiddenError
|
||||||
|
@ -31,7 +31,7 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext) response.Response {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return hs.handleQueryMetricsError(err)
|
return hs.handleQueryMetricsError(err)
|
||||||
}
|
}
|
||||||
return toJsonStreamingResponse(resp)
|
return hs.toJsonStreamingResponse(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hs *HTTPServer) handleQueryMetricsError(err error) *response.NormalResponse {
|
func (hs *HTTPServer) handleQueryMetricsError(err error) *response.NormalResponse {
|
||||||
@ -147,7 +147,7 @@ func (hs *HTTPServer) QueryMetricsFromDashboard(c *models.ReqContext) response.R
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return hs.handleQueryMetricsError(err)
|
return hs.handleQueryMetricsError(err)
|
||||||
}
|
}
|
||||||
return toJsonStreamingResponse(resp)
|
return hs.toJsonStreamingResponse(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryMetrics returns query metrics
|
// QueryMetrics returns query metrics
|
||||||
@ -198,11 +198,16 @@ func (hs *HTTPServer) QueryMetrics(c *models.ReqContext) response.Response {
|
|||||||
return response.JSON(statusCode, &legacyResp)
|
return response.JSON(statusCode, &legacyResp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toJsonStreamingResponse(qdr *backend.QueryDataResponse) response.Response {
|
func (hs *HTTPServer) toJsonStreamingResponse(qdr *backend.QueryDataResponse) response.Response {
|
||||||
|
statusWhenError := http.StatusBadRequest
|
||||||
|
if hs.Features.IsEnabled(featuremgmt.FlagDatasourceQueryMultiStatus) {
|
||||||
|
statusWhenError = http.StatusMultiStatus
|
||||||
|
}
|
||||||
|
|
||||||
statusCode := http.StatusOK
|
statusCode := http.StatusOK
|
||||||
for _, res := range qdr.Responses {
|
for _, res := range qdr.Responses {
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
statusCode = http.StatusBadRequest
|
statusCode = statusWhenError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
|
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
|
||||||
|
"github.com/grafana/grafana/pkg/web/webtest"
|
||||||
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
|
|
||||||
@ -19,12 +20,14 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
"github.com/grafana/grafana/pkg/models"
|
"github.com/grafana/grafana/pkg/models"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
|
fakeDatasources "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||||
datasources "github.com/grafana/grafana/pkg/services/datasources/service"
|
datasources "github.com/grafana/grafana/pkg/services/datasources/service"
|
||||||
"github.com/grafana/grafana/pkg/services/query"
|
"github.com/grafana/grafana/pkg/services/query"
|
||||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||||
"github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
"github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
||||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -500,3 +503,51 @@ func TestAPIEndpoint_Metrics_ParseDashboardQueryParams(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `/ds/query` endpoint test
|
||||||
|
func TestAPIEndpoint_Metrics_QueryMetricsV2(t *testing.T) {
|
||||||
|
qds := query.ProvideService(
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
&fakePluginRequestValidator{},
|
||||||
|
&fakeDatasources.FakeDataSourceService{},
|
||||||
|
&fakePluginClient{
|
||||||
|
QueryDataHandlerFunc: func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
|
resp := backend.Responses{
|
||||||
|
"A": backend.DataResponse{
|
||||||
|
Error: fmt.Errorf("query failed"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &backend.QueryDataResponse{Responses: resp}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&fakeOAuthTokenService{},
|
||||||
|
)
|
||||||
|
serverFeatureEnabled := SetupAPITestServer(t, func(hs *HTTPServer) {
|
||||||
|
hs.queryDataService = qds
|
||||||
|
hs.Features = featuremgmt.WithFeatures(featuremgmt.FlagDatasourceQueryMultiStatus, true)
|
||||||
|
})
|
||||||
|
serverFeatureDisabled := SetupAPITestServer(t, func(hs *HTTPServer) {
|
||||||
|
hs.queryDataService = qds
|
||||||
|
hs.Features = featuremgmt.WithFeatures(featuremgmt.FlagDatasourceQueryMultiStatus, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Status code is 400 when data source response has an error and feature toggle is disabled", func(t *testing.T) {
|
||||||
|
req := serverFeatureDisabled.NewPostRequest("/api/ds/query", strings.NewReader(queryDatasourceInput))
|
||||||
|
webtest.RequestWithSignedInUser(req, &models.SignedInUser{UserId: 1, OrgId: 1, OrgRole: models.ROLE_VIEWER})
|
||||||
|
resp, err := serverFeatureDisabled.SendJSON(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, resp.Body.Close())
|
||||||
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Status code is 207 when data source response has an error and feature toggle is enabled", func(t *testing.T) {
|
||||||
|
req := serverFeatureEnabled.NewPostRequest("/api/ds/query", strings.NewReader(queryDatasourceInput))
|
||||||
|
webtest.RequestWithSignedInUser(req, &models.SignedInUser{UserId: 1, OrgId: 1, OrgRole: models.ROLE_VIEWER})
|
||||||
|
resp, err := serverFeatureEnabled.SendJSON(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, resp.Body.Close())
|
||||||
|
require.Equal(t, http.StatusMultiStatus, resp.StatusCode)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -249,9 +249,11 @@ type fakePluginClient struct {
|
|||||||
plugins.Client
|
plugins.Client
|
||||||
|
|
||||||
req *backend.CallResourceRequest
|
req *backend.CallResourceRequest
|
||||||
|
|
||||||
|
backend.QueryDataHandlerFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fakePluginClient) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
func (c *fakePluginClient) CallResource(_ context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||||
c.req = req
|
c.req = req
|
||||||
bytes, err := json.Marshal(map[string]interface{}{
|
bytes, err := json.Marshal(map[string]interface{}{
|
||||||
"message": "hello",
|
"message": "hello",
|
||||||
@ -266,3 +268,11 @@ func (c *fakePluginClient) CallResource(ctx context.Context, req *backend.CallRe
|
|||||||
Body: bytes,
|
Body: bytes,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *fakePluginClient) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
|
if c.QueryDataHandlerFunc != nil {
|
||||||
|
return c.QueryDataHandlerFunc.QueryData(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
return backend.NewQueryDataResponse(), nil
|
||||||
|
}
|
||||||
|
@ -236,5 +236,10 @@ var (
|
|||||||
Description: "Use dynamic labels instead of alias patterns in CloudWatch datasource",
|
Description: "Use dynamic labels instead of alias patterns in CloudWatch datasource",
|
||||||
State: FeatureStateStable,
|
State: FeatureStateStable,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "datasourceQueryMultiStatus",
|
||||||
|
Description: "Introduce HTTP 207 Multi Status for api/ds/query",
|
||||||
|
State: FeatureStateAlpha,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -174,4 +174,8 @@ const (
|
|||||||
// FlagCloudWatchDynamicLabels
|
// FlagCloudWatchDynamicLabels
|
||||||
// Use dynamic labels instead of alias patterns in CloudWatch datasource
|
// Use dynamic labels instead of alias patterns in CloudWatch datasource
|
||||||
FlagCloudWatchDynamicLabels = "cloudWatchDynamicLabels"
|
FlagCloudWatchDynamicLabels = "cloudWatchDynamicLabels"
|
||||||
|
|
||||||
|
// FlagDatasourceQueryMultiStatus
|
||||||
|
// Introduce HTTP 207 Multi Status for api/ds/query
|
||||||
|
FlagDatasourceQueryMultiStatus = "datasourceQueryMultiStatus"
|
||||||
)
|
)
|
||||||
|
@ -4692,15 +4692,15 @@
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "DatasourceID",
|
"x-go-name": "PermissionID",
|
||||||
"name": "datasource_id",
|
"name": "permissionId",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "PermissionID",
|
"x-go-name": "DatasourceID",
|
||||||
"name": "permissionId",
|
"name": "datasource_id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@ -4745,6 +4745,9 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"$ref": "#/responses/queryDataResponse"
|
"$ref": "#/responses/queryDataResponse"
|
||||||
},
|
},
|
||||||
|
"207": {
|
||||||
|
"$ref": "#/responses/queryDataResponse"
|
||||||
|
},
|
||||||
"400": {
|
"400": {
|
||||||
"$ref": "#/responses/badRequestError"
|
"$ref": "#/responses/badRequestError"
|
||||||
},
|
},
|
||||||
@ -8258,14 +8261,6 @@
|
|||||||
"summary": "Add External Group.",
|
"summary": "Add External Group.",
|
||||||
"operationId": "addTeamGroupApi",
|
"operationId": "addTeamGroupApi",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int64",
|
|
||||||
"x-go-name": "TeamID",
|
|
||||||
"name": "teamId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"x-go-name": "Body",
|
"x-go-name": "Body",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
@ -8274,6 +8269,14 @@
|
|||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/TeamGroupMapping"
|
"$ref": "#/definitions/TeamGroupMapping"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"x-go-name": "TeamID",
|
||||||
|
"name": "teamId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@ -8307,16 +8310,16 @@
|
|||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"x-go-name": "TeamID",
|
"x-go-name": "GroupID",
|
||||||
"name": "teamId",
|
"name": "groupId",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"x-go-name": "GroupID",
|
"x-go-name": "TeamID",
|
||||||
"name": "groupId",
|
"name": "teamId",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@ -10534,6 +10537,9 @@
|
|||||||
"ApiKeyDTO": {
|
"ApiKeyDTO": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"accessControl": {
|
||||||
|
"$ref": "#/definitions/Metadata"
|
||||||
|
},
|
||||||
"expiration": {
|
"expiration": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
@ -10555,7 +10561,7 @@
|
|||||||
"x-go-name": "Role"
|
"x-go-name": "Role"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "github.com/grafana/grafana/pkg/models"
|
"x-go-package": "github.com/grafana/grafana/pkg/api/dtos"
|
||||||
},
|
},
|
||||||
"ApiRuleNode": {
|
"ApiRuleNode": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -13632,7 +13638,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"id": {
|
"id": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "Id"
|
"x-go-name": "ID"
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -13647,7 +13653,7 @@
|
|||||||
"x-go-name": "Url"
|
"x-go-name": "Url"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "github.com/grafana/grafana/pkg/models"
|
"x-go-package": "github.com/grafana/grafana/pkg/services/preference"
|
||||||
},
|
},
|
||||||
"NavbarPreference": {
|
"NavbarPreference": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -14739,7 +14745,7 @@
|
|||||||
"x-go-name": "HomeTab"
|
"x-go-name": "HomeTab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "github.com/grafana/grafana/pkg/models"
|
"x-go-package": "github.com/grafana/grafana/pkg/services/preference"
|
||||||
},
|
},
|
||||||
"Receiver": {
|
"Receiver": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -3754,15 +3754,15 @@
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "DatasourceID",
|
"x-go-name": "PermissionID",
|
||||||
"name": "datasource_id",
|
"name": "permissionId",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "PermissionID",
|
"x-go-name": "DatasourceID",
|
||||||
"name": "permissionId",
|
"name": "datasource_id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@ -3807,6 +3807,9 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"$ref": "#/responses/queryDataResponse"
|
"$ref": "#/responses/queryDataResponse"
|
||||||
},
|
},
|
||||||
|
"207": {
|
||||||
|
"$ref": "#/responses/queryDataResponse"
|
||||||
|
},
|
||||||
"400": {
|
"400": {
|
||||||
"$ref": "#/responses/badRequestError"
|
"$ref": "#/responses/badRequestError"
|
||||||
},
|
},
|
||||||
@ -6667,14 +6670,6 @@
|
|||||||
"summary": "Add External Group.",
|
"summary": "Add External Group.",
|
||||||
"operationId": "addTeamGroupApi",
|
"operationId": "addTeamGroupApi",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int64",
|
|
||||||
"x-go-name": "TeamID",
|
|
||||||
"name": "teamId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"x-go-name": "Body",
|
"x-go-name": "Body",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
@ -6683,6 +6678,14 @@
|
|||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/TeamGroupMapping"
|
"$ref": "#/definitions/TeamGroupMapping"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"x-go-name": "TeamID",
|
||||||
|
"name": "teamId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@ -6716,16 +6719,16 @@
|
|||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"x-go-name": "TeamID",
|
"x-go-name": "GroupID",
|
||||||
"name": "teamId",
|
"name": "groupId",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"x-go-name": "GroupID",
|
"x-go-name": "TeamID",
|
||||||
"name": "groupId",
|
"name": "teamId",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@ -8626,6 +8629,9 @@
|
|||||||
"ApiKeyDTO": {
|
"ApiKeyDTO": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"accessControl": {
|
||||||
|
"$ref": "#/definitions/Metadata"
|
||||||
|
},
|
||||||
"expiration": {
|
"expiration": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
@ -8647,7 +8653,7 @@
|
|||||||
"x-go-name": "Role"
|
"x-go-name": "Role"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "github.com/grafana/grafana/pkg/models"
|
"x-go-package": "github.com/grafana/grafana/pkg/api/dtos"
|
||||||
},
|
},
|
||||||
"BrandingOptionsDTO": {
|
"BrandingOptionsDTO": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -10715,7 +10721,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"id": {
|
"id": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "Id"
|
"x-go-name": "ID"
|
||||||
},
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -10730,7 +10736,7 @@
|
|||||||
"x-go-name": "Url"
|
"x-go-name": "Url"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "github.com/grafana/grafana/pkg/models"
|
"x-go-package": "github.com/grafana/grafana/pkg/services/preference"
|
||||||
},
|
},
|
||||||
"NavbarPreference": {
|
"NavbarPreference": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -11191,7 +11197,7 @@
|
|||||||
"x-go-name": "HomeTab"
|
"x-go-name": "HomeTab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "github.com/grafana/grafana/pkg/models"
|
"x-go-package": "github.com/grafana/grafana/pkg/services/preference"
|
||||||
},
|
},
|
||||||
"RecordingRuleJSON": {
|
"RecordingRuleJSON": {
|
||||||
"description": "RecordingRuleJSON is the external representation of a recording rule",
|
"description": "RecordingRuleJSON is the external representation of a recording rule",
|
||||||
|
@ -29,6 +29,8 @@ import { VariableWithMultiSupport } from 'app/features/variables/types';
|
|||||||
import { store } from 'app/store/store';
|
import { store } from 'app/store/store';
|
||||||
import { AppNotificationTimeout } from 'app/types';
|
import { AppNotificationTimeout } from 'app/types';
|
||||||
|
|
||||||
|
import config from '../../../core/config';
|
||||||
|
|
||||||
import { CloudWatchAnnotationSupport } from './annotationSupport';
|
import { CloudWatchAnnotationSupport } from './annotationSupport';
|
||||||
import { SQLCompletionItemProvider } from './cloudwatch-sql/completion/CompletionItemProvider';
|
import { SQLCompletionItemProvider } from './cloudwatch-sql/completion/CompletionItemProvider';
|
||||||
import { ThrottlingErrorMessage } from './components/ThrottlingErrorMessage';
|
import { ThrottlingErrorMessage } from './components/ThrottlingErrorMessage';
|
||||||
@ -669,6 +671,10 @@ export class CloudWatchDatasource
|
|||||||
return this.awsRequest(DS_QUERY_ENDPOINT, requestParams, headers).pipe(
|
return this.awsRequest(DS_QUERY_ENDPOINT, requestParams, headers).pipe(
|
||||||
map((response) => resultsToDataFrames({ data: response })),
|
map((response) => resultsToDataFrames({ data: response })),
|
||||||
catchError((err: FetchError) => {
|
catchError((err: FetchError) => {
|
||||||
|
if (config.featureToggles.datasourceQueryMultiStatus && err.status === 207) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
if (err.status === 400) {
|
if (err.status === 400) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user