mirror of
https://github.com/grafana/grafana.git
synced 2025-08-26 12:20:47 +08:00

* 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>
150 lines
4.4 KiB
TypeScript
150 lines
4.4 KiB
TypeScript
import React from 'react';
|
|
import { Input } from '@grafana/ui';
|
|
|
|
import { TemplateSrv } from 'app/features/templating/template_srv';
|
|
import { SelectableValue } from '@grafana/data';
|
|
|
|
import StackdriverDatasource from '../datasource';
|
|
import { Metrics, LabelFilter, AnnotationsHelp, Project } from './';
|
|
import { toOption } from '../functions';
|
|
import { AnnotationTarget, MetricDescriptor } from '../types';
|
|
|
|
export interface Props {
|
|
onQueryChange: (target: AnnotationTarget) => void;
|
|
target: AnnotationTarget;
|
|
datasource: StackdriverDatasource;
|
|
templateSrv: TemplateSrv;
|
|
}
|
|
|
|
interface State extends AnnotationTarget {
|
|
variableOptionGroup: SelectableValue<string>;
|
|
variableOptions: Array<SelectableValue<string>>;
|
|
labels: any;
|
|
[key: string]: any;
|
|
}
|
|
|
|
const DefaultTarget: State = {
|
|
projectName: '',
|
|
projects: [],
|
|
metricType: '',
|
|
filters: [],
|
|
metricKind: '',
|
|
valueType: '',
|
|
refId: 'annotationQuery',
|
|
title: '',
|
|
text: '',
|
|
labels: {},
|
|
variableOptionGroup: {},
|
|
variableOptions: [],
|
|
};
|
|
|
|
export class AnnotationQueryEditor extends React.Component<Props, State> {
|
|
state: State = DefaultTarget;
|
|
|
|
async UNSAFE_componentWillMount() {
|
|
// 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.
|
|
const { target, datasource } = this.props;
|
|
if (!target.projectName) {
|
|
target.projectName = datasource.getDefaultProject();
|
|
}
|
|
|
|
const variableOptionGroup = {
|
|
label: 'Template Variables',
|
|
options: datasource.variables.map(toOption),
|
|
};
|
|
|
|
const projects = await datasource.getProjects();
|
|
this.setState({
|
|
variableOptionGroup,
|
|
variableOptions: variableOptionGroup.options,
|
|
...target,
|
|
projects,
|
|
});
|
|
|
|
datasource.getLabels(target.metricType, target.projectName, target.refId).then(labels => this.setState({ labels }));
|
|
}
|
|
|
|
onMetricTypeChange = ({ valueType, metricKind, type, unit }: MetricDescriptor) => {
|
|
const { onQueryChange, datasource } = this.props;
|
|
this.setState(
|
|
{
|
|
metricType: type,
|
|
unit,
|
|
valueType,
|
|
metricKind,
|
|
},
|
|
() => {
|
|
onQueryChange(this.state);
|
|
}
|
|
);
|
|
datasource.getLabels(type, this.state.refId, this.state.projectName).then(labels => this.setState({ labels }));
|
|
};
|
|
|
|
onChange(prop: string, value: string | string[]) {
|
|
this.setState({ [prop]: value }, () => {
|
|
this.props.onQueryChange(this.state);
|
|
});
|
|
}
|
|
|
|
render() {
|
|
const { metricType, projectName, filters, title, text, variableOptionGroup, labels, variableOptions } = this.state;
|
|
const { datasource } = this.props;
|
|
|
|
return (
|
|
<>
|
|
<Project
|
|
templateVariableOptions={variableOptions}
|
|
datasource={datasource}
|
|
projectName={projectName || datasource.getDefaultProject()}
|
|
onChange={value => this.onChange('projectName', value)}
|
|
/>
|
|
<Metrics
|
|
projectName={projectName}
|
|
metricType={metricType}
|
|
templateSrv={datasource.templateSrv}
|
|
datasource={datasource}
|
|
templateVariableOptions={variableOptions}
|
|
onChange={metric => this.onMetricTypeChange(metric)}
|
|
>
|
|
{metric => (
|
|
<>
|
|
<LabelFilter
|
|
labels={labels}
|
|
filters={filters}
|
|
onChange={value => this.onChange('filters', value)}
|
|
variableOptionGroup={variableOptionGroup}
|
|
/>
|
|
</>
|
|
)}
|
|
</Metrics>
|
|
<div className="gf-form gf-form-inline">
|
|
<div className="gf-form">
|
|
<span className="gf-form-label query-keyword width-9">Title</span>
|
|
<Input
|
|
type="text"
|
|
className="gf-form-input width-20"
|
|
value={title}
|
|
onChange={e => this.onChange('title', e.target.value)}
|
|
/>
|
|
</div>
|
|
<div className="gf-form">
|
|
<span className="gf-form-label query-keyword width-9">Text</span>
|
|
<Input
|
|
type="text"
|
|
className="gf-form-input width-20"
|
|
value={text}
|
|
onChange={e => this.onChange('text', e.target.value)}
|
|
/>
|
|
</div>
|
|
<div className="gf-form gf-form--grow">
|
|
<div className="gf-form-label gf-form-label--grow" />
|
|
</div>
|
|
</div>
|
|
|
|
<AnnotationsHelp />
|
|
</>
|
|
);
|
|
}
|
|
}
|