The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/features/dashboard-scene/settings/variables/utils.ts

197 lines
6.1 KiB

import { chain } from 'lodash';
import { DataSourceInstanceSettings, SelectableValue } from '@grafana/data';
import { config, getDataSourceSrv } from '@grafana/runtime';
import {
ConstantVariable,
CustomVariable,
DataSourceVariable,
IntervalVariable,
TextBoxVariable,
QueryVariable,
GroupByVariable,
SceneVariable,
MultiValueVariable,
AdHocFiltersVariable,
SceneVariableState,
} from '@grafana/scenes';
import { VariableType } from '@grafana/schema';
import { getIntervalsQueryFromNewIntervalModel } from '../../utils/utils';
import { AdHocFiltersVariableEditor } from './editors/AdHocFiltersVariableEditor';
import { ConstantVariableEditor } from './editors/ConstantVariableEditor';
import { CustomVariableEditor } from './editors/CustomVariableEditor';
import { DataSourceVariableEditor } from './editors/DataSourceVariableEditor';
import { GroupByVariableEditor } from './editors/GroupByVariableEditor';
import { IntervalVariableEditor } from './editors/IntervalVariableEditor';
import { QueryVariableEditor } from './editors/QueryVariableEditor';
import { TextBoxVariableEditor } from './editors/TextBoxVariableEditor';
interface EditableVariableConfig {
name: string;
description: string;
editor: React.ComponentType<any>;
}
export type EditableVariableType = Exclude<VariableType, 'system'>;
export function isEditableVariableType(type: VariableType): type is EditableVariableType {
return type !== 'system';
}
export const EDITABLE_VARIABLES: Record<EditableVariableType, EditableVariableConfig> = {
custom: {
name: 'Custom',
description: 'Define variable values manually',
editor: CustomVariableEditor,
},
query: {
name: 'Query',
description: 'Variable values are fetched from a datasource query',
editor: QueryVariableEditor,
},
constant: {
name: 'Constant',
description: 'Define a hidden constant variable, useful for metric prefixes in dashboards you want to share',
editor: ConstantVariableEditor,
},
interval: {
name: 'Interval',
description: 'Define a timespan interval (ex 1m, 1h, 1d)',
editor: IntervalVariableEditor,
},
datasource: {
name: 'Data source',
description: 'Enables you to dynamically switch the data source for multiple panels',
editor: DataSourceVariableEditor,
},
adhoc: {
name: 'Ad hoc filters',
description: 'Add key/value filters on the fly',
editor: AdHocFiltersVariableEditor,
},
groupby: {
name: 'Group by',
description: 'Add keys to group by on the fly',
editor: GroupByVariableEditor,
},
textbox: {
name: 'Textbox',
description: 'Define a textbox variable, where users can enter any arbitrary string',
editor: TextBoxVariableEditor,
},
};
export const EDITABLE_VARIABLES_SELECT_ORDER: EditableVariableType[] = [
'query',
'custom',
'textbox',
'constant',
'datasource',
'interval',
'adhoc',
'groupby',
];
export function getVariableTypeSelectOptions(): Array<SelectableValue<EditableVariableType>> {
const results = EDITABLE_VARIABLES_SELECT_ORDER.map((variableType) => ({
label: EDITABLE_VARIABLES[variableType].name,
value: variableType,
description: EDITABLE_VARIABLES[variableType].description,
}));
if (!config.featureToggles.groupByVariable) {
// Remove group by variable type if feature toggle is off
return results.filter((option) => option.value !== 'groupby');
}
return results;
}
export function getVariableEditor(type: EditableVariableType) {
return EDITABLE_VARIABLES[type].editor;
}
interface CommonVariableProperties {
name: string;
label?: string;
}
export function getVariableScene(type: EditableVariableType, initialState: CommonVariableProperties) {
switch (type) {
case 'custom':
return new CustomVariable(initialState);
case 'query':
return new QueryVariable(initialState);
case 'constant':
return new ConstantVariable(initialState);
case 'interval':
return new IntervalVariable(initialState);
case 'datasource':
return new DataSourceVariable(initialState);
case 'adhoc':
return new AdHocFiltersVariable(initialState);
case 'groupby':
return new GroupByVariable(initialState);
case 'textbox':
return new TextBoxVariable(initialState);
}
}
export function getVariableDefault(variables: Array<SceneVariable<SceneVariableState>>) {
const defaultVariableType = 'query';
const nextVariableIdName = getNextAvailableId(defaultVariableType, variables);
return new QueryVariable({
name: nextVariableIdName,
});
}
export function getNextAvailableId(type: VariableType, variables: Array<SceneVariable<SceneVariableState>>): string {
let counter = 0;
let nextId = `${type}${counter}`;
while (variables.find((variable) => variable.state.name === nextId)) {
nextId = `${type}${++counter}`;
}
return nextId;
}
export function hasVariableOptions(variable: SceneVariable): variable is MultiValueVariable {
// variable options can be defined by state.options or state.intervals in case of interval variable
return 'options' in variable.state || 'intervals' in variable.state;
}
export function getDefinition(model: SceneVariable): string {
let definition = '';
if (model instanceof QueryVariable) {
definition = model.state.definition || (typeof model.state.query === 'string' ? model.state.query : '');
} else if (model instanceof DataSourceVariable) {
definition = String(model.state.pluginId);
} else if (model instanceof CustomVariable) {
definition = model.state.query;
} else if (model instanceof IntervalVariable) {
definition = getIntervalsQueryFromNewIntervalModel(model.state.intervals);
} else if (model instanceof TextBoxVariable || model instanceof ConstantVariable) {
definition = String(model.state.value);
}
return definition;
}
export function getOptionDataSourceTypes() {
const datasources = getDataSourceSrv().getList({ metrics: true, variables: true });
const optionTypes = chain(datasources)
.uniqBy('meta.id')
.map((ds: DataSourceInstanceSettings) => {
return { label: ds.meta.name, value: ds.meta.id };
})
.value();
optionTypes.unshift({ label: '', value: '' });
return optionTypes;
}