mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
InfluxDB: Introduce custom variable support (#87903)
* Introduce custom variable support * Remove comment lines * betterer
This commit is contained in:
parent
a2aea70100
commit
9bdfb6ee13
@ -5555,12 +5555,6 @@ exports[`no gf-form usage`] = {
|
||||
"public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/TagsSection.tsx:5381": [
|
||||
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"]
|
||||
],
|
||||
"public/app/plugins/datasource/influxdb/components/editor/variable/VariableQueryEditor.tsx:5381": [
|
||||
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"],
|
||||
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"],
|
||||
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"],
|
||||
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"]
|
||||
],
|
||||
"public/app/plugins/datasource/loki/components/LokiQueryField.tsx:5381": [
|
||||
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"],
|
||||
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"],
|
||||
|
@ -20,7 +20,7 @@ export const QueryEditor = ({ query, onChange, onRunQuery, datasource }: Props)
|
||||
case InfluxVersion.Flux:
|
||||
return (
|
||||
<div className="gf-form-query-content">
|
||||
<FluxQueryEditor query={query} onChange={onChange} onRunQuery={onRunQuery} datasource={datasource} />
|
||||
<FluxQueryEditor query={query} onChange={onChange} datasource={datasource} />
|
||||
</div>
|
||||
);
|
||||
case InfluxVersion.SQL:
|
||||
|
@ -20,7 +20,6 @@ import { InfluxQuery } from '../../../../types';
|
||||
|
||||
interface Props extends Themeable2 {
|
||||
onChange: (query: InfluxQuery) => void;
|
||||
onRunQuery: () => void;
|
||||
query: InfluxQuery;
|
||||
// `datasource` is not used internally, but this component is used at some places
|
||||
// directly, where the `datasource` prop has to exist. later, when the whole
|
||||
@ -98,7 +97,6 @@ v1.tagValues(
|
||||
class UnthemedFluxQueryEditor extends PureComponent<Props> {
|
||||
onFluxQueryChange = (query: string) => {
|
||||
this.props.onChange({ ...this.props.query, query });
|
||||
this.props.onRunQuery();
|
||||
};
|
||||
|
||||
onSampleChange = (val: SelectableValue<string>) => {
|
||||
@ -109,7 +107,6 @@ class UnthemedFluxQueryEditor extends PureComponent<Props> {
|
||||
|
||||
// Angular HACK: Since the target does not actually change!
|
||||
this.forceUpdate();
|
||||
this.props.onRunQuery();
|
||||
};
|
||||
|
||||
getSuggestions = (): CodeEditorSuggestionItem[] => {
|
||||
|
@ -1,68 +1,75 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
import { Field, FieldSet, InlineFormLabel, TextArea } from '@grafana/ui';
|
||||
import { QueryEditorProps } from '@grafana/data';
|
||||
import { Field, FieldSet, InlineFieldRow, TextArea } from '@grafana/ui';
|
||||
import { InlineField } from '@grafana/ui/';
|
||||
|
||||
import InfluxDatasource from '../../../datasource';
|
||||
import { InfluxVersion } from '../../../types';
|
||||
import { InfluxOptions, InfluxQuery, InfluxVariableQuery, InfluxVersion } from '../../../types';
|
||||
import { FluxQueryEditor } from '../query/flux/FluxQueryEditor';
|
||||
|
||||
interface Props {
|
||||
query: string; // before flux, it was always a string
|
||||
onChange: (query?: string) => void;
|
||||
datasource: InfluxDatasource;
|
||||
}
|
||||
export type Props = QueryEditorProps<InfluxDatasource, InfluxQuery, InfluxOptions, InfluxVariableQuery>;
|
||||
|
||||
export default class VariableQueryEditor extends PureComponent<Props> {
|
||||
onRefresh = () => {
|
||||
// noop
|
||||
const refId = 'InfluxVariableQueryEditor-VariableQuery';
|
||||
|
||||
const useVariableQuery = (query: InfluxVariableQuery | string): InfluxVariableQuery => {
|
||||
// in legacy variable support query can be only a string
|
||||
// in new variable support query can be an object and hold more information
|
||||
// to be able to support old version we check the query here
|
||||
if (typeof query === 'string') {
|
||||
return {
|
||||
refId,
|
||||
query,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
refId,
|
||||
query: query.query ?? '',
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export const InfluxVariableEditor = ({ onChange, datasource, query }: Props) => {
|
||||
const varQuery = useVariableQuery(query);
|
||||
|
||||
const onChangeHandler = (q: InfluxQuery) => {
|
||||
onChange({ refId, query: q.query || '' });
|
||||
};
|
||||
|
||||
render() {
|
||||
let { query, datasource, onChange } = this.props;
|
||||
const onBlurHandler = (e: React.FocusEvent<HTMLTextAreaElement>) => {
|
||||
onChange({ refId, query: e.currentTarget.value });
|
||||
};
|
||||
|
||||
switch (datasource.version) {
|
||||
case InfluxVersion.Flux:
|
||||
return (
|
||||
<FluxQueryEditor
|
||||
datasource={datasource}
|
||||
query={{
|
||||
refId: 'A',
|
||||
query,
|
||||
}}
|
||||
onRunQuery={this.onRefresh}
|
||||
onChange={(v) => onChange(v.query)}
|
||||
/>
|
||||
);
|
||||
case InfluxVersion.SQL:
|
||||
return (
|
||||
<FieldSet>
|
||||
<Field htmlFor="influx-sql-variable-query">
|
||||
<TextArea
|
||||
id="influx-sql-variable-query"
|
||||
defaultValue={query || ''}
|
||||
placeholder="metric name or tags query"
|
||||
rows={1}
|
||||
onBlur={(e) => onChange(e.currentTarget.value)}
|
||||
/>
|
||||
</Field>
|
||||
</FieldSet>
|
||||
);
|
||||
case InfluxVersion.InfluxQL:
|
||||
default:
|
||||
return (
|
||||
<div className="gf-form-inline">
|
||||
<InlineFormLabel width={10}>Query</InlineFormLabel>
|
||||
<div className="gf-form-inline gf-form--grow">
|
||||
<TextArea
|
||||
defaultValue={query || ''}
|
||||
placeholder="metric name or tags query"
|
||||
rows={1}
|
||||
className="gf-form-input"
|
||||
onBlur={(e) => onChange(e.currentTarget.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
switch (datasource.version) {
|
||||
case InfluxVersion.Flux:
|
||||
return <FluxQueryEditor datasource={datasource} query={varQuery} onChange={onChangeHandler} />;
|
||||
case InfluxVersion.SQL:
|
||||
return (
|
||||
<FieldSet>
|
||||
<Field htmlFor="influx-sql-variable-query">
|
||||
<TextArea
|
||||
id="influx-sql-variable-query"
|
||||
defaultValue={varQuery.query || ''}
|
||||
placeholder="metric name or tags query"
|
||||
rows={1}
|
||||
onBlur={onBlurHandler}
|
||||
/>
|
||||
</Field>
|
||||
</FieldSet>
|
||||
);
|
||||
case InfluxVersion.InfluxQL:
|
||||
default:
|
||||
return (
|
||||
<InlineFieldRow>
|
||||
<InlineField label="Query" labelWidth={20} required grow aria-labelledby="label-select">
|
||||
<TextArea
|
||||
defaultValue={varQuery.query || ''}
|
||||
placeholder="metric name or tags query"
|
||||
rows={1}
|
||||
onBlur={onBlurHandler}
|
||||
/>
|
||||
</InlineField>
|
||||
</InlineFieldRow>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -49,6 +49,7 @@ import { prepareAnnotation } from './migrations';
|
||||
import { buildRawQuery, removeRegexWrapper } from './queryUtils';
|
||||
import ResponseParser from './response_parser';
|
||||
import { DEFAULT_POLICY, InfluxOptions, InfluxQuery, InfluxQueryTag, InfluxVersion } from './types';
|
||||
import { InfluxVariableSupport } from './variables';
|
||||
|
||||
export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery, InfluxOptions> {
|
||||
type: string;
|
||||
@ -89,6 +90,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
||||
this.responseParser = new ResponseParser();
|
||||
this.version = settingsData.version ?? InfluxVersion.InfluxQL;
|
||||
this.isProxyAccess = instanceSettings.access === 'proxy';
|
||||
this.variables = new InfluxVariableSupport(this, this.templateSrv);
|
||||
|
||||
if (this.version === InfluxVersion.Flux) {
|
||||
// When flux, use an annotation processor rather than the `annotationQuery` lifecycle
|
||||
|
@ -3,11 +3,9 @@ import { DataSourcePlugin } from '@grafana/data';
|
||||
import ConfigEditor from './components/editor/config/ConfigEditor';
|
||||
import { QueryEditor } from './components/editor/query/QueryEditor';
|
||||
import { InfluxStartPage } from './components/editor/query/influxql/InfluxStartPage';
|
||||
import VariableQueryEditor from './components/editor/variable/VariableQueryEditor';
|
||||
import InfluxDatasource from './datasource';
|
||||
|
||||
export const plugin = new DataSourcePlugin(InfluxDatasource)
|
||||
.setConfigEditor(ConfigEditor)
|
||||
.setQueryEditor(QueryEditor)
|
||||
.setVariableQueryEditor(VariableQueryEditor)
|
||||
.setQueryEditorHelp(InfluxStartPage);
|
||||
|
@ -60,6 +60,10 @@ export interface InfluxQueryTag {
|
||||
|
||||
export type ResultFormat = 'time_series' | 'table' | 'logs';
|
||||
|
||||
export interface InfluxVariableQuery extends DataQuery {
|
||||
query: string;
|
||||
}
|
||||
|
||||
export interface InfluxQuery extends DataQuery {
|
||||
policy?: string;
|
||||
measurement?: string;
|
||||
|
37
public/app/plugins/datasource/influxdb/variables.ts
Normal file
37
public/app/plugins/datasource/influxdb/variables.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { from, Observable, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { CustomVariableSupport, DataQueryRequest, DataQueryResponse } from '@grafana/data';
|
||||
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||
|
||||
import { InfluxVariableEditor } from './components/editor/variable/VariableQueryEditor';
|
||||
import InfluxDatasource from './datasource';
|
||||
import { InfluxVariableQuery } from './types';
|
||||
|
||||
export class InfluxVariableSupport extends CustomVariableSupport<InfluxDatasource> {
|
||||
editor = InfluxVariableEditor;
|
||||
|
||||
constructor(
|
||||
private readonly datasource: InfluxDatasource,
|
||||
private readonly templateSrv: TemplateSrv = getTemplateSrv()
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
query(request: DataQueryRequest<InfluxVariableQuery>): Observable<DataQueryResponse> {
|
||||
let query: string | undefined;
|
||||
if (typeof request.targets[0] === 'string') {
|
||||
query = request.targets[0];
|
||||
} else {
|
||||
query = request.targets[0].query;
|
||||
}
|
||||
|
||||
if (!query) {
|
||||
return of({ data: [] });
|
||||
}
|
||||
|
||||
const interpolated = this.templateSrv.replace(query, request.scopedVars, this.datasource.interpolateQueryExpr);
|
||||
const metricFindStream = from(this.datasource.metricFindQuery(interpolated, request.range));
|
||||
return metricFindStream.pipe(map((results) => ({ data: results })));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user