diff --git a/packages/grafana-ui/src/types/datasource.ts b/packages/grafana-ui/src/types/datasource.ts index 79c5b22488d..d7f628707da 100644 --- a/packages/grafana-ui/src/types/datasource.ts +++ b/packages/grafana-ui/src/types/datasource.ts @@ -3,9 +3,11 @@ import { PluginMeta } from './plugin'; import { TableData, TimeSeries } from './data'; export interface DataQueryResponse { - data: TimeSeries[] | [TableData] | any; + data: DataQueryResponseData; } +export type DataQueryResponseData = TimeSeries[] | [TableData] | any; + export interface DataQuery { /** * A - Z diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index 619391d46d1..31e5a392050 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -20,6 +20,7 @@ import { ResultType, QueryIntervals, QueryOptions, + ResultGetter, } from 'app/types/explore'; import { LogsDedupStrategy } from 'app/core/logs_model'; @@ -301,11 +302,24 @@ export function getIntervals(range: RawTimeRange, lowLimit: string, resolution: return kbn.calculateInterval(absoluteRange, resolution, lowLimit); } -export function makeTimeSeriesList(dataList) { - return dataList.map((seriesData, index) => { +export const makeTimeSeriesList: ResultGetter = (dataList, transaction, allTransactions) => { + // Prevent multiple Graph transactions to have the same colors + let colorIndexOffset = 0; + for (const other of allTransactions) { + // Only need to consider transactions that came before the current one + if (other === transaction) { + break; + } + // Count timeseries of previous query results + if (other.resultType === 'Graph' && other.done) { + colorIndexOffset += other.result.length; + } + } + + return dataList.map((seriesData, index: number) => { const datapoints = seriesData.datapoints || []; const alias = seriesData.target; - const colorIndex = index % colors.length; + const colorIndex = (colorIndexOffset + index) % colors.length; const color = colors[colorIndex]; const series = new TimeSeries({ @@ -317,7 +331,7 @@ export function makeTimeSeriesList(dataList) { return series; }); -} +}; /** * Update the query history. Side-effect: store history in local storage diff --git a/public/app/features/explore/state/actions.ts b/public/app/features/explore/state/actions.ts index b84a0534836..e0b84320fa7 100644 --- a/public/app/features/explore/state/actions.ts +++ b/public/app/features/explore/state/actions.ts @@ -597,7 +597,8 @@ function runQueriesForType( const res = await datasourceInstance.query(transaction.options); eventBridge.emit('data-received', res.data || []); const latency = Date.now() - now; - const results = resultGetter ? resultGetter(res.data) : res.data; + const { queryTransactions } = getState().explore[exploreId]; + const results = resultGetter ? resultGetter(res.data, transaction, queryTransactions) : res.data; dispatch(queryTransactionSuccess(exploreId, transaction.id, results, latency, queries, datasourceId)); } catch (response) { eventBridge.emit('data-error', response); diff --git a/public/app/types/explore.ts b/public/app/types/explore.ts index 7a6af04b2ee..27894200e51 100644 --- a/public/app/types/explore.ts +++ b/public/app/types/explore.ts @@ -4,13 +4,14 @@ import { RawTimeRange, TimeRange, DataQuery, + DataQueryResponseData, DataSourceSelectItem, DataSourceApi, QueryHint, ExploreStartPageProps, } from '@grafana/ui'; -import { Emitter } from 'app/core/core'; +import { Emitter, TimeSeries } from 'app/core/core'; import { LogsModel, LogsDedupStrategy, LogLevel } from 'app/core/logs_model'; import TableModel from 'app/core/table_model'; @@ -322,6 +323,12 @@ export interface QueryTransaction { export type RangeScanner = () => RawTimeRange; +export type ResultGetter = ( + result: DataQueryResponseData, + transaction: QueryTransaction, + allTransactions: QueryTransaction[] +) => TimeSeries; + export interface TextMatch { text: string; start: number;