Renamed targets to queries

This commit is contained in:
David Kaltschmidt 2018-11-21 16:28:30 +01:00
parent b3161bea5a
commit 22987ee75f
10 changed files with 168 additions and 168 deletions

View File

@ -10,7 +10,7 @@ const DEFAULT_EXPLORE_STATE: ExploreState = {
exploreDatasources: [],
graphRange: DEFAULT_RANGE,
history: [],
initialTargets: [],
initialQueries: [],
queryTransactions: [],
range: DEFAULT_RANGE,
showingGraph: true,
@ -26,17 +26,17 @@ describe('state functions', () => {
it('returns default state on empty string', () => {
expect(parseUrlState('')).toMatchObject({
datasource: null,
targets: [],
queries: [],
range: DEFAULT_RANGE,
});
});
it('returns a valid Explore state from URL parameter', () => {
const paramValue =
'%7B"datasource":"Local","targets":%5B%7B"expr":"metric"%7D%5D,"range":%7B"from":"now-1h","to":"now"%7D%7D';
'%7B"datasource":"Local","queries":%5B%7B"expr":"metric"%7D%5D,"range":%7B"from":"now-1h","to":"now"%7D%7D';
expect(parseUrlState(paramValue)).toMatchObject({
datasource: 'Local',
targets: [{ expr: 'metric' }],
queries: [{ expr: 'metric' }],
range: {
from: 'now-1h',
to: 'now',
@ -48,7 +48,7 @@ describe('state functions', () => {
const paramValue = '%5B"now-1h","now","Local",%7B"expr":"metric"%7D%5D';
expect(parseUrlState(paramValue)).toMatchObject({
datasource: 'Local',
targets: [{ expr: 'metric' }],
queries: [{ expr: 'metric' }],
range: {
from: 'now-1h',
to: 'now',
@ -66,7 +66,7 @@ describe('state functions', () => {
from: 'now-5h',
to: 'now',
},
initialTargets: [
initialQueries: [
{
refId: '1',
expr: 'metric{test="a/b"}',
@ -78,7 +78,7 @@ describe('state functions', () => {
],
};
expect(serializeStateToUrlParam(state)).toBe(
'{"datasource":"foo","targets":[{"expr":"metric{test=\\"a/b\\"}"},' +
'{"datasource":"foo","queries":[{"expr":"metric{test=\\"a/b\\"}"},' +
'{"expr":"super{foo=\\"x/z\\"}"}],"range":{"from":"now-5h","to":"now"}}'
);
});
@ -91,7 +91,7 @@ describe('state functions', () => {
from: 'now-5h',
to: 'now',
},
initialTargets: [
initialQueries: [
{
refId: '1',
expr: 'metric{test="a/b"}',
@ -117,7 +117,7 @@ describe('state functions', () => {
from: 'now - 5h',
to: 'now',
},
initialTargets: [
initialQueries: [
{
refId: '1',
expr: 'metric{test="a/b"}',
@ -132,12 +132,12 @@ describe('state functions', () => {
const parsed = parseUrlState(serialized);
// Account for datasource vs datasourceName
const { datasource, targets, ...rest } = parsed;
const { datasource, queries, ...rest } = parsed;
const resultState = {
...rest,
datasource: DEFAULT_EXPLORE_STATE.datasource,
datasourceName: datasource,
initialTargets: targets,
initialQueries: queries,
};
expect(state).toMatchObject(resultState);

View File

@ -32,7 +32,7 @@ export async function getExploreUrl(
timeSrv: any
) {
let exploreDatasource = panelDatasource;
let exploreTargets = panelTargets;
let exploreTargets: DataQuery[] = panelTargets;
let url;
// Mixed datasources need to choose only one datasource
@ -79,25 +79,25 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState {
to: parsed[1],
};
const datasource = parsed[2];
const targets = parsed.slice(3);
return { datasource, targets, range };
const queries = parsed.slice(3);
return { datasource, queries, range };
}
return parsed;
} catch (e) {
console.error(e);
}
}
return { datasource: null, targets: [], range: DEFAULT_RANGE };
return { datasource: null, queries: [], range: DEFAULT_RANGE };
}
export function serializeStateToUrlParam(state: ExploreState, compact?: boolean): string {
const urlState: ExploreUrlState = {
datasource: state.datasourceName,
targets: state.initialTargets.map(({ key, refId, ...rest }) => rest),
queries: state.initialQueries.map(({ key, refId, ...rest }) => rest),
range: state.range,
};
if (compact) {
return JSON.stringify([urlState.range.from, urlState.range.to, urlState.datasource, ...urlState.targets]);
return JSON.stringify([urlState.range.from, urlState.range.to, urlState.datasource, ...urlState.queries]);
}
return JSON.stringify(urlState);
}
@ -110,25 +110,25 @@ export function generateRefId(index = 0): string {
return `${index + 1}`;
}
export function generateTargetKeys(index = 0): { refId: string; key: string } {
export function generateQueryKeys(index = 0): { refId: string; key: string } {
return { refId: generateRefId(index), key: generateKey(index) };
}
/**
* Ensure at least one target exists and that targets have the necessary keys
*/
export function ensureTargets(targets?: DataQuery[]): DataQuery[] {
if (targets && typeof targets === 'object' && targets.length > 0) {
return targets.map((target, i) => ({ ...target, ...generateTargetKeys(i) }));
export function ensureQueries(queries?: DataQuery[]): DataQuery[] {
if (queries && typeof queries === 'object' && queries.length > 0) {
return queries.map((query, i) => ({ ...query, ...generateQueryKeys(i) }));
}
return [{ ...generateTargetKeys() }];
return [{ ...generateQueryKeys() }];
}
/**
* A target is non-empty when it has keys other than refId and key.
*/
export function hasNonEmptyTarget(targets: DataQuery[]): boolean {
return targets.some(target => Object.keys(target).length > 2);
export function hasNonEmptyQuery(queries: DataQuery[]): boolean {
return queries.some(query => Object.keys(query).length > 2);
}
export function getIntervals(
@ -146,7 +146,7 @@ export function getIntervals(
return kbn.calculateInterval(absoluteRange, resolution, datasource.interval);
}
export function makeTimeSeriesList(dataList, options) {
export function makeTimeSeriesList(dataList) {
return dataList.map((seriesData, index) => {
const datapoints = seriesData.datapoints || [];
const alias = seriesData.target;
@ -167,10 +167,10 @@ export function makeTimeSeriesList(dataList, options) {
/**
* Update the query history. Side-effect: store history in local storage
*/
export function updateHistory(history: HistoryItem[], datasourceId: string, targets: DataQuery[]): HistoryItem[] {
export function updateHistory(history: HistoryItem[], datasourceId: string, queries: DataQuery[]): HistoryItem[] {
const ts = Date.now();
targets.forEach(target => {
history = [{ target, ts }, ...history];
queries.forEach(query => {
history = [{ query, ts }, ...history];
});
if (history.length > MAX_HISTORY_ITEMS) {

View File

@ -16,11 +16,11 @@ import { RawTimeRange, DataQuery } from 'app/types/series';
import store from 'app/core/store';
import {
DEFAULT_RANGE,
ensureTargets,
ensureQueries,
getIntervals,
generateKey,
generateTargetKeys,
hasNonEmptyTarget,
generateQueryKeys,
hasNonEmptyQuery,
makeTimeSeriesList,
updateHistory,
} from 'app/core/utils/explore';
@ -63,7 +63,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
* Current query expressions of the rows including their modifications, used for running queries.
* Not kept in component state to prevent edit-render roundtrips.
*/
modifiedTargets: DataQuery[];
modifiedQueries: DataQuery[];
/**
* Local ID cache to compare requested vs selected datasource
*/
@ -72,14 +72,14 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
constructor(props) {
super(props);
const splitState: ExploreState = props.splitState;
let initialTargets: DataQuery[];
let initialQueries: DataQuery[];
if (splitState) {
// Split state overrides everything
this.state = splitState;
initialTargets = splitState.initialTargets;
initialQueries = splitState.initialQueries;
} else {
const { datasource, targets, range } = props.urlState as ExploreUrlState;
initialTargets = ensureTargets(targets);
const { datasource, queries, range } = props.urlState as ExploreUrlState;
initialQueries = ensureQueries(queries);
const initialRange = range || { ...DEFAULT_RANGE };
this.state = {
datasource: null,
@ -89,7 +89,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
datasourceName: datasource,
exploreDatasources: [],
graphRange: initialRange,
initialTargets,
initialQueries,
history: [],
queryTransactions: [],
range: initialRange,
@ -102,7 +102,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
supportsTable: null,
};
}
this.modifiedTargets = initialTargets.slice();
this.modifiedQueries = initialQueries.slice();
}
async componentDidMount() {
@ -165,26 +165,26 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
}
// Check if queries can be imported from previously selected datasource
let modifiedTargets = this.modifiedTargets;
let modifiedQueries = this.modifiedQueries;
if (origin) {
if (origin.meta.id === datasource.meta.id) {
// Keep same queries if same type of datasource
modifiedTargets = [...this.modifiedTargets];
modifiedQueries = [...this.modifiedQueries];
} else if (datasource.importQueries) {
// Datasource-specific importers
modifiedTargets = await datasource.importQueries(this.modifiedTargets, origin.meta);
modifiedQueries = await datasource.importQueries(this.modifiedQueries, origin.meta);
} else {
// Default is blank queries
modifiedTargets = ensureTargets();
modifiedQueries = ensureQueries();
}
}
// Reset edit state with new queries
const nextTargets = this.state.initialTargets.map((q, i) => ({
...modifiedTargets[i],
...generateTargetKeys(i),
const nextQueries = this.state.initialQueries.map((q, i) => ({
...modifiedQueries[i],
...generateQueryKeys(i),
}));
this.modifiedTargets = modifiedTargets;
this.modifiedQueries = modifiedQueries;
// Custom components
const StartPage = datasource.pluginExports.ExploreStartPage;
@ -200,7 +200,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
supportsTable,
datasourceLoading: false,
datasourceName: datasource.name,
initialTargets: nextTargets,
initialQueries: nextQueries,
showingStartPage: Boolean(StartPage),
},
() => {
@ -217,15 +217,15 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
onAddQueryRow = index => {
// Local cache
this.modifiedTargets[index + 1] = { ...generateTargetKeys(index + 1) };
this.modifiedQueries[index + 1] = { ...generateQueryKeys(index + 1) };
this.setState(state => {
const { initialTargets, queryTransactions } = state;
const { initialQueries, queryTransactions } = state;
const nextTargets = [
...initialTargets.slice(0, index + 1),
{ ...this.modifiedTargets[index + 1] },
...initialTargets.slice(index + 1),
const nextQueries = [
...initialQueries.slice(0, index + 1),
{ ...this.modifiedQueries[index + 1] },
...initialQueries.slice(index + 1),
];
// Ongoing transactions need to update their row indices
@ -239,7 +239,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
return qt;
});
return { initialTargets: nextTargets, queryTransactions: nextQueryTransactions };
return { initialQueries: nextQueries, queryTransactions: nextQueryTransactions };
});
};
@ -258,24 +258,24 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
onChangeQuery = (value: DataQuery, index: number, override?: boolean) => {
// Keep current value in local cache
this.modifiedTargets[index] = value;
this.modifiedQueries[index] = value;
if (override) {
this.setState(state => {
// Replace query row
const { initialTargets, queryTransactions } = state;
const target: DataQuery = {
const { initialQueries, queryTransactions } = state;
const query: DataQuery = {
...value,
...generateTargetKeys(index),
...generateQueryKeys(index),
};
const nextTargets = [...initialTargets];
nextTargets[index] = target;
const nextQueries = [...initialQueries];
nextQueries[index] = query;
// Discard ongoing transaction related to row query
const nextQueryTransactions = queryTransactions.filter(qt => qt.rowIndex !== index);
return {
initialTargets: nextTargets,
initialQueries: nextQueries,
queryTransactions: nextQueryTransactions,
};
}, this.onSubmit);
@ -290,10 +290,10 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
};
onClickClear = () => {
this.modifiedTargets = ensureTargets();
this.modifiedQueries = ensureQueries();
this.setState(
prevState => ({
initialTargets: [...this.modifiedTargets],
initialQueries: [...this.modifiedQueries],
queryTransactions: [],
showingStartPage: Boolean(prevState.StartPage),
}),
@ -347,10 +347,10 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
};
// Use this in help pages to set page to a single query
onClickExample = (target: DataQuery) => {
const nextTargets = [{ ...target, ...generateTargetKeys() }];
this.modifiedTargets = [...nextTargets];
this.setState({ initialTargets: nextTargets }, this.onSubmit);
onClickExample = (query: DataQuery) => {
const nextQueries = [{ ...query, ...generateQueryKeys() }];
this.modifiedQueries = [...nextQueries];
this.setState({ initialQueries: nextQueries }, this.onSubmit);
};
onClickSplit = () => {
@ -390,28 +390,28 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
const preventSubmit = action.preventSubmit;
this.setState(
state => {
const { initialTargets, queryTransactions } = state;
let nextTargets: DataQuery[];
const { initialQueries, queryTransactions } = state;
let nextQueries: DataQuery[];
let nextQueryTransactions;
if (index === undefined) {
// Modify all queries
nextTargets = initialTargets.map((target, i) => ({
...datasource.modifyQuery(this.modifiedTargets[i], action),
...generateTargetKeys(i),
nextQueries = initialQueries.map((query, i) => ({
...datasource.modifyQuery(this.modifiedQueries[i], action),
...generateQueryKeys(i),
}));
// Discard all ongoing transactions
nextQueryTransactions = [];
} else {
// Modify query only at index
nextTargets = initialTargets.map((target, i) => {
nextQueries = initialQueries.map((query, i) => {
// Synchronise all queries with local query cache to ensure consistency
// TODO still needed?
return i === index
? {
...datasource.modifyQuery(this.modifiedTargets[i], action),
...generateTargetKeys(i),
...datasource.modifyQuery(this.modifiedQueries[i], action),
...generateQueryKeys(i),
}
: target;
: query;
});
nextQueryTransactions = queryTransactions
// Consume the hint corresponding to the action
@ -424,9 +424,9 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
// Preserve previous row query transaction to keep results visible if next query is incomplete
.filter(qt => preventSubmit || qt.rowIndex !== index);
}
this.modifiedTargets = [...nextTargets];
this.modifiedQueries = [...nextQueries];
return {
initialTargets: nextTargets,
initialQueries: nextQueries,
queryTransactions: nextQueryTransactions,
};
},
@ -438,22 +438,22 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
onRemoveQueryRow = index => {
// Remove from local cache
this.modifiedTargets = [...this.modifiedTargets.slice(0, index), ...this.modifiedTargets.slice(index + 1)];
this.modifiedQueries = [...this.modifiedQueries.slice(0, index), ...this.modifiedQueries.slice(index + 1)];
this.setState(
state => {
const { initialTargets, queryTransactions } = state;
if (initialTargets.length <= 1) {
const { initialQueries, queryTransactions } = state;
if (initialQueries.length <= 1) {
return null;
}
// Remove row from react state
const nextTargets = [...initialTargets.slice(0, index), ...initialTargets.slice(index + 1)];
const nextQueries = [...initialQueries.slice(0, index), ...initialQueries.slice(index + 1)];
// Discard transactions related to row query
const nextQueryTransactions = queryTransactions.filter(qt => qt.rowIndex !== index);
return {
initialTargets: nextTargets,
initialQueries: nextQueries,
queryTransactions: nextQueryTransactions,
};
},
@ -475,36 +475,36 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
this.saveState();
};
buildQueryOptions(target: DataQuery, targetOptions: { format: string; hinting?: boolean; instant?: boolean }) {
buildQueryOptions(query: DataQuery, queryOptions: { format: string; hinting?: boolean; instant?: boolean }) {
const { datasource, range } = this.state;
const { interval, intervalMs } = getIntervals(range, datasource, this.el.offsetWidth);
const targets = [
const queries = [
{
...targetOptions,
...target,
...queryOptions,
...query,
},
];
// Clone range for query request
const queryRange: RawTimeRange = { ...range };
// Datasource is using `panelId + target.refId` for cancellation logic.
// Datasource is using `panelId + query.refId` for cancellation logic.
// Using `format` here because it relates to the view panel that the request is for.
const panelId = targetOptions.format;
const panelId = queryOptions.format;
return {
interval,
intervalMs,
panelId,
targets,
queries,
range: queryRange,
};
}
startQueryTransaction(target: DataQuery, rowIndex: number, resultType: ResultType, options: any): QueryTransaction {
const queryOptions = this.buildQueryOptions(target, options);
startQueryTransaction(query: DataQuery, rowIndex: number, resultType: ResultType, options: any): QueryTransaction {
const queryOptions = this.buildQueryOptions(query, options);
const transaction: QueryTransaction = {
target,
query,
resultType,
rowIndex,
id: generateKey(), // reusing for unique ID
@ -537,7 +537,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
transactionId: string,
result: any,
latency: number,
targets: DataQuery[],
queries: DataQuery[],
datasourceId: string
) {
const { datasource } = this.state;
@ -558,7 +558,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
// Get query hints
let hints: QueryHint[];
if (datasource.getQueryHints as QueryHintGetter) {
hints = datasource.getQueryHints(transaction.target, result);
hints = datasource.getQueryHints(transaction.query, result);
}
// Mark transactions as complete
@ -575,7 +575,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
return qt;
});
const nextHistory = updateHistory(history, datasourceId, targets);
const nextHistory = updateHistory(history, datasourceId, queries);
return {
history: nextHistory,
@ -638,15 +638,15 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
}
async runGraphQueries() {
const targets = [...this.modifiedTargets];
if (!hasNonEmptyTarget(targets)) {
const queries = [...this.modifiedQueries];
if (!hasNonEmptyQuery(queries)) {
return;
}
const { datasource } = this.state;
const datasourceId = datasource.meta.id;
// Run all queries concurrently
targets.forEach(async (target, rowIndex) => {
const transaction = this.startQueryTransaction(target, rowIndex, 'Graph', {
queries.forEach(async (query, rowIndex) => {
const transaction = this.startQueryTransaction(query, rowIndex, 'Graph', {
format: 'time_series',
instant: false,
});
@ -654,8 +654,8 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
const now = Date.now();
const res = await datasource.query(transaction.options);
const latency = Date.now() - now;
const results = makeTimeSeriesList(res.data, transaction.options);
this.completeQueryTransaction(transaction.id, results, latency, targets, datasourceId);
const results = makeTimeSeriesList(res.data);
this.completeQueryTransaction(transaction.id, results, latency, queries, datasourceId);
this.setState({ graphRange: transaction.options.range });
} catch (response) {
this.failQueryTransaction(transaction.id, response, datasourceId);
@ -664,15 +664,15 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
}
async runTableQuery() {
const targets = [...this.modifiedTargets];
if (!hasNonEmptyTarget(targets)) {
const queries = [...this.modifiedQueries];
if (!hasNonEmptyQuery(queries)) {
return;
}
const { datasource } = this.state;
const datasourceId = datasource.meta.id;
// Run all queries concurrently
targets.forEach(async (target, rowIndex) => {
const transaction = this.startQueryTransaction(target, rowIndex, 'Table', {
queries.forEach(async (query, rowIndex) => {
const transaction = this.startQueryTransaction(query, rowIndex, 'Table', {
format: 'table',
instant: true,
valueWithRefId: true,
@ -682,7 +682,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
const res = await datasource.query(transaction.options);
const latency = Date.now() - now;
const results = res.data[0];
this.completeQueryTransaction(transaction.id, results, latency, targets, datasourceId);
this.completeQueryTransaction(transaction.id, results, latency, queries, datasourceId);
} catch (response) {
this.failQueryTransaction(transaction.id, response, datasourceId);
}
@ -690,21 +690,21 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
}
async runLogsQuery() {
const targets = [...this.modifiedTargets];
if (!hasNonEmptyTarget(targets)) {
const queries = [...this.modifiedQueries];
if (!hasNonEmptyQuery(queries)) {
return;
}
const { datasource } = this.state;
const datasourceId = datasource.meta.id;
// Run all queries concurrently
targets.forEach(async (target, rowIndex) => {
const transaction = this.startQueryTransaction(target, rowIndex, 'Logs', { format: 'logs' });
queries.forEach(async (query, rowIndex) => {
const transaction = this.startQueryTransaction(query, rowIndex, 'Logs', { format: 'logs' });
try {
const now = Date.now();
const res = await datasource.query(transaction.options);
const latency = Date.now() - now;
const results = res.data;
this.completeQueryTransaction(transaction.id, results, latency, targets, datasourceId);
this.completeQueryTransaction(transaction.id, results, latency, queries, datasourceId);
} catch (response) {
this.failQueryTransaction(transaction.id, response, datasourceId);
}
@ -716,7 +716,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
return {
...this.state,
queryTransactions: [],
initialTargets: [...this.modifiedTargets],
initialQueries: [...this.modifiedQueries],
};
}
@ -736,7 +736,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
exploreDatasources,
graphRange,
history,
initialTargets,
initialQueries,
queryTransactions,
range,
showingGraph,
@ -850,7 +850,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
<QueryRows
datasource={datasource}
history={history}
initialTargets={initialTargets}
initialQueries={initialQueries}
onAddQueryRow={this.onAddQueryRow}
onChangeQuery={this.onChangeQuery}
onClickHintFix={this.onModifyQueries}

View File

@ -32,7 +32,7 @@ interface QueryRowCommonProps {
type QueryRowProps = QueryRowCommonProps &
QueryRowEventHandlers & {
index: number;
initialTarget: DataQuery;
initialQuery: DataQuery;
};
class QueryRow extends PureComponent<QueryRowProps> {
@ -76,7 +76,7 @@ class QueryRow extends PureComponent<QueryRowProps> {
};
render() {
const { datasource, history, initialTarget, transactions } = this.props;
const { datasource, history, initialQuery, transactions } = this.props;
const transactionWithError = transactions.find(t => t.error !== undefined);
const hint = getFirstHintFromTransactions(transactions);
const queryError = transactionWithError ? transactionWithError.error : null;
@ -91,7 +91,7 @@ class QueryRow extends PureComponent<QueryRowProps> {
datasource={datasource}
error={queryError}
hint={hint}
initialTarget={initialTarget}
initialQuery={initialQuery}
history={history}
onClickHintFix={this.onClickHintFix}
onPressEnter={this.onPressEnter}
@ -116,19 +116,19 @@ class QueryRow extends PureComponent<QueryRowProps> {
type QueryRowsProps = QueryRowCommonProps &
QueryRowEventHandlers & {
initialTargets: DataQuery[];
initialQueries: DataQuery[];
};
export default class QueryRows extends PureComponent<QueryRowsProps> {
render() {
const { className = '', initialTargets, transactions, ...handlers } = this.props;
const { className = '', initialQueries, transactions, ...handlers } = this.props;
return (
<div className={className}>
{initialTargets.map((target, index) => (
{initialQueries.map((query, index) => (
<QueryRow
key={target.key}
key={query.key}
index={index}
initialTarget={target}
initialQuery={query}
transactions={transactions.filter(t => t.rowIndex === index)}
{...handlers}
/>

View File

@ -54,7 +54,7 @@ interface LoggingQueryFieldProps {
error?: string | JSX.Element;
hint?: any;
history?: any[];
initialTarget?: DataQuery;
initialQuery?: DataQuery;
onClickHintFix?: (action: any) => void;
onPressEnter?: () => void;
onQueryChange?: (value: DataQuery, override?: boolean) => void;
@ -135,13 +135,13 @@ class LoggingQueryField extends React.PureComponent<LoggingQueryFieldProps, Logg
onChangeQuery = (value: string, override?: boolean) => {
// Send text change to parent
const { initialTarget, onQueryChange } = this.props;
const { initialQuery, onQueryChange } = this.props;
if (onQueryChange) {
const target = {
...initialTarget,
const query = {
...initialQuery,
expr: value,
};
onQueryChange(target, override);
onQueryChange(query, override);
}
};
@ -186,7 +186,7 @@ class LoggingQueryField extends React.PureComponent<LoggingQueryFieldProps, Logg
};
render() {
const { error, hint, initialTarget } = this.props;
const { error, hint, initialQuery } = this.props;
const { logLabelOptions, syntaxLoaded } = this.state;
const cleanText = this.languageProvider ? this.languageProvider.cleanText : undefined;
const chooserText = syntaxLoaded ? 'Log labels' : 'Loading labels...';
@ -204,7 +204,7 @@ class LoggingQueryField extends React.PureComponent<LoggingQueryFieldProps, Logg
<QueryField
additionalPlugins={this.plugins}
cleanText={cleanText}
initialQuery={initialTarget.expr}
initialQuery={initialQuery.expr}
onTypeahead={this.onTypeahead}
onWillApplySuggestion={willApplySuggestion}
onValueChanged={this.onChangeQuery}

View File

@ -112,8 +112,8 @@ export default class LoggingDatasource {
});
}
async importQueries(targets: DataQuery[], originMeta: PluginMeta): Promise<DataQuery[]> {
return this.languageProvider.importQueries(targets, originMeta.id);
async importQueries(queries: DataQuery[], originMeta: PluginMeta): Promise<DataQuery[]> {
return this.languageProvider.importQueries(queries, originMeta.id);
}
metadataRequest(url) {

View File

@ -158,20 +158,20 @@ export default class LoggingLanguageProvider extends LanguageProvider {
return { context, refresher, suggestions };
}
async importQueries(targets: DataQuery[], datasourceType: string): Promise<DataQuery[]> {
async importQueries(queries: DataQuery[], datasourceType: string): Promise<DataQuery[]> {
if (datasourceType === 'prometheus') {
return Promise.all(
targets.map(async target => {
const expr = await this.importPrometheusQuery(target.expr);
queries.map(async query => {
const expr = await this.importPrometheusQuery(query.expr);
return {
...target,
...query,
expr,
};
})
);
}
return targets.map(target => ({
...target,
return queries.map(query => ({
...query,
expr: '',
}));
}

View File

@ -88,7 +88,7 @@ interface CascaderOption {
type PromQueryFieldProps = {
datasource: any;
error?: string | JSX.Element;
initialTarget: DataQuery;
initialQuery: DataQuery;
hint?: any;
history?: any[];
metricsByPrefix?: CascaderOption[];
@ -162,15 +162,15 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
this.onChangeQuery(query, true);
};
onChangeQuery = (query: string, override?: boolean) => {
onChangeQuery = (value: string, override?: boolean) => {
// Send text change to parent
const { initialTarget, onQueryChange } = this.props;
const { initialQuery, onQueryChange } = this.props;
if (onQueryChange) {
const target: DataQuery = {
...initialTarget,
expr: query,
const query: DataQuery = {
...initialQuery,
expr: value,
};
onQueryChange(target, override);
onQueryChange(query, override);
}
};
@ -232,7 +232,7 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
};
render() {
const { error, hint, initialTarget } = this.props;
const { error, hint, initialQuery } = this.props;
const { metricsOptions, syntaxLoaded } = this.state;
const cleanText = this.languageProvider ? this.languageProvider.cleanText : undefined;
const chooserText = syntaxLoaded ? 'Metrics' : 'Loading metrics...';
@ -250,7 +250,7 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
<QueryField
additionalPlugins={this.plugins}
cleanText={cleanText}
initialQuery={initialTarget.expr}
initialQuery={initialQuery.expr}
onTypeahead={this.onTypeahead}
onWillApplySuggestion={willApplySuggestion}
onValueChanged={this.onChangeQuery}

View File

@ -421,23 +421,23 @@ export class PrometheusDatasource {
});
}
getExploreState(targets: DataQuery[]): Partial<ExploreUrlState> {
getExploreState(queries: DataQuery[]): Partial<ExploreUrlState> {
let state: Partial<ExploreUrlState> = { datasource: this.name };
if (targets && targets.length > 0) {
const expandedTargets = targets.map(target => ({
...target,
expr: this.templateSrv.replace(target.expr, {}, this.interpolateQueryExpr),
if (queries && queries.length > 0) {
const expandedQueries = queries.map(query => ({
...query,
expr: this.templateSrv.replace(query.expr, {}, this.interpolateQueryExpr),
}));
state = {
...state,
targets: expandedTargets,
queries: expandedQueries,
};
}
return state;
}
getQueryHints(target: DataQuery, result: any[]) {
return getQueryHints(target.expr, result, this);
getQueryHints(query: DataQuery, result: any[]) {
return getQueryHints(query.expr, result, this);
}
loadRules() {
@ -455,35 +455,35 @@ export class PrometheusDatasource {
});
}
modifyQuery(target: DataQuery, action: any): DataQuery {
let query = target.expr;
modifyQuery(query: DataQuery, action: any): DataQuery {
let expression = query.expr || '';
switch (action.type) {
case 'ADD_FILTER': {
query = addLabelToQuery(query, action.key, action.value);
expression = addLabelToQuery(expression, action.key, action.value);
break;
}
case 'ADD_HISTOGRAM_QUANTILE': {
query = `histogram_quantile(0.95, sum(rate(${query}[5m])) by (le))`;
expression = `histogram_quantile(0.95, sum(rate(${expression}[5m])) by (le))`;
break;
}
case 'ADD_RATE': {
query = `rate(${query}[5m])`;
expression = `rate(${expression}[5m])`;
break;
}
case 'ADD_SUM': {
query = `sum(${query.trim()}) by ($1)`;
expression = `sum(${expression.trim()}) by ($1)`;
break;
}
case 'EXPAND_RULES': {
if (action.mapping) {
query = expandRecordingRules(query, action.mapping);
expression = expandRecordingRules(expression, action.mapping);
}
break;
}
default:
break;
}
return { ...target, expr: query };
return { ...query, expr: expression };
}
getPrometheusTime(date, roundUp) {

View File

@ -79,7 +79,7 @@ interface ExploreDatasource {
export interface HistoryItem {
ts: number;
target: DataQuery;
query: DataQuery;
}
export abstract class LanguageProvider {
@ -126,7 +126,7 @@ export interface QueryHint {
}
export interface QueryHintGetter {
(target: DataQuery, results: any[], ...rest: any): QueryHint[];
(query: DataQuery, results: any[], ...rest: any): QueryHint[];
}
export interface QueryTransaction {
@ -136,10 +136,10 @@ export interface QueryTransaction {
hints?: QueryHint[];
latency: number;
options: any;
query: DataQuery;
result?: any; // Table model / Timeseries[] / Logs
resultType: ResultType;
rowIndex: number;
target: DataQuery;
}
export interface TextMatch {
@ -159,7 +159,7 @@ export interface ExploreState {
exploreDatasources: ExploreDatasource[];
graphRange: RawTimeRange;
history: HistoryItem[];
initialTargets: DataQuery[];
initialQueries: DataQuery[];
queryTransactions: QueryTransaction[];
range: RawTimeRange;
showingGraph: boolean;
@ -173,7 +173,7 @@ export interface ExploreState {
export interface ExploreUrlState {
datasource: string;
targets: any[]; // Should be a DataQuery, but we're going to strip refIds, so typing makes less sense
queries: any[]; // Should be a DataQuery, but we're going to strip refIds, so typing makes less sense
range: RawTimeRange;
}