Modify the Server Error scenario to return frontend errors (#47157)

This commit is contained in:
Josh Hunt 2022-04-07 10:59:49 +01:00 committed by GitHub
parent c3fe027d58
commit 41642fd5f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 5 deletions

View File

@ -177,9 +177,12 @@ Timestamps will line up evenly on timeStepSeconds (For example, 60 seconds means
})
s.registerScenario(&Scenario{
ID: string(serverError500Query),
Name: "Server Error (500)",
handler: s.handleServerError500Scenario,
// Is no longer strictly a _server_ error scenario, but ID is kept for legacy :)
ID: string(serverError500Query),
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{
@ -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) {
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) {

View File

@ -21,6 +21,7 @@ import { defaultStreamQuery } from './runStreams';
import { CSVFileEditor } from './components/CSVFileEditor';
import { CSVContentEditor } from './components/CSVContentEditor';
import { USAQueryEditor, usaQueryModes } from './components/USAQueryEditor';
import ErrorEditor from './components/ErrorEditor';
const showLabelsFor = ['random_walk', 'predictable_pulse'];
const endpoints = [
@ -69,6 +70,7 @@ export const QueryEditor = ({ query, datasource, onChange, onRunQuery }: Props)
[scenarioList, query]
);
const scenarioId = currentScenario?.id;
const description = currentScenario?.description;
const onScenarioChange = (item: SelectableValue<string>) => {
const scenario = scenarioList?.find((sc) => sc.id === item.value);
@ -287,6 +289,9 @@ export const QueryEditor = ({ query, datasource, onChange, onRunQuery }: Props)
{scenarioId === 'node_graph' && (
<NodeGraphEditor onChange={(val: NodesQuery) => onChange({ ...query, nodes: val })} query={query} />
)}
{scenarioId === 'server_error_500' && <ErrorEditor onChange={onUpdate} query={query} />}
{description && <p>{description}</p>}
</>
);
};

View 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;

View File

@ -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 {
@ -68,6 +68,12 @@ export class TestDataDataSource extends DataSourceWithBackend<TestDataQuery> {
case 'raw_frame':
streams.push(this.rawFrameQuery(target, options));
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
case 'manual_entry': {
let csvContent = 'Time,Value\n';
@ -202,6 +208,29 @@ export class TestDataDataSource extends DataSourceWithBackend<TestDataQuery> {
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> {

View File

@ -4,6 +4,7 @@ export interface Scenario {
id: string;
name: string;
stringInput: string;
description?: string;
}
export interface TestDataQuery extends DataQuery {
@ -22,6 +23,7 @@ export interface TestDataQuery extends DataQuery {
csvContent?: string;
rawFrameContent?: string;
usa?: USAQuery;
errorType?: 'server_panic' | 'frontend_exception' | 'frontend_observable';
}
export interface NodesQuery {