Files
Erik Sundell a111cc0d5c Stackdriver: Support for SLO queries (#22917)
* wip: add slo support

* Export DataSourcePlugin

* wip: break out metric query editor into its own component

* wip: refactor frontend - keep SLO and Metric query in differnt objects

* wip - load services and slos

* Fix broken test

* Add interactive slo expression builder

* Change order of dropdowns

* Refactoring backend model. slo unit testing in progress

* Unit test migration and SLOs

* Cleanup SLO editor

* Simplify alias by component

* Support alias by for slos

* Support slos in variable queries

* Fix broken last query error

* Update Help section to include SLO aliases

* streamline datasource resource cache

* Break out api specific stuff in datasource to its own file

* Move get projects call to frontend

* Refactor api caching

* Unit test api service

* Fix lint go issue

* Fix typescript strict errors

* Fix test datasource

* Use budget fraction selector instead of budget

* Reset SLO when service is changed

* Handle error in case resource call returned no data

* Show real SLI display name

* Use unsafe prefix on will mount hook

* Store goal in query model since it will be used as soon as graph panel supports adding a threshold

* Add comment to describe why componentWillMount is used

* Interpolate sloid

* Break out SLO aggregation into its own func

* Also test group bys for metricquery test

* Remove not used type fields

* Remove annoying stackdriver prefix from error message

* Default view param to FULL

* Add part about SLO query builder in docs

* Use new images

* Fixes after feedback

* Add one more group by test

* Make stackdriver types internal

* Update docs/sources/features/datasources/stackdriver.md

Co-Authored-By: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>

* Update docs/sources/features/datasources/stackdriver.md

Co-Authored-By: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>

* Update docs/sources/features/datasources/stackdriver.md

Co-Authored-By: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>

* Updates after PR feedback

* add test for when no alias by defined

* fix infinite loop when newVariables feature flag is on

onChange being called in componentDidUpdate produces an
infinite loop when using the new React template variable
implementation.

Also fixes a spelling mistake

* implements feedback for documentation changes

* more doc changes

Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>
Co-authored-by: Daniel Lee <dan.limerick@gmail.com>
2020-03-27 12:01:16 +01:00

115 lines
4.2 KiB
TypeScript

import React, { PureComponent } from 'react';
import appEvents from 'app/core/app_events';
import { CoreEvents } from 'app/types';
import { MetricQueryEditor, QueryTypeSelector, SLOQueryEditor, Help } from './';
import { StackdriverQuery, MetricQuery, QueryType, SLOQuery } from '../types';
import { defaultQuery } from './MetricQueryEditor';
import { defaultQuery as defaultSLOQuery } from './SLOQueryEditor';
import { toOption, formatStackdriverError } from '../functions';
import StackdriverDatasource from '../datasource';
import { ExploreQueryFieldProps } from '@grafana/data';
export type Props = ExploreQueryFieldProps<StackdriverDatasource, StackdriverQuery>;
interface State {
lastQueryError: string;
}
export class QueryEditor extends PureComponent<Props, State> {
state: State = { lastQueryError: '' };
async UNSAFE_componentWillMount() {
const { datasource, query } = this.props;
// Unfortunately, migrations like this need to go componentWillMount. As soon as there's
// migration hook for this module.ts, we can do the migrations there instead.
if (!this.props.query.hasOwnProperty('metricQuery')) {
const { hide, refId, datasource, key, queryType, maxLines, metric, ...metricQuery } = this.props.query as any;
this.props.query.metricQuery = metricQuery;
}
if (!this.props.query.hasOwnProperty('queryType')) {
this.props.query.queryType = QueryType.METRICS;
}
await datasource.ensureGCEDefaultProject();
if (!query.metricQuery.projectName) {
this.props.query.metricQuery.projectName = datasource.getDefaultProject();
}
}
componentDidMount() {
appEvents.on(CoreEvents.dsRequestError, this.onDataError.bind(this));
appEvents.on(CoreEvents.dsRequestResponse, this.onDataResponse.bind(this));
}
componentWillUnmount() {
appEvents.off(CoreEvents.dsRequestResponse, this.onDataResponse.bind(this));
appEvents.on(CoreEvents.dsRequestError, this.onDataError.bind(this));
}
onDataResponse() {
this.setState({ lastQueryError: '' });
}
onDataError(error: any) {
this.setState({ lastQueryError: formatStackdriverError(error) });
}
onQueryChange(prop: string, value: any) {
this.props.onChange({ ...this.props.query, [prop]: value });
this.props.onRunQuery();
}
render() {
const { datasource, query, onRunQuery, onChange } = this.props;
const metricQuery = { ...defaultQuery, projectName: datasource.getDefaultProject(), ...query.metricQuery };
const sloQuery = { ...defaultSLOQuery, projectName: datasource.getDefaultProject(), ...query.sloQuery };
const queryType = query.queryType || QueryType.METRICS;
const meta = this.props.data?.series.length ? this.props.data?.series[0].meta : {};
const usedAlignmentPeriod = meta?.alignmentPeriod as string;
const variableOptionGroup = {
label: 'Template Variables',
expanded: false,
options: datasource.variables.map(toOption),
};
return (
<>
<QueryTypeSelector
value={queryType}
templateVariableOptions={variableOptionGroup.options}
onChange={(queryType: QueryType) => {
onChange({ ...query, sloQuery, queryType });
onRunQuery();
}}
></QueryTypeSelector>
{queryType === QueryType.METRICS && (
<MetricQueryEditor
refId={query.refId}
variableOptionGroup={variableOptionGroup}
usedAlignmentPeriod={usedAlignmentPeriod}
onChange={(query: MetricQuery) => this.onQueryChange('metricQuery', query)}
onRunQuery={onRunQuery}
datasource={datasource}
query={metricQuery}
></MetricQueryEditor>
)}
{queryType === QueryType.SLO && (
<SLOQueryEditor
variableOptionGroup={variableOptionGroup}
usedAlignmentPeriod={usedAlignmentPeriod}
onChange={(query: SLOQuery) => this.onQueryChange('sloQuery', query)}
onRunQuery={onRunQuery}
datasource={datasource}
query={sloQuery}
></SLOQueryEditor>
)}
<Help rawQuery={decodeURIComponent(meta?.rawQuery ?? '')} lastQueryError={this.state.lastQueryError} />
</>
);
}
}