From d06b26de262c1dccb9976d506fdc8e6f39b16118 Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Fri, 13 Jul 2018 09:09:36 +0200 Subject: [PATCH] Explore Datasource selector Adds a datasource selector to the Explore UI. Only datasource plugins that have `explore: true` in their `plugin.json` can be selected. - adds datasource selector (based on react-select) to explore UI - adds getExploreSources to datasource service - new `explore` flag in datasource plugins model - Prometheus plugin enabled explore --- pkg/plugins/datasource_plugin.go | 1 + public/app/containers/Explore/Explore.tsx | 92 +++++++++++++++---- public/app/features/plugins/datasource_srv.ts | 33 ++++--- .../plugins/specs/datasource_srv.jest.ts | 30 +++++- .../plugins/datasource/prometheus/plugin.json | 30 ++++-- public/sass/pages/_explore.scss | 4 + 6 files changed, 148 insertions(+), 42 deletions(-) diff --git a/pkg/plugins/datasource_plugin.go b/pkg/plugins/datasource_plugin.go index 2fec6acbf54..cef35a2e7d9 100644 --- a/pkg/plugins/datasource_plugin.go +++ b/pkg/plugins/datasource_plugin.go @@ -22,6 +22,7 @@ type DataSourcePlugin struct { Annotations bool `json:"annotations"` Metrics bool `json:"metrics"` Alerting bool `json:"alerting"` + Explore bool `json:"explore"` QueryOptions map[string]bool `json:"queryOptions,omitempty"` BuiltIn bool `json:"builtIn,omitempty"` Mixed bool `json:"mixed,omitempty"` diff --git a/public/app/containers/Explore/Explore.tsx b/public/app/containers/Explore/Explore.tsx index deebe84f2c8..90bf0941572 100644 --- a/public/app/containers/Explore/Explore.tsx +++ b/public/app/containers/Explore/Explore.tsx @@ -1,16 +1,17 @@ import React from 'react'; import { hot } from 'react-hot-loader'; +import Select from 'react-select'; + import colors from 'app/core/utils/colors'; import TimeSeries from 'app/core/time_series2'; +import { decodePathComponent } from 'app/core/utils/location_util'; import ElapsedTime from './ElapsedTime'; import QueryRows from './QueryRows'; import Graph from './Graph'; import Table from './Table'; import TimePicker, { DEFAULT_RANGE } from './TimePicker'; -import { DatasourceSrv } from 'app/features/plugins/datasource_srv'; import { buildQueryOptions, ensureQueries, generateQueryKey, hasQuery } from './utils/query'; -import { decodePathComponent } from 'app/core/utils/location_util'; function makeTimeSeriesList(dataList, options) { return dataList.map((seriesData, index) => { @@ -46,7 +47,8 @@ function parseInitialState(initial) { interface IExploreState { datasource: any; datasourceError: any; - datasourceLoading: any; + datasourceLoading: boolean | null; + datasourceMissing: boolean; graphResult: any; latency: number; loading: any; @@ -61,15 +63,14 @@ interface IExploreState { // @observer export class Explore extends React.Component { - datasourceSrv: DatasourceSrv; - constructor(props) { super(props); const { range, queries } = parseInitialState(props.routeParams.initial); this.state = { datasource: null, datasourceError: null, - datasourceLoading: true, + datasourceLoading: null, + datasourceMissing: false, graphResult: null, latency: 0, loading: false, @@ -85,19 +86,43 @@ export class Explore extends React.Component { } async componentDidMount() { - const datasource = await this.props.datasourceSrv.get(); - const testResult = await datasource.testDatasource(); - if (testResult.status === 'success') { - this.setState({ datasource, datasourceError: null, datasourceLoading: false }, () => this.handleSubmit()); + const { datasourceSrv } = this.props; + if (!datasourceSrv) { + throw new Error('No datasource service passed as props.'); + } + const datasources = datasourceSrv.getExploreSources(); + if (datasources.length > 0) { + this.setState({ datasourceLoading: true }); + // Try default datasource, otherwise get first + let datasource = await datasourceSrv.get(); + if (!datasource.meta.explore) { + datasource = await datasourceSrv.get(datasources[0].name); + } + this.setDatasource(datasource); } else { - this.setState({ datasource: null, datasourceError: testResult.message, datasourceLoading: false }); + this.setState({ datasourceMissing: true }); } } componentDidCatch(error) { + this.setState({ datasourceError: error }); console.error(error); } + async setDatasource(datasource) { + try { + const testResult = await datasource.testDatasource(); + if (testResult.status === 'success') { + this.setState({ datasource, datasourceError: null, datasourceLoading: false }, () => this.handleSubmit()); + } else { + this.setState({ datasource: datasource, datasourceError: testResult.message, datasourceLoading: false }); + } + } catch (error) { + const message = (error && error.statusText) || error; + this.setState({ datasource: datasource, datasourceError: message, datasourceLoading: false }); + } + } + handleAddQueryRow = index => { const { queries } = this.state; const nextQueries = [ @@ -108,6 +133,18 @@ export class Explore extends React.Component { this.setState({ queries: nextQueries }); }; + handleChangeDatasource = async option => { + this.setState({ + datasource: null, + datasourceError: null, + datasourceLoading: true, + graphResult: null, + tableResult: null, + }); + const datasource = await this.props.datasourceSrv.get(option.value); + this.setDatasource(datasource); + }; + handleChangeQuery = (query, index) => { const { queries } = this.state; const nextQuery = { @@ -226,11 +263,12 @@ export class Explore extends React.Component { }; render() { - const { position, split } = this.props; + const { datasourceSrv, position, split } = this.props; const { datasource, datasourceError, datasourceLoading, + datasourceMissing, graphResult, latency, loading, @@ -247,6 +285,12 @@ export class Explore extends React.Component { const graphButtonActive = showingBoth || showingGraph ? 'active' : ''; const tableButtonActive = showingBoth || showingTable ? 'active' : ''; const exploreClass = split ? 'explore explore-split' : 'explore'; + const datasources = datasourceSrv.getExploreSources().map(ds => ({ + value: ds.name, + label: ds.name, + })); + const selectedDatasource = datasource ? datasource.name : undefined; + return (
@@ -264,6 +308,18 @@ export class Explore extends React.Component {
)} + {!datasourceMissing ? ( +
+