add experimental slo query editor (#51351)

This commit is contained in:
Kevin Yu 2022-07-06 08:48:43 -07:00 committed by GitHub
parent c12d1727f0
commit 396278a6e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 249 additions and 1 deletions

View File

@ -0,0 +1,56 @@
import React, { useEffect, useState } from 'react';
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';
import { QueryEditorRow } from '..';
import { SELECT_WIDTH } from '../../constants';
import CloudMonitoringDatasource from '../../datasource';
import { SLOQuery } from '../../types';
export interface Props {
refId: string;
onChange: (query: SLOQuery) => void;
query: SLOQuery;
templateVariableOptions: Array<SelectableValue<string>>;
datasource: CloudMonitoringDatasource;
}
export const SLO: React.FC<Props> = ({ refId, query, templateVariableOptions, onChange, datasource }) => {
const [slos, setSLOs] = useState<Array<SelectableValue<string>>>([]);
const { projectName, serviceId } = query;
useEffect(() => {
if (!projectName || !serviceId) {
return;
}
datasource.getServiceLevelObjectives(projectName, serviceId).then((sloIds: Array<SelectableValue<string>>) => {
setSLOs([
{
label: 'Template Variables',
options: templateVariableOptions,
},
...sloIds,
]);
});
}, [datasource, projectName, serviceId, templateVariableOptions]);
return (
<QueryEditorRow label="SLO" htmlFor={`${refId}-slo`}>
<Select
inputId={`${refId}-slo`}
width={SELECT_WIDTH}
allowCustomValue
value={query?.sloId && { value: query?.sloId, label: query?.sloName || query?.sloId }}
placeholder="Select SLO"
options={slos}
onChange={async ({ value: sloId = '', label: sloName = '' }) => {
const slos = await datasource.getServiceLevelObjectives(projectName, serviceId);
const slo = slos.find(({ value }) => value === datasource.templateSrv.replace(sloId));
onChange({ ...query, sloId, sloName, goal: slo?.goal });
}}
/>
</QueryEditorRow>
);
};

View File

@ -0,0 +1,99 @@
import React from 'react';
import { SelectableValue } from '@grafana/data';
import { EditorField, EditorFieldGroup, EditorRow, Stack } from '@grafana/experimental';
import { Project } from '..';
import { ALIGNMENT_PERIODS } from '../../constants';
import CloudMonitoringDatasource from '../../datasource';
import { AlignmentTypes, CustomMetaData, SLOQuery } from '../../types';
import { AliasBy } from './AliasBy';
import { AlignmentPeriodLabel } from './AlignmentPeriodLabel';
import { PeriodSelect } from './PeriodSelect';
import { SLO } from './SLO';
import { Selector } from './Selector';
import { Service } from './Service';
export interface Props {
refId: string;
customMetaData: CustomMetaData;
variableOptionGroup: SelectableValue<string>;
onChange: (query: SLOQuery) => void;
onRunQuery: () => void;
query: SLOQuery;
datasource: CloudMonitoringDatasource;
}
export const defaultQuery: (dataSource: CloudMonitoringDatasource) => SLOQuery = (dataSource) => ({
projectName: dataSource.getDefaultProject(),
alignmentPeriod: 'cloud-monitoring-auto',
perSeriesAligner: AlignmentTypes.ALIGN_MEAN,
aliasBy: '',
selectorName: 'select_slo_health',
serviceId: '',
serviceName: '',
sloId: '',
sloName: '',
});
export function SLOQueryEditor({
refId,
query,
datasource,
onChange,
variableOptionGroup,
customMetaData,
}: React.PropsWithChildren<Props>) {
return (
<>
<Project
refId={refId}
templateVariableOptions={variableOptionGroup.options}
projectName={query.projectName}
datasource={datasource}
onChange={(projectName) => onChange({ ...query, projectName })}
/>
<Service
refId={refId}
datasource={datasource}
templateVariableOptions={variableOptionGroup.options}
query={query}
onChange={onChange}
/>
<SLO
refId={refId}
datasource={datasource}
templateVariableOptions={variableOptionGroup.options}
query={query}
onChange={onChange}
/>
<Selector
refId={refId}
datasource={datasource}
templateVariableOptions={variableOptionGroup.options}
query={query}
onChange={onChange}
/>
<EditorRow>
<EditorFieldGroup>
<EditorField label="Alignment period">
<PeriodSelect
inputId={`${refId}-alignment-period`}
templateVariableOptions={variableOptionGroup.options}
current={query.alignmentPeriod}
onChange={(period) => onChange({ ...query, alignmentPeriod: period })}
aligmentPeriods={ALIGNMENT_PERIODS}
/>
</EditorField>
<Stack alignItems="flex-end">
<AlignmentPeriodLabel datasource={datasource} customMetaData={customMetaData} />
</Stack>
</EditorFieldGroup>
</EditorRow>
<AliasBy refId={refId} value={query.aliasBy} onChange={(aliasBy) => onChange({ ...query, aliasBy })} />
</>
);
}

View File

@ -0,0 +1,38 @@
import React from 'react';
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';
import { QueryEditorRow } from '..';
import { SELECT_WIDTH, SELECTORS } from '../../constants';
import CloudMonitoringDatasource from '../../datasource';
import { SLOQuery } from '../../types';
export interface Props {
refId: string;
onChange: (query: SLOQuery) => void;
query: SLOQuery;
templateVariableOptions: Array<SelectableValue<string>>;
datasource: CloudMonitoringDatasource;
}
export const Selector: React.FC<Props> = ({ refId, query, templateVariableOptions, onChange, datasource }) => {
return (
<QueryEditorRow label="Selector" htmlFor={`${refId}-slo-selector`}>
<Select
inputId={`${refId}-slo-selector`}
width={SELECT_WIDTH}
allowCustomValue
value={[...SELECTORS, ...templateVariableOptions].find((s) => s.value === query?.selectorName ?? '')}
options={[
{
label: 'Template Variables',
options: templateVariableOptions,
},
...SELECTORS,
]}
onChange={({ value: selectorName }) => onChange({ ...query, selectorName: selectorName ?? '' })}
/>
</QueryEditorRow>
);
};

View File

@ -0,0 +1,54 @@
import React, { useEffect, useState } from 'react';
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';
import { QueryEditorRow } from '..';
import { SELECT_WIDTH } from '../../constants';
import CloudMonitoringDatasource from '../../datasource';
import { SLOQuery } from '../../types';
export interface Props {
refId: string;
onChange: (query: SLOQuery) => void;
query: SLOQuery;
templateVariableOptions: Array<SelectableValue<string>>;
datasource: CloudMonitoringDatasource;
}
export const Service: React.FC<Props> = ({ refId, query, templateVariableOptions, onChange, datasource }) => {
const [services, setServices] = useState<Array<SelectableValue<string>>>([]);
const { projectName } = query;
useEffect(() => {
if (!projectName) {
return;
}
datasource.getSLOServices(projectName).then((services: Array<SelectableValue<string>>) => {
setServices([
{
label: 'Template Variables',
options: templateVariableOptions,
},
...services,
]);
});
}, [datasource, projectName, templateVariableOptions]);
return (
<QueryEditorRow label="Service" htmlFor={`${refId}-slo-service`}>
<Select
inputId={`${refId}-slo-service`}
width={SELECT_WIDTH}
allowCustomValue
value={query?.serviceId && { value: query?.serviceId, label: query?.serviceName || query?.serviceId }}
placeholder="Select service"
options={services}
onChange={({ value: serviceId = '', label: serviceName = '' }) =>
onChange({ ...query, serviceId, serviceName, sloId: '' })
}
/>
</QueryEditorRow>
);
};

View File

@ -12,6 +12,7 @@ import { CloudMonitoringQuery, EditorMode, MetricQuery, QueryType, SLOQuery, Clo
import { MetricQueryEditor as ExperimentalMetricQueryEditor } from './Experimental/MetricQueryEditor';
import { QueryHeader } from './Experimental/QueryHeader';
import { SLOQueryEditor as ExperimentalSLOQueryEditor } from './Experimental/SLOQueryEditor';
import { defaultQuery } from './MetricQueryEditor';
import { defaultQuery as defaultSLOQuery } from './SLO/SLOQueryEditor';
@ -82,7 +83,7 @@ export class QueryEditor extends PureComponent<Props> {
)}
{queryType === QueryType.SLO && (
<SLOQueryEditor
<ExperimentalSLOQueryEditor
refId={query.refId}
variableOptionGroup={variableOptionGroup}
customMetaData={customMetaData}