mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 16:15:42 -06:00
add experimental slo query editor (#51351)
This commit is contained in:
parent
c12d1727f0
commit
396278a6e5
@ -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>
|
||||||
|
);
|
||||||
|
};
|
@ -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 })} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -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>
|
||||||
|
);
|
||||||
|
};
|
@ -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>
|
||||||
|
);
|
||||||
|
};
|
@ -12,6 +12,7 @@ import { CloudMonitoringQuery, EditorMode, MetricQuery, QueryType, SLOQuery, Clo
|
|||||||
|
|
||||||
import { MetricQueryEditor as ExperimentalMetricQueryEditor } from './Experimental/MetricQueryEditor';
|
import { MetricQueryEditor as ExperimentalMetricQueryEditor } from './Experimental/MetricQueryEditor';
|
||||||
import { QueryHeader } from './Experimental/QueryHeader';
|
import { QueryHeader } from './Experimental/QueryHeader';
|
||||||
|
import { SLOQueryEditor as ExperimentalSLOQueryEditor } from './Experimental/SLOQueryEditor';
|
||||||
import { defaultQuery } from './MetricQueryEditor';
|
import { defaultQuery } from './MetricQueryEditor';
|
||||||
import { defaultQuery as defaultSLOQuery } from './SLO/SLOQueryEditor';
|
import { defaultQuery as defaultSLOQuery } from './SLO/SLOQueryEditor';
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ export class QueryEditor extends PureComponent<Props> {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{queryType === QueryType.SLO && (
|
{queryType === QueryType.SLO && (
|
||||||
<SLOQueryEditor
|
<ExperimentalSLOQueryEditor
|
||||||
refId={query.refId}
|
refId={query.refId}
|
||||||
variableOptionGroup={variableOptionGroup}
|
variableOptionGroup={variableOptionGroup}
|
||||||
customMetaData={customMetaData}
|
customMetaData={customMetaData}
|
||||||
|
Loading…
Reference in New Issue
Block a user