|
@@ -50,6 +50,35 @@ interface ExploreProps {
|
|
|
urlState: ExploreUrlState;
|
|
urlState: ExploreUrlState;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function calulcateResultsFromQueryTransactions(
|
|
|
|
|
+ queryTransactions: QueryTransaction[],
|
|
|
|
|
+ datasource: any,
|
|
|
|
|
+ graphInterval: number
|
|
|
|
|
+) {
|
|
|
|
|
+ const graphResult = _.flatten(
|
|
|
|
|
+ queryTransactions.filter(qt => qt.resultType === 'Graph' && qt.done && qt.result).map(qt => qt.result)
|
|
|
|
|
+ );
|
|
|
|
|
+ const tableResult = mergeTablesIntoModel(
|
|
|
|
|
+ new TableModel(),
|
|
|
|
|
+ ...queryTransactions.filter(qt => qt.resultType === 'Table' && qt.done && qt.result).map(qt => qt.result)
|
|
|
|
|
+ );
|
|
|
|
|
+ const logsResult =
|
|
|
|
|
+ datasource && datasource.mergeStreams
|
|
|
|
|
+ ? datasource.mergeStreams(
|
|
|
|
|
+ _.flatten(
|
|
|
|
|
+ queryTransactions.filter(qt => qt.resultType === 'Logs' && qt.done && qt.result).map(qt => qt.result)
|
|
|
|
|
+ ),
|
|
|
|
|
+ graphInterval
|
|
|
|
|
+ )
|
|
|
|
|
+ : undefined;
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ graphResult,
|
|
|
|
|
+ tableResult,
|
|
|
|
|
+ logsResult,
|
|
|
|
|
+ };
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Explore provides an area for quick query iteration for a given datasource.
|
|
* Explore provides an area for quick query iteration for a given datasource.
|
|
|
* Once a datasource is selected it populates the query section at the top.
|
|
* Once a datasource is selected it populates the query section at the top.
|
|
@@ -122,9 +151,11 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
datasourceMissing: false,
|
|
datasourceMissing: false,
|
|
|
datasourceName: datasource,
|
|
datasourceName: datasource,
|
|
|
exploreDatasources: [],
|
|
exploreDatasources: [],
|
|
|
- graphRange: initialRange,
|
|
|
|
|
|
|
+ graphInterval: 15 * 1000,
|
|
|
|
|
+ graphResult: [],
|
|
|
initialQueries,
|
|
initialQueries,
|
|
|
history: [],
|
|
history: [],
|
|
|
|
|
+ logsResult: null,
|
|
|
queryTransactions: [],
|
|
queryTransactions: [],
|
|
|
range: initialRange,
|
|
range: initialRange,
|
|
|
scanning: false,
|
|
scanning: false,
|
|
@@ -135,6 +166,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
supportsGraph: null,
|
|
supportsGraph: null,
|
|
|
supportsLogs: null,
|
|
supportsLogs: null,
|
|
|
supportsTable: null,
|
|
supportsTable: null,
|
|
|
|
|
+ tableResult: new TableModel(),
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
this.modifiedQueries = initialQueries.slice();
|
|
this.modifiedQueries = initialQueries.slice();
|
|
@@ -176,6 +208,8 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async setDatasource(datasource: any, origin?: DataSource) {
|
|
async setDatasource(datasource: any, origin?: DataSource) {
|
|
|
|
|
+ const { initialQueries, range } = this.state;
|
|
|
|
|
+
|
|
|
const supportsGraph = datasource.meta.metrics;
|
|
const supportsGraph = datasource.meta.metrics;
|
|
|
const supportsLogs = datasource.meta.logs;
|
|
const supportsLogs = datasource.meta.logs;
|
|
|
const supportsTable = datasource.meta.metrics;
|
|
const supportsTable = datasource.meta.metrics;
|
|
@@ -220,7 +254,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Reset edit state with new queries
|
|
// Reset edit state with new queries
|
|
|
- const nextQueries = this.state.initialQueries.map((q, i) => ({
|
|
|
|
|
|
|
+ const nextQueries = initialQueries.map((q, i) => ({
|
|
|
...modifiedQueries[i],
|
|
...modifiedQueries[i],
|
|
|
...generateQueryKeys(i),
|
|
...generateQueryKeys(i),
|
|
|
}));
|
|
}));
|
|
@@ -229,11 +263,15 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
// Custom components
|
|
// Custom components
|
|
|
const StartPage = datasource.pluginExports.ExploreStartPage;
|
|
const StartPage = datasource.pluginExports.ExploreStartPage;
|
|
|
|
|
|
|
|
|
|
+ // Calculate graph bucketing interval
|
|
|
|
|
+ const graphInterval = getIntervals(range, datasource, this.el ? this.el.offsetWidth : 0).intervalMs;
|
|
|
|
|
+
|
|
|
this.setState(
|
|
this.setState(
|
|
|
{
|
|
{
|
|
|
StartPage,
|
|
StartPage,
|
|
|
datasource,
|
|
datasource,
|
|
|
datasourceError,
|
|
datasourceError,
|
|
|
|
|
+ graphInterval,
|
|
|
history,
|
|
history,
|
|
|
supportsGraph,
|
|
supportsGraph,
|
|
|
supportsLogs,
|
|
supportsLogs,
|
|
@@ -414,12 +452,19 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
this.setState(
|
|
this.setState(
|
|
|
state => {
|
|
state => {
|
|
|
const showingTable = !state.showingTable;
|
|
const showingTable = !state.showingTable;
|
|
|
- let nextQueryTransactions = state.queryTransactions;
|
|
|
|
|
- if (!showingTable) {
|
|
|
|
|
- // Discard transactions related to Table query
|
|
|
|
|
- nextQueryTransactions = state.queryTransactions.filter(qt => qt.resultType !== 'Table');
|
|
|
|
|
|
|
+ if (showingTable) {
|
|
|
|
|
+ return { showingTable, queryTransactions: state.queryTransactions };
|
|
|
}
|
|
}
|
|
|
- return { queryTransactions: nextQueryTransactions, showingTable };
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // Toggle off needs discarding of table queries
|
|
|
|
|
+ const nextQueryTransactions = state.queryTransactions.filter(qt => qt.resultType !== 'Table');
|
|
|
|
|
+ const results = calulcateResultsFromQueryTransactions(
|
|
|
|
|
+ nextQueryTransactions,
|
|
|
|
|
+ state.datasource,
|
|
|
|
|
+ state.graphInterval
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ return { ...results, queryTransactions: nextQueryTransactions, showingTable };
|
|
|
},
|
|
},
|
|
|
() => {
|
|
() => {
|
|
|
if (this.state.showingTable) {
|
|
if (this.state.showingTable) {
|
|
@@ -500,8 +545,14 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
|
|
|
|
|
// Discard transactions related to row query
|
|
// Discard transactions related to row query
|
|
|
const nextQueryTransactions = queryTransactions.filter(qt => qt.rowIndex !== index);
|
|
const nextQueryTransactions = queryTransactions.filter(qt => qt.rowIndex !== index);
|
|
|
|
|
+ const results = calulcateResultsFromQueryTransactions(
|
|
|
|
|
+ nextQueryTransactions,
|
|
|
|
|
+ state.datasource,
|
|
|
|
|
+ state.graphInterval
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
return {
|
|
return {
|
|
|
|
|
+ ...results,
|
|
|
initialQueries: nextQueries,
|
|
initialQueries: nextQueries,
|
|
|
queryTransactions: nextQueryTransactions,
|
|
queryTransactions: nextQueryTransactions,
|
|
|
};
|
|
};
|
|
@@ -609,7 +660,14 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
// Append new transaction
|
|
// Append new transaction
|
|
|
const nextQueryTransactions = [...remainingTransactions, transaction];
|
|
const nextQueryTransactions = [...remainingTransactions, transaction];
|
|
|
|
|
|
|
|
|
|
+ const results = calulcateResultsFromQueryTransactions(
|
|
|
|
|
+ nextQueryTransactions,
|
|
|
|
|
+ state.datasource,
|
|
|
|
|
+ state.graphInterval
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
return {
|
|
return {
|
|
|
|
|
+ ...results,
|
|
|
queryTransactions: nextQueryTransactions,
|
|
queryTransactions: nextQueryTransactions,
|
|
|
showingStartPage: false,
|
|
showingStartPage: false,
|
|
|
};
|
|
};
|
|
@@ -660,6 +718,12 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
return qt;
|
|
return qt;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ const results = calulcateResultsFromQueryTransactions(
|
|
|
|
|
+ nextQueryTransactions,
|
|
|
|
|
+ state.datasource,
|
|
|
|
|
+ state.graphInterval
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
const nextHistory = updateHistory(history, datasourceId, queries);
|
|
const nextHistory = updateHistory(history, datasourceId, queries);
|
|
|
|
|
|
|
|
// Keep scanning for results if this was the last scanning transaction
|
|
// Keep scanning for results if this was the last scanning transaction
|
|
@@ -671,19 +735,13 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
return {
|
|
|
|
|
+ ...results,
|
|
|
history: nextHistory,
|
|
history: nextHistory,
|
|
|
queryTransactions: nextQueryTransactions,
|
|
queryTransactions: nextQueryTransactions,
|
|
|
};
|
|
};
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- discardTransactions(rowIndex: number) {
|
|
|
|
|
- this.setState(state => {
|
|
|
|
|
- const remainingTransactions = state.queryTransactions.filter(qt => qt.rowIndex !== rowIndex);
|
|
|
|
|
- return { queryTransactions: remainingTransactions };
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
failQueryTransaction(transactionId: string, response: any, datasourceId: string) {
|
|
failQueryTransaction(transactionId: string, response: any, datasourceId: string) {
|
|
|
const { datasource } = this.state;
|
|
const { datasource } = this.state;
|
|
|
if (datasource.meta.id !== datasourceId || response.cancelled) {
|
|
if (datasource.meta.id !== datasourceId || response.cancelled) {
|
|
@@ -746,7 +804,6 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
const latency = Date.now() - now;
|
|
const latency = Date.now() - now;
|
|
|
const results = resultGetter ? resultGetter(res.data) : res.data;
|
|
const results = resultGetter ? resultGetter(res.data) : res.data;
|
|
|
this.completeQueryTransaction(transaction.id, results, latency, queries, datasourceId);
|
|
this.completeQueryTransaction(transaction.id, results, latency, queries, datasourceId);
|
|
|
- this.setState({ graphRange: transaction.options.range });
|
|
|
|
|
} catch (response) {
|
|
} catch (response) {
|
|
|
this.failQueryTransaction(transaction.id, response, datasourceId);
|
|
this.failQueryTransaction(transaction.id, response, datasourceId);
|
|
|
}
|
|
}
|
|
@@ -776,9 +833,10 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
datasourceLoading,
|
|
datasourceLoading,
|
|
|
datasourceMissing,
|
|
datasourceMissing,
|
|
|
exploreDatasources,
|
|
exploreDatasources,
|
|
|
- graphRange,
|
|
|
|
|
|
|
+ graphResult,
|
|
|
history,
|
|
history,
|
|
|
initialQueries,
|
|
initialQueries,
|
|
|
|
|
+ logsResult,
|
|
|
queryTransactions,
|
|
queryTransactions,
|
|
|
range,
|
|
range,
|
|
|
scanning,
|
|
scanning,
|
|
@@ -790,31 +848,14 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
supportsGraph,
|
|
supportsGraph,
|
|
|
supportsLogs,
|
|
supportsLogs,
|
|
|
supportsTable,
|
|
supportsTable,
|
|
|
|
|
+ tableResult,
|
|
|
} = this.state;
|
|
} = this.state;
|
|
|
const graphHeight = showingGraph && showingTable ? '200px' : '400px';
|
|
const graphHeight = showingGraph && showingTable ? '200px' : '400px';
|
|
|
const exploreClass = split ? 'explore explore-split' : 'explore';
|
|
const exploreClass = split ? 'explore explore-split' : 'explore';
|
|
|
const selectedDatasource = datasource ? exploreDatasources.find(d => d.label === datasource.name) : undefined;
|
|
const selectedDatasource = datasource ? exploreDatasources.find(d => d.label === datasource.name) : undefined;
|
|
|
- const graphRangeIntervals = getIntervals(graphRange, datasource, this.el ? this.el.offsetWidth : 0);
|
|
|
|
|
const graphLoading = queryTransactions.some(qt => qt.resultType === 'Graph' && !qt.done);
|
|
const graphLoading = queryTransactions.some(qt => qt.resultType === 'Graph' && !qt.done);
|
|
|
const tableLoading = queryTransactions.some(qt => qt.resultType === 'Table' && !qt.done);
|
|
const tableLoading = queryTransactions.some(qt => qt.resultType === 'Table' && !qt.done);
|
|
|
const logsLoading = queryTransactions.some(qt => qt.resultType === 'Logs' && !qt.done);
|
|
const logsLoading = queryTransactions.some(qt => qt.resultType === 'Logs' && !qt.done);
|
|
|
- // TODO don't recreate those on each re-render
|
|
|
|
|
- const graphResult = _.flatten(
|
|
|
|
|
- queryTransactions.filter(qt => qt.resultType === 'Graph' && qt.done && qt.result).map(qt => qt.result)
|
|
|
|
|
- );
|
|
|
|
|
- const tableResult = mergeTablesIntoModel(
|
|
|
|
|
- new TableModel(),
|
|
|
|
|
- ...queryTransactions.filter(qt => qt.resultType === 'Table' && qt.done && qt.result).map(qt => qt.result)
|
|
|
|
|
- );
|
|
|
|
|
- const logsResult =
|
|
|
|
|
- datasource && datasource.mergeStreams
|
|
|
|
|
- ? datasource.mergeStreams(
|
|
|
|
|
- _.flatten(
|
|
|
|
|
- queryTransactions.filter(qt => qt.resultType === 'Logs' && qt.done && qt.result).map(qt => qt.result)
|
|
|
|
|
- ),
|
|
|
|
|
- graphRangeIntervals.intervalMs
|
|
|
|
|
- )
|
|
|
|
|
- : undefined;
|
|
|
|
|
const loading = queryTransactions.some(qt => !qt.done);
|
|
const loading = queryTransactions.some(qt => !qt.done);
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
@@ -919,7 +960,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|
|
height={graphHeight}
|
|
height={graphHeight}
|
|
|
id={`explore-graph-${position}`}
|
|
id={`explore-graph-${position}`}
|
|
|
onChangeTime={this.onChangeTime}
|
|
onChangeTime={this.onChangeTime}
|
|
|
- range={graphRange}
|
|
|
|
|
|
|
+ range={range}
|
|
|
split={split}
|
|
split={split}
|
|
|
/>
|
|
/>
|
|
|
</Panel>
|
|
</Panel>
|