mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Modify the Server Error scenario to return frontend errors (#47157)
This commit is contained in:
@@ -177,9 +177,12 @@ Timestamps will line up evenly on timeStepSeconds (For example, 60 seconds means
|
|||||||
})
|
})
|
||||||
|
|
||||||
s.registerScenario(&Scenario{
|
s.registerScenario(&Scenario{
|
||||||
ID: string(serverError500Query),
|
// Is no longer strictly a _server_ error scenario, but ID is kept for legacy :)
|
||||||
Name: "Server Error (500)",
|
ID: string(serverError500Query),
|
||||||
handler: s.handleServerError500Scenario,
|
Name: "Conditional Error",
|
||||||
|
handler: s.handleServerError500Scenario,
|
||||||
|
StringInput: "1,20,90,30,5,0",
|
||||||
|
Description: "Returns an error when the String Input field is empty",
|
||||||
})
|
})
|
||||||
|
|
||||||
s.registerScenario(&Scenario{
|
s.registerScenario(&Scenario{
|
||||||
@@ -449,7 +452,19 @@ func (s *Service) handlePredictablePulseScenario(ctx context.Context, req *backe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) handleServerError500Scenario(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (s *Service) handleServerError500Scenario(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
panic("Test Data Panic!")
|
for _, q := range req.Queries {
|
||||||
|
model, err := simplejson.NewJson(q.JSON)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
stringInput := model.Get("stringInput").MustString()
|
||||||
|
if stringInput == "" {
|
||||||
|
panic("Test Data Panic!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.handleCSVMetricValuesScenario(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) handleClientSideScenario(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (s *Service) handleClientSideScenario(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
|
@@ -21,6 +21,7 @@ import { defaultStreamQuery } from './runStreams';
|
|||||||
import { CSVFileEditor } from './components/CSVFileEditor';
|
import { CSVFileEditor } from './components/CSVFileEditor';
|
||||||
import { CSVContentEditor } from './components/CSVContentEditor';
|
import { CSVContentEditor } from './components/CSVContentEditor';
|
||||||
import { USAQueryEditor, usaQueryModes } from './components/USAQueryEditor';
|
import { USAQueryEditor, usaQueryModes } from './components/USAQueryEditor';
|
||||||
|
import ErrorEditor from './components/ErrorEditor';
|
||||||
|
|
||||||
const showLabelsFor = ['random_walk', 'predictable_pulse'];
|
const showLabelsFor = ['random_walk', 'predictable_pulse'];
|
||||||
const endpoints = [
|
const endpoints = [
|
||||||
@@ -69,6 +70,7 @@ export const QueryEditor = ({ query, datasource, onChange, onRunQuery }: Props)
|
|||||||
[scenarioList, query]
|
[scenarioList, query]
|
||||||
);
|
);
|
||||||
const scenarioId = currentScenario?.id;
|
const scenarioId = currentScenario?.id;
|
||||||
|
const description = currentScenario?.description;
|
||||||
|
|
||||||
const onScenarioChange = (item: SelectableValue<string>) => {
|
const onScenarioChange = (item: SelectableValue<string>) => {
|
||||||
const scenario = scenarioList?.find((sc) => sc.id === item.value);
|
const scenario = scenarioList?.find((sc) => sc.id === item.value);
|
||||||
@@ -287,6 +289,9 @@ export const QueryEditor = ({ query, datasource, onChange, onRunQuery }: Props)
|
|||||||
{scenarioId === 'node_graph' && (
|
{scenarioId === 'node_graph' && (
|
||||||
<NodeGraphEditor onChange={(val: NodesQuery) => onChange({ ...query, nodes: val })} query={query} />
|
<NodeGraphEditor onChange={(val: NodesQuery) => onChange({ ...query, nodes: val })} query={query} />
|
||||||
)}
|
)}
|
||||||
|
{scenarioId === 'server_error_500' && <ErrorEditor onChange={onUpdate} query={query} />}
|
||||||
|
|
||||||
|
{description && <p>{description}</p>}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
36
public/app/plugins/datasource/testdata/components/ErrorEditor.tsx
vendored
Normal file
36
public/app/plugins/datasource/testdata/components/ErrorEditor.tsx
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { InlineField, InlineFieldRow, Select } from '@grafana/ui';
|
||||||
|
import React from 'react';
|
||||||
|
import { EditorProps } from '../QueryEditor';
|
||||||
|
|
||||||
|
const ERROR_OPTIONS = [
|
||||||
|
{
|
||||||
|
label: 'Server panic',
|
||||||
|
value: 'server_panic',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Frontend exception',
|
||||||
|
value: 'frontend_exception',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Frontend observable',
|
||||||
|
value: 'frontend_observable',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const FrontendErrorQueryEditor: React.FC<EditorProps> = ({ query, onChange }) => {
|
||||||
|
return (
|
||||||
|
<InlineFieldRow>
|
||||||
|
<InlineField labelWidth={14} label="Error type">
|
||||||
|
<Select
|
||||||
|
options={ERROR_OPTIONS}
|
||||||
|
value={query.errorType}
|
||||||
|
onChange={(v) => {
|
||||||
|
onChange({ ...query, errorType: v.value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</InlineField>
|
||||||
|
</InlineFieldRow>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FrontendErrorQueryEditor;
|
@@ -1,4 +1,4 @@
|
|||||||
import { from, merge, Observable, of } from 'rxjs';
|
import { from, merge, Observable, of, throwError } from 'rxjs';
|
||||||
import { delay } from 'rxjs/operators';
|
import { delay } from 'rxjs/operators';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -68,6 +68,12 @@ export class TestDataDataSource extends DataSourceWithBackend<TestDataQuery> {
|
|||||||
case 'raw_frame':
|
case 'raw_frame':
|
||||||
streams.push(this.rawFrameQuery(target, options));
|
streams.push(this.rawFrameQuery(target, options));
|
||||||
break;
|
break;
|
||||||
|
case 'server_error_500':
|
||||||
|
// this now has an option where it can return/throw an error from the frontend.
|
||||||
|
// if it doesn't, send it to the backend where it might panic there :)
|
||||||
|
const query = this.serverErrorQuery(target, options);
|
||||||
|
query ? streams.push(query) : backendQueries.push(target);
|
||||||
|
break;
|
||||||
// Unusable since 7, removed in 8
|
// Unusable since 7, removed in 8
|
||||||
case 'manual_entry': {
|
case 'manual_entry': {
|
||||||
let csvContent = 'Time,Value\n';
|
let csvContent = 'Time,Value\n';
|
||||||
@@ -202,6 +208,29 @@ export class TestDataDataSource extends DataSourceWithBackend<TestDataQuery> {
|
|||||||
return of({ data: [], error: ex }).pipe(delay(100));
|
return of({ data: [], error: ex }).pipe(delay(100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serverErrorQuery(
|
||||||
|
target: TestDataQuery,
|
||||||
|
options: DataQueryRequest<TestDataQuery>
|
||||||
|
): Observable<DataQueryResponse> | null {
|
||||||
|
const { errorType } = target;
|
||||||
|
console.log("we're here!", target);
|
||||||
|
|
||||||
|
if (errorType === 'server_panic') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stringInput = target.stringInput ?? '';
|
||||||
|
if (stringInput === '') {
|
||||||
|
if (errorType === 'frontend_exception') {
|
||||||
|
throw new Error('Scenario threw an exception in the frontend because the input was empty.');
|
||||||
|
} else {
|
||||||
|
return throwError(() => new Error('Scenario returned an error because the input was empty.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function runGrafanaAPI(target: TestDataQuery, req: DataQueryRequest<TestDataQuery>): Observable<DataQueryResponse> {
|
function runGrafanaAPI(target: TestDataQuery, req: DataQueryRequest<TestDataQuery>): Observable<DataQueryResponse> {
|
||||||
|
@@ -4,6 +4,7 @@ export interface Scenario {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
stringInput: string;
|
stringInput: string;
|
||||||
|
description?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TestDataQuery extends DataQuery {
|
export interface TestDataQuery extends DataQuery {
|
||||||
@@ -22,6 +23,7 @@ export interface TestDataQuery extends DataQuery {
|
|||||||
csvContent?: string;
|
csvContent?: string;
|
||||||
rawFrameContent?: string;
|
rawFrameContent?: string;
|
||||||
usa?: USAQuery;
|
usa?: USAQuery;
|
||||||
|
errorType?: 'server_panic' | 'frontend_exception' | 'frontend_observable';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NodesQuery {
|
export interface NodesQuery {
|
||||||
|
Reference in New Issue
Block a user