From 591ea0bfe30c097dbd58921fbf67f3a798698209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Mon, 10 Jun 2019 14:39:53 +0200 Subject: [PATCH] Explore: Adds LogQueryField for InfluxDb (#17450) * Wip: Intial commit * Wip: Adds intial InfluxLogsQueryField * Refactor: Adds measurements to InfluxLogQueryField * Style: Tweaks styles and adds chosen measurement to measurements * Refactor: Adds remove filter row * refactor: make influx datasource typed Uses the new api for exporting the plugin. * adds metricFindQuery to DataSourceApi metricFindQuery, getTagKeys and getTagValues now returns a promise * influx: minor improvements Limits logs result to 1000. Don't show adhoc filter until measurement have been selected. * Refactor: Adds fields to Cascader and uses chosen field as log column Co-authored-by: Marcus --- packages/grafana-ui/src/types/datasource.ts | 25 ++++ public/app/features/explore/AdHocFilter.tsx | 83 +++++++++++ .../app/features/explore/AdHocFilterField.tsx | 138 ++++++++++++++++++ .../components/InfluxLogsQueryField.tsx | 102 +++++++++++++ .../plugins/datasource/influxdb/datasource.ts | 24 ++- ...{influx_query.ts => influx_query_model.ts} | 8 +- .../app/plugins/datasource/influxdb/module.ts | 13 +- .../plugins/datasource/influxdb/plugin.json | 1 + .../plugins/datasource/influxdb/query_ctrl.ts | 6 +- ...ery.test.ts => influx_query_model.test.ts} | 64 +++++--- .../app/plugins/datasource/influxdb/types.ts | 35 +++++ .../datasource/input/InputDatasource.ts | 3 +- public/sass/utils/_utils.scss | 11 ++ 13 files changed, 472 insertions(+), 41 deletions(-) create mode 100644 public/app/features/explore/AdHocFilter.tsx create mode 100644 public/app/features/explore/AdHocFilterField.tsx create mode 100644 public/app/plugins/datasource/influxdb/components/InfluxLogsQueryField.tsx rename public/app/plugins/datasource/influxdb/{influx_query.ts => influx_query_model.ts} (97%) rename public/app/plugins/datasource/influxdb/specs/{influx_query.test.ts => influx_query_model.test.ts} (87%) create mode 100644 public/app/plugins/datasource/influxdb/types.ts diff --git a/packages/grafana-ui/src/types/datasource.ts b/packages/grafana-ui/src/types/datasource.ts index 22bf4b060b9..b9f4a574972 100644 --- a/packages/grafana-ui/src/types/datasource.ts +++ b/packages/grafana-ui/src/types/datasource.ts @@ -30,6 +30,11 @@ export class DataSourcePlugin< return this; } + setConfigCtrl(ConfigCtrl: any) { + this.angularConfigCtrl = ConfigCtrl; + return this; + } + setQueryCtrl(QueryCtrl: any) { this.components.QueryCtrl = QueryCtrl; return this; @@ -199,6 +204,21 @@ export abstract class DataSourceApi< options?: TContextQueryOptions ) => Promise; + /** + * Variable query action. + */ + metricFindQuery?(query: any, options?: any): Promise; + + /** + * Get tag keys for adhoc filters + */ + getTagKeys?(options: any): Promise; + + /** + * Get tag values for adhoc filters + */ + getTagValues?(options: { key: any }): Promise; + /** * Set after constructor call, as the data source instance is the most common thing to pass around * we attach the components to this instance for easy access @@ -396,6 +416,10 @@ export interface QueryHint { fix?: QueryFix; } +export interface MetricFindValue { + text: string; +} + export interface DataSourceJsonData { authType?: string; defaultRegion?: string; @@ -440,6 +464,7 @@ export interface DataSourceInstanceSettings ({ + keyValueContainer: css` + label: key-value-container; + display: flex; + flex-flow: row nowrap; + `, +}); + +enum ChangeType { + Key = 'key', + Value = 'value', + Operator = 'operator', +} + +export interface Props { + keys: string[]; + keysPlaceHolder?: string; + initialKey?: string; + initialOperator?: string; + initialValue?: string; + values?: string[]; + valuesPlaceHolder?: string; + onKeyChanged: (key: string) => void; + onValueChanged: (value: string) => void; + onOperatorChanged: (operator: string) => void; +} + +export const AdHocFilter: React.FunctionComponent = props => { + const theme = useContext(ThemeContext); + const styles = getStyles(theme); + + const onChange = (changeType: ChangeType) => (item: SelectOptionItem) => { + const { onKeyChanged, onValueChanged, onOperatorChanged } = props; + switch (changeType) { + case ChangeType.Key: + onKeyChanged(item.value); + break; + case ChangeType.Operator: + onOperatorChanged(item.value); + break; + case ChangeType.Value: + onValueChanged(item.value); + break; + } + }; + + const stringToOption = (value: string) => ({ label: value, value: value }); + + const { keys, initialKey, keysPlaceHolder, initialOperator, values, initialValue, valuesPlaceHolder } = props; + const operators = ['=', '!=']; + const keysAsOptions = keys ? keys.map(stringToOption) : []; + const selectedKey = initialKey ? keysAsOptions.filter(option => option.value === initialKey) : null; + const valuesAsOptions = values ? values.map(stringToOption) : []; + const selectedValue = initialValue ? valuesAsOptions.filter(option => option.value === initialValue) : null; + const operatorsAsOptions = operators.map(stringToOption); + const selectedOperator = initialOperator + ? operatorsAsOptions.filter(option => option.value === initialOperator) + : null; + + return ( +
+ +