grafana/public/app/features/query/state/PanelQueryRunner.ts

466 lines
15 KiB
TypeScript
Raw Normal View History

import { cloneDeep, merge } from 'lodash';
import { Observable, of, ReplaySubject, Unsubscribable } from 'rxjs';
import { map, mergeMap, catchError } from 'rxjs/operators';
import {
applyFieldOverrides,
compareArrayValues,
compareDataFrameStructures,
CoreApp,
DataConfigSource,
DataFrame,
DataQuery,
DataQueryRequest,
DataSourceApi,
DataSourceJsonData,
DataSourceRef,
DataTransformContext,
DataTransformerConfig,
getDefaultTimeRange,
LoadingState,
PanelData,
rangeUtil,
ScopedVars,
TimeRange,
TimeZone,
toDataFrame,
transformDataFrame,
preProcessPanelData,
ApplyFieldOverrideOptions,
StreamingDataFrame,
DataTopic,
} from '@grafana/data';
import { toDataQueryError } from '@grafana/runtime';
import { ExpressionDatasourceRef } from '@grafana/runtime/src/utils/DataSourceWithBackend';
import { isStreamingDataFrame } from 'app/features/live/data/utils';
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
import { getTemplateSrv } from 'app/features/templating/template_srv';
import { isSharedDashboardQuery, runSharedRequest } from '../../../plugins/datasource/dashboard';
import { PanelModel } from '../../dashboard/state';
Annotations: Adds DashboardQueryRunner (#32834) * WIP: initial commit * Fix: Fixed $timeout call when testing snapshots * Chore: reverts changes to metrics_panel_ctrl.ts * Chore: reverts changes to annotations_srv * Refactor: adds DashboardQueryRunner.run to initdashboard * Refactor: adds run to dashboard model start refresh * Refactor: move to own folder and split up into smaller files * Tests: adds tests for LegacyAnnotationQueryRunner * Tests: adds tests for AnnotationsQueryRunner * Tests: adds tests for SnapshotWorker * Refactor: renames from canRun|run to canWork|work * Tests: adds tests for AlertStatesWorker * Tests: adds tests for AnnotationsWorker * Refactor: renames operators * Refactor: renames operators * Tests: adds tests for DashboardQueryRunner * Refactor: adds mergePanelAndDashboardData function * Tests: fixes broken tests * Chore: Fixes errors after merge with master * Chore: Removes usage of AnnotationSrv from event_editor and initDashboard * WIP: getting annotations and alerts working in graph (snapshot not working) * Refactor: fixes snapshot data for React panels * Refactor: Fixes so snapshots work for Graph * Refactor: moves alert types to grafana-data * Refactor: changes to some for readability * Tests: skipping tests for now, needs rewrite * Refactor: refactors out common static functions to utils * Refactor: fixes resolving annotations from dataframes * Refactor: removes getRunners/Workers functions * Docs: fixes docs errors * Docs: trying to fix doc error * Refactor: changes after PR comments * Refactor: hides everything behind a factory instead * Refactor: adds cancellation between runs and explicitly
2021-04-26 12:13:03 +08:00
import { getDashboardQueryRunner } from './DashboardQueryRunner/DashboardQueryRunner';
import { mergePanelAndDashData } from './mergePanelAndDashData';
import { runRequest } from './runRequest';
export interface QueryRunnerOptions<
TQuery extends DataQuery = DataQuery,
TOptions extends DataSourceJsonData = DataSourceJsonData,
> {
datasource: DataSourceRef | DataSourceApi<TQuery, TOptions> | null;
queries: TQuery[];
panelId?: number;
panelPluginId?: string;
dashboardUID?: string;
timezone: TimeZone;
timeRange: TimeRange;
timeInfo?: string; // String description of time range for display
maxDataPoints: number;
minInterval: string | undefined | null;
scopedVars?: ScopedVars;
cacheTimeout?: string | null;
queryCachingTTL?: number | null;
transformations?: DataTransformerConfig[];
app?: CoreApp;
}
let counter = 100;
export function getNextRequestId() {
return 'Q' + counter++;
}
export interface GetDataOptions {
withTransforms: boolean;
withFieldConfig: boolean;
}
export class PanelQueryRunner {
private subject: ReplaySubject<PanelData>;
QueryProcessing: Observable query interface and RxJS for query & stream processing (#18899) * I needed to learn some rxjs and understand this more, so just playing around * Updated * Removed all the complete calls * Refactoring * StreamHandler -> observable start * progress * simple singal works * Handle update time range * added error handling * wrap old function * minor changes * handle data format in the subscribe function * Use replay subject to return last value to subscribers * Set loading state after no response in 50ms * added missing file * updated comment * Added cancelation of network requests * runRequest: Added unit test scenario framework * Progress on tests * minor refactor of unit tests * updated test * removed some old code * Shared queries work again, and also became so much simplier * unified query and observe methods * implict any fix * Fixed closed subject issue * removed comment * Use last returned data for loading state * WIP: Explore to runRequest makover step1 * Minor progress * Minor progress on explore and runRequest * minor progress * Things are starting to work in explore * Updated prometheus to use new observable query response, greatly simplified code * Revert refId change * Found better solution for key/refId/requestId problem * use observable with loki * tests compile * fix loki query prep * Explore: correct first response handling * Refactorings * Refactoring * Explore: Fixes LoadingState and GraphResults between runs (#18986) * Refactor: Adds state to DataQueryResponse * Fix: Fixes so we do not empty results before new data arrives Fixes: #17409 * Transformations work * observable test data * remove single() from loki promise * Fixed comment * Explore: Fixes failing Loki and Prometheus unit tests (#18995) * Tests: Makes datasource tests work again * Fix: Fixes loki datasource so highligthing works * Chore: Runs Prettier * Fixed query runner tests * Delay loading state indication to 200ms * Fixed test * fixed unit tests * Clear cached calcs * Fixed bug getProcesedDataFrames * Fix the correct test is a better idea * Fix: Fixes so queries in Explore are only run if Graph/Table is shown (#19000) * Fix: Fixes so queries in Explore are only run if Graph/Table is shown Fixes: #18618 * Refactor: Removes unnecessary condition * PanelData: provide legacy data only when needed (#19018) * no legacy * invert logic... now compiles * merge getQueryResponseData and getDataRaw * update comment about query editor * use single getData() function * only send legacy when it is used in explore * pre process rather than post process * pre process rather than post process * Minor refactoring * Add missing tags to test datasource response * MixedDatasource: Adds query observable pattern to MixedDatasource (#19037) * start mixed datasource * Refactor: Refactors into observable parttern * Tests: Fixes tests * Tests: Removes console.log * Refactor: Adds unique requestId
2019-09-12 23:28:46 +08:00
private subscription?: Unsubscribable;
private lastResult?: PanelData;
private dataConfigSource: DataConfigSource;
private lastRequest?: DataQueryRequest;
private templateSrv = getTemplateSrv();
constructor(dataConfigSource: DataConfigSource) {
QueryProcessing: Observable query interface and RxJS for query & stream processing (#18899) * I needed to learn some rxjs and understand this more, so just playing around * Updated * Removed all the complete calls * Refactoring * StreamHandler -> observable start * progress * simple singal works * Handle update time range * added error handling * wrap old function * minor changes * handle data format in the subscribe function * Use replay subject to return last value to subscribers * Set loading state after no response in 50ms * added missing file * updated comment * Added cancelation of network requests * runRequest: Added unit test scenario framework * Progress on tests * minor refactor of unit tests * updated test * removed some old code * Shared queries work again, and also became so much simplier * unified query and observe methods * implict any fix * Fixed closed subject issue * removed comment * Use last returned data for loading state * WIP: Explore to runRequest makover step1 * Minor progress * Minor progress on explore and runRequest * minor progress * Things are starting to work in explore * Updated prometheus to use new observable query response, greatly simplified code * Revert refId change * Found better solution for key/refId/requestId problem * use observable with loki * tests compile * fix loki query prep * Explore: correct first response handling * Refactorings * Refactoring * Explore: Fixes LoadingState and GraphResults between runs (#18986) * Refactor: Adds state to DataQueryResponse * Fix: Fixes so we do not empty results before new data arrives Fixes: #17409 * Transformations work * observable test data * remove single() from loki promise * Fixed comment * Explore: Fixes failing Loki and Prometheus unit tests (#18995) * Tests: Makes datasource tests work again * Fix: Fixes loki datasource so highligthing works * Chore: Runs Prettier * Fixed query runner tests * Delay loading state indication to 200ms * Fixed test * fixed unit tests * Clear cached calcs * Fixed bug getProcesedDataFrames * Fix the correct test is a better idea * Fix: Fixes so queries in Explore are only run if Graph/Table is shown (#19000) * Fix: Fixes so queries in Explore are only run if Graph/Table is shown Fixes: #18618 * Refactor: Removes unnecessary condition * PanelData: provide legacy data only when needed (#19018) * no legacy * invert logic... now compiles * merge getQueryResponseData and getDataRaw * update comment about query editor * use single getData() function * only send legacy when it is used in explore * pre process rather than post process * pre process rather than post process * Minor refactoring * Add missing tags to test datasource response * MixedDatasource: Adds query observable pattern to MixedDatasource (#19037) * start mixed datasource * Refactor: Refactors into observable parttern * Tests: Fixes tests * Tests: Removes console.log * Refactor: Adds unique requestId
2019-09-12 23:28:46 +08:00
this.subject = new ReplaySubject(1);
this.dataConfigSource = dataConfigSource;
}
/**
QueryProcessing: Observable query interface and RxJS for query & stream processing (#18899) * I needed to learn some rxjs and understand this more, so just playing around * Updated * Removed all the complete calls * Refactoring * StreamHandler -> observable start * progress * simple singal works * Handle update time range * added error handling * wrap old function * minor changes * handle data format in the subscribe function * Use replay subject to return last value to subscribers * Set loading state after no response in 50ms * added missing file * updated comment * Added cancelation of network requests * runRequest: Added unit test scenario framework * Progress on tests * minor refactor of unit tests * updated test * removed some old code * Shared queries work again, and also became so much simplier * unified query and observe methods * implict any fix * Fixed closed subject issue * removed comment * Use last returned data for loading state * WIP: Explore to runRequest makover step1 * Minor progress * Minor progress on explore and runRequest * minor progress * Things are starting to work in explore * Updated prometheus to use new observable query response, greatly simplified code * Revert refId change * Found better solution for key/refId/requestId problem * use observable with loki * tests compile * fix loki query prep * Explore: correct first response handling * Refactorings * Refactoring * Explore: Fixes LoadingState and GraphResults between runs (#18986) * Refactor: Adds state to DataQueryResponse * Fix: Fixes so we do not empty results before new data arrives Fixes: #17409 * Transformations work * observable test data * remove single() from loki promise * Fixed comment * Explore: Fixes failing Loki and Prometheus unit tests (#18995) * Tests: Makes datasource tests work again * Fix: Fixes loki datasource so highligthing works * Chore: Runs Prettier * Fixed query runner tests * Delay loading state indication to 200ms * Fixed test * fixed unit tests * Clear cached calcs * Fixed bug getProcesedDataFrames * Fix the correct test is a better idea * Fix: Fixes so queries in Explore are only run if Graph/Table is shown (#19000) * Fix: Fixes so queries in Explore are only run if Graph/Table is shown Fixes: #18618 * Refactor: Removes unnecessary condition * PanelData: provide legacy data only when needed (#19018) * no legacy * invert logic... now compiles * merge getQueryResponseData and getDataRaw * update comment about query editor * use single getData() function * only send legacy when it is used in explore * pre process rather than post process * pre process rather than post process * Minor refactoring * Add missing tags to test datasource response * MixedDatasource: Adds query observable pattern to MixedDatasource (#19037) * start mixed datasource * Refactor: Refactors into observable parttern * Tests: Fixes tests * Tests: Removes console.log * Refactor: Adds unique requestId
2019-09-12 23:28:46 +08:00
* Returns an observable that subscribes to the shared multi-cast subject (that reply last result).
*/
getData(options: GetDataOptions): Observable<PanelData> {
const { withFieldConfig, withTransforms } = options;
let structureRev = 1;
let lastFieldConfig: ApplyFieldOverrideOptions | undefined = undefined;
let lastProcessedFrames: DataFrame[] = [];
let lastRawFrames: DataFrame[] = [];
let lastTransformations: DataTransformerConfig[] | undefined;
let isFirstPacket = true;
let lastConfigRev = -1;
if (this.dataConfigSource.snapshotData) {
const snapshotPanelData: PanelData = {
state: LoadingState.Done,
series: this.dataConfigSource.snapshotData.map((v) => toDataFrame(v)),
timeRange: getDefaultTimeRange(), // Don't need real time range for snapshots
structureRev,
};
return of(snapshotPanelData);
}
return this.subject.pipe(
mergeMap((data: PanelData) => {
let fieldConfig = this.dataConfigSource.getFieldOverrideOptions();
let transformations = this.dataConfigSource.getTransformations();
if (
data.series === lastRawFrames &&
lastFieldConfig?.fieldConfig === fieldConfig?.fieldConfig &&
lastTransformations === transformations
) {
return of({ ...data, structureRev, series: lastProcessedFrames });
}
lastFieldConfig = fieldConfig;
lastTransformations = transformations;
lastRawFrames = data.series;
let dataWithTransforms = of(data);
if (withTransforms) {
dataWithTransforms = this.applyTransformations(data);
}
return dataWithTransforms.pipe(
map((data: PanelData) => {
let processedData = data;
let streamingPacketWithSameSchema = false;
if (withFieldConfig && data.series?.length) {
if (lastConfigRev === this.dataConfigSource.configRev) {
let streamingDataFrame: StreamingDataFrame | undefined;
for (const frame of data.series) {
if (isStreamingDataFrame(frame)) {
streamingDataFrame = frame;
break;
}
}
if (
streamingDataFrame &&
!streamingDataFrame.packetInfo.schemaChanged &&
// TODO: remove the condition below after fixing
// https://github.com/grafana/grafana/pull/41492#issuecomment-970281430
lastProcessedFrames[0].fields.length === streamingDataFrame.fields.length
) {
processedData = {
...processedData,
series: lastProcessedFrames.map((frame, frameIndex) => ({
...frame,
length: data.series[frameIndex].length,
fields: frame.fields.map((field, fieldIndex) => ({
...field,
values: data.series[frameIndex].fields[fieldIndex].values,
state: {
...field.state,
calcs: undefined,
range: undefined,
},
})),
})),
};
streamingPacketWithSameSchema = true;
}
}
if (fieldConfig != null && (isFirstPacket || !streamingPacketWithSameSchema)) {
lastConfigRev = this.dataConfigSource.configRev!;
processedData = {
...processedData,
series: applyFieldOverrides({
timeZone: data.request?.timezone ?? 'browser',
data: processedData.series,
...fieldConfig!,
}),
};
if (processedData.annotations) {
processedData.annotations = applyFieldOverrides({
data: processedData.annotations,
...fieldConfig!,
fieldConfig: {
defaults: {},
overrides: [],
},
});
}
isFirstPacket = false;
}
}
if (
!streamingPacketWithSameSchema &&
!compareArrayValues(lastProcessedFrames, processedData.series, compareDataFrameStructures)
) {
structureRev++;
}
lastProcessedFrames = processedData.series;
return { ...processedData, structureRev };
})
);
})
);
}
private applyTransformations(data: PanelData): Observable<PanelData> {
const transformations = this.dataConfigSource.getTransformations();
const allTransformationsDisabled = transformations && transformations.every((t) => t.disabled);
if (allTransformationsDisabled || !transformations || transformations.length === 0) {
return of(data);
}
const ctx: DataTransformContext = {
interpolate: (v: string) => this.templateSrv.replace(v, data?.request?.scopedVars),
};
let seriesTransformations = transformations.filter((t) => t.topic == null || t.topic === DataTopic.Series);
let annotationsTransformations = transformations.filter((t) => t.topic === DataTopic.Annotations);
let seriesStream = transformDataFrame(seriesTransformations, data.series, ctx);
let annotationsStream = transformDataFrame(annotationsTransformations, data.annotations ?? [], ctx);
return merge(seriesStream, annotationsStream).pipe(
map((frames) => {
let isAnnotations = frames.some((f) => f.meta?.dataTopic === DataTopic.Annotations);
let transformed = isAnnotations ? { annotations: frames } : { series: frames };
return { ...data, ...transformed };
}),
catchError((err) => {
console.warn('Error running transformation:', err);
return of({
...data,
state: LoadingState.Error,
errors: [toDataQueryError(err)],
});
})
);
}
QueryProcessing: Observable query interface and RxJS for query & stream processing (#18899) * I needed to learn some rxjs and understand this more, so just playing around * Updated * Removed all the complete calls * Refactoring * StreamHandler -> observable start * progress * simple singal works * Handle update time range * added error handling * wrap old function * minor changes * handle data format in the subscribe function * Use replay subject to return last value to subscribers * Set loading state after no response in 50ms * added missing file * updated comment * Added cancelation of network requests * runRequest: Added unit test scenario framework * Progress on tests * minor refactor of unit tests * updated test * removed some old code * Shared queries work again, and also became so much simplier * unified query and observe methods * implict any fix * Fixed closed subject issue * removed comment * Use last returned data for loading state * WIP: Explore to runRequest makover step1 * Minor progress * Minor progress on explore and runRequest * minor progress * Things are starting to work in explore * Updated prometheus to use new observable query response, greatly simplified code * Revert refId change * Found better solution for key/refId/requestId problem * use observable with loki * tests compile * fix loki query prep * Explore: correct first response handling * Refactorings * Refactoring * Explore: Fixes LoadingState and GraphResults between runs (#18986) * Refactor: Adds state to DataQueryResponse * Fix: Fixes so we do not empty results before new data arrives Fixes: #17409 * Transformations work * observable test data * remove single() from loki promise * Fixed comment * Explore: Fixes failing Loki and Prometheus unit tests (#18995) * Tests: Makes datasource tests work again * Fix: Fixes loki datasource so highligthing works * Chore: Runs Prettier * Fixed query runner tests * Delay loading state indication to 200ms * Fixed test * fixed unit tests * Clear cached calcs * Fixed bug getProcesedDataFrames * Fix the correct test is a better idea * Fix: Fixes so queries in Explore are only run if Graph/Table is shown (#19000) * Fix: Fixes so queries in Explore are only run if Graph/Table is shown Fixes: #18618 * Refactor: Removes unnecessary condition * PanelData: provide legacy data only when needed (#19018) * no legacy * invert logic... now compiles * merge getQueryResponseData and getDataRaw * update comment about query editor * use single getData() function * only send legacy when it is used in explore * pre process rather than post process * pre process rather than post process * Minor refactoring * Add missing tags to test datasource response * MixedDatasource: Adds query observable pattern to MixedDatasource (#19037) * start mixed datasource * Refactor: Refactors into observable parttern * Tests: Fixes tests * Tests: Removes console.log * Refactor: Adds unique requestId
2019-09-12 23:28:46 +08:00
async run(options: QueryRunnerOptions) {
const {
queries,
timezone,
datasource,
panelId,
panelPluginId,
dashboardUID,
timeRange,
timeInfo,
cacheTimeout,
queryCachingTTL,
maxDataPoints,
scopedVars,
minInterval,
app,
} = options;
if (isSharedDashboardQuery(datasource)) {
this.pipeToSubject(runSharedRequest(options, queries[0]), panelId, true);
QueryProcessing: Observable query interface and RxJS for query & stream processing (#18899) * I needed to learn some rxjs and understand this more, so just playing around * Updated * Removed all the complete calls * Refactoring * StreamHandler -> observable start * progress * simple singal works * Handle update time range * added error handling * wrap old function * minor changes * handle data format in the subscribe function * Use replay subject to return last value to subscribers * Set loading state after no response in 50ms * added missing file * updated comment * Added cancelation of network requests * runRequest: Added unit test scenario framework * Progress on tests * minor refactor of unit tests * updated test * removed some old code * Shared queries work again, and also became so much simplier * unified query and observe methods * implict any fix * Fixed closed subject issue * removed comment * Use last returned data for loading state * WIP: Explore to runRequest makover step1 * Minor progress * Minor progress on explore and runRequest * minor progress * Things are starting to work in explore * Updated prometheus to use new observable query response, greatly simplified code * Revert refId change * Found better solution for key/refId/requestId problem * use observable with loki * tests compile * fix loki query prep * Explore: correct first response handling * Refactorings * Refactoring * Explore: Fixes LoadingState and GraphResults between runs (#18986) * Refactor: Adds state to DataQueryResponse * Fix: Fixes so we do not empty results before new data arrives Fixes: #17409 * Transformations work * observable test data * remove single() from loki promise * Fixed comment * Explore: Fixes failing Loki and Prometheus unit tests (#18995) * Tests: Makes datasource tests work again * Fix: Fixes loki datasource so highligthing works * Chore: Runs Prettier * Fixed query runner tests * Delay loading state indication to 200ms * Fixed test * fixed unit tests * Clear cached calcs * Fixed bug getProcesedDataFrames * Fix the correct test is a better idea * Fix: Fixes so queries in Explore are only run if Graph/Table is shown (#19000) * Fix: Fixes so queries in Explore are only run if Graph/Table is shown Fixes: #18618 * Refactor: Removes unnecessary condition * PanelData: provide legacy data only when needed (#19018) * no legacy * invert logic... now compiles * merge getQueryResponseData and getDataRaw * update comment about query editor * use single getData() function * only send legacy when it is used in explore * pre process rather than post process * pre process rather than post process * Minor refactoring * Add missing tags to test datasource response * MixedDatasource: Adds query observable pattern to MixedDatasource (#19037) * start mixed datasource * Refactor: Refactors into observable parttern * Tests: Fixes tests * Tests: Removes console.log * Refactor: Adds unique requestId
2019-09-12 23:28:46 +08:00
return;
}
const request: DataQueryRequest = {
app: app ?? CoreApp.Dashboard,
requestId: getNextRequestId(),
timezone,
panelId,
panelPluginId,
dashboardUID,
range: timeRange,
timeInfo,
interval: '',
intervalMs: 0,
targets: cloneDeep(queries),
maxDataPoints: maxDataPoints,
scopedVars: scopedVars || {},
cacheTimeout,
queryCachingTTL,
startTime: Date.now(),
rangeRaw: timeRange.raw,
};
try {
const ds = await getDataSource(datasource, request.scopedVars);
const isMixedDS = ds.meta?.mixed;
Public Dashboards: Pubdash panels get data from pubdash api (#50556) * Public dashboard query API * Create new API on service for building metric request * Flesh out testing, implement BuildPublicDashboardMetricRequest * Test for errors and missing panels * WIP: Test for multiple datasources * Refactor tests, add supporting code for multiple datasources * Gets the panel data from the pubdash query api * Adds tests to make sure we get the correct api url from retrieving panel data * Public dashboard query API * Create new API on service for building metric request * Flesh out testing, implement BuildPublicDashboardMetricRequest * Test for errors and missing panels * WIP: Test for multiple datasources * Refactor tests, add supporting code for multiple datasources * Handle queries from multiple datasources * Replace dashboard time range with pubdash time range settings * Fix comments from review, build failure * removes changes to DataSourceWithBackend.ts regarding getting the pubdash panel query url. Going to do this in a new class, PublicDashboardDataSource.ts * Include pubdash Uid in dashboard meta * Creates new PublicDashboardDataSource.ts and adds test * Passes pubdash uid down to PanelQueryRunner.ts to a PublicDashboardDatasource can be chosen when were looking at a public dashboard * removes comment * checks for error when unmarshalling json * Only replace dashboard time settings with pubdash time settings when pubdash time settings exist * formatting and added comment Co-authored-by: Jesse Weaver <jesse.weaver@grafana.com> Co-authored-by: Jeff Levin <jeff@levinology.com>
2022-06-14 08:03:43 +08:00
// Attach the data source to each query
request.targets = request.targets.map((query) => {
const isExpressionQuery = query.datasource?.type === ExpressionDatasourceRef.type;
// When using a data source variable, the panel might have the incorrect datasource
// stored, so when running the query make sure it is done with the correct one
if (!query.datasource || (query.datasource.uid !== ds.uid && !isMixedDS && !isExpressionQuery)) {
query.datasource = ds.getRef();
}
return query;
});
const lowerIntervalLimit = minInterval ? this.templateSrv.replace(minInterval, request.scopedVars) : ds.interval;
const norm = rangeUtil.calculateInterval(timeRange, maxDataPoints, lowerIntervalLimit);
// make shallow copy of scoped vars,
// and add built in variables interval and interval_ms
request.scopedVars = Object.assign({}, request.scopedVars, {
__interval: { text: norm.interval, value: norm.interval },
__interval_ms: { text: norm.intervalMs.toString(), value: norm.intervalMs },
});
request.interval = norm.interval;
request.intervalMs = norm.intervalMs;
request.filters = this.templateSrv.getAdhocFilters(ds.name, true);
this.lastRequest = request;
Annotations: Adds DashboardQueryRunner (#32834) * WIP: initial commit * Fix: Fixed $timeout call when testing snapshots * Chore: reverts changes to metrics_panel_ctrl.ts * Chore: reverts changes to annotations_srv * Refactor: adds DashboardQueryRunner.run to initdashboard * Refactor: adds run to dashboard model start refresh * Refactor: move to own folder and split up into smaller files * Tests: adds tests for LegacyAnnotationQueryRunner * Tests: adds tests for AnnotationsQueryRunner * Tests: adds tests for SnapshotWorker * Refactor: renames from canRun|run to canWork|work * Tests: adds tests for AlertStatesWorker * Tests: adds tests for AnnotationsWorker * Refactor: renames operators * Refactor: renames operators * Tests: adds tests for DashboardQueryRunner * Refactor: adds mergePanelAndDashboardData function * Tests: fixes broken tests * Chore: Fixes errors after merge with master * Chore: Removes usage of AnnotationSrv from event_editor and initDashboard * WIP: getting annotations and alerts working in graph (snapshot not working) * Refactor: fixes snapshot data for React panels * Refactor: Fixes so snapshots work for Graph * Refactor: moves alert types to grafana-data * Refactor: changes to some for readability * Tests: skipping tests for now, needs rewrite * Refactor: refactors out common static functions to utils * Refactor: fixes resolving annotations from dataframes * Refactor: removes getRunners/Workers functions * Docs: fixes docs errors * Docs: trying to fix doc error * Refactor: changes after PR comments * Refactor: hides everything behind a factory instead * Refactor: adds cancellation between runs and explicitly
2021-04-26 12:13:03 +08:00
this.pipeToSubject(runRequest(ds, request), panelId);
} catch (err) {
this.pipeToSubject(
of({
state: LoadingState.Error,
error: toDataQueryError(err),
series: [],
timeRange: request.range,
}),
panelId
);
QueryProcessing: Observable query interface and RxJS for query & stream processing (#18899) * I needed to learn some rxjs and understand this more, so just playing around * Updated * Removed all the complete calls * Refactoring * StreamHandler -> observable start * progress * simple singal works * Handle update time range * added error handling * wrap old function * minor changes * handle data format in the subscribe function * Use replay subject to return last value to subscribers * Set loading state after no response in 50ms * added missing file * updated comment * Added cancelation of network requests * runRequest: Added unit test scenario framework * Progress on tests * minor refactor of unit tests * updated test * removed some old code * Shared queries work again, and also became so much simplier * unified query and observe methods * implict any fix * Fixed closed subject issue * removed comment * Use last returned data for loading state * WIP: Explore to runRequest makover step1 * Minor progress * Minor progress on explore and runRequest * minor progress * Things are starting to work in explore * Updated prometheus to use new observable query response, greatly simplified code * Revert refId change * Found better solution for key/refId/requestId problem * use observable with loki * tests compile * fix loki query prep * Explore: correct first response handling * Refactorings * Refactoring * Explore: Fixes LoadingState and GraphResults between runs (#18986) * Refactor: Adds state to DataQueryResponse * Fix: Fixes so we do not empty results before new data arrives Fixes: #17409 * Transformations work * observable test data * remove single() from loki promise * Fixed comment * Explore: Fixes failing Loki and Prometheus unit tests (#18995) * Tests: Makes datasource tests work again * Fix: Fixes loki datasource so highligthing works * Chore: Runs Prettier * Fixed query runner tests * Delay loading state indication to 200ms * Fixed test * fixed unit tests * Clear cached calcs * Fixed bug getProcesedDataFrames * Fix the correct test is a better idea * Fix: Fixes so queries in Explore are only run if Graph/Table is shown (#19000) * Fix: Fixes so queries in Explore are only run if Graph/Table is shown Fixes: #18618 * Refactor: Removes unnecessary condition * PanelData: provide legacy data only when needed (#19018) * no legacy * invert logic... now compiles * merge getQueryResponseData and getDataRaw * update comment about query editor * use single getData() function * only send legacy when it is used in explore * pre process rather than post process * pre process rather than post process * Minor refactoring * Add missing tags to test datasource response * MixedDatasource: Adds query observable pattern to MixedDatasource (#19037) * start mixed datasource * Refactor: Refactors into observable parttern * Tests: Fixes tests * Tests: Removes console.log * Refactor: Adds unique requestId
2019-09-12 23:28:46 +08:00
}
}
private pipeToSubject(observable: Observable<PanelData>, panelId?: number, skipPreProcess = false) {
QueryProcessing: Observable query interface and RxJS for query & stream processing (#18899) * I needed to learn some rxjs and understand this more, so just playing around * Updated * Removed all the complete calls * Refactoring * StreamHandler -> observable start * progress * simple singal works * Handle update time range * added error handling * wrap old function * minor changes * handle data format in the subscribe function * Use replay subject to return last value to subscribers * Set loading state after no response in 50ms * added missing file * updated comment * Added cancelation of network requests * runRequest: Added unit test scenario framework * Progress on tests * minor refactor of unit tests * updated test * removed some old code * Shared queries work again, and also became so much simplier * unified query and observe methods * implict any fix * Fixed closed subject issue * removed comment * Use last returned data for loading state * WIP: Explore to runRequest makover step1 * Minor progress * Minor progress on explore and runRequest * minor progress * Things are starting to work in explore * Updated prometheus to use new observable query response, greatly simplified code * Revert refId change * Found better solution for key/refId/requestId problem * use observable with loki * tests compile * fix loki query prep * Explore: correct first response handling * Refactorings * Refactoring * Explore: Fixes LoadingState and GraphResults between runs (#18986) * Refactor: Adds state to DataQueryResponse * Fix: Fixes so we do not empty results before new data arrives Fixes: #17409 * Transformations work * observable test data * remove single() from loki promise * Fixed comment * Explore: Fixes failing Loki and Prometheus unit tests (#18995) * Tests: Makes datasource tests work again * Fix: Fixes loki datasource so highligthing works * Chore: Runs Prettier * Fixed query runner tests * Delay loading state indication to 200ms * Fixed test * fixed unit tests * Clear cached calcs * Fixed bug getProcesedDataFrames * Fix the correct test is a better idea * Fix: Fixes so queries in Explore are only run if Graph/Table is shown (#19000) * Fix: Fixes so queries in Explore are only run if Graph/Table is shown Fixes: #18618 * Refactor: Removes unnecessary condition * PanelData: provide legacy data only when needed (#19018) * no legacy * invert logic... now compiles * merge getQueryResponseData and getDataRaw * update comment about query editor * use single getData() function * only send legacy when it is used in explore * pre process rather than post process * pre process rather than post process * Minor refactoring * Add missing tags to test datasource response * MixedDatasource: Adds query observable pattern to MixedDatasource (#19037) * start mixed datasource * Refactor: Refactors into observable parttern * Tests: Fixes tests * Tests: Removes console.log * Refactor: Adds unique requestId
2019-09-12 23:28:46 +08:00
if (this.subscription) {
this.subscription.unsubscribe();
}
QueryProcessing: Observable query interface and RxJS for query & stream processing (#18899) * I needed to learn some rxjs and understand this more, so just playing around * Updated * Removed all the complete calls * Refactoring * StreamHandler -> observable start * progress * simple singal works * Handle update time range * added error handling * wrap old function * minor changes * handle data format in the subscribe function * Use replay subject to return last value to subscribers * Set loading state after no response in 50ms * added missing file * updated comment * Added cancelation of network requests * runRequest: Added unit test scenario framework * Progress on tests * minor refactor of unit tests * updated test * removed some old code * Shared queries work again, and also became so much simplier * unified query and observe methods * implict any fix * Fixed closed subject issue * removed comment * Use last returned data for loading state * WIP: Explore to runRequest makover step1 * Minor progress * Minor progress on explore and runRequest * minor progress * Things are starting to work in explore * Updated prometheus to use new observable query response, greatly simplified code * Revert refId change * Found better solution for key/refId/requestId problem * use observable with loki * tests compile * fix loki query prep * Explore: correct first response handling * Refactorings * Refactoring * Explore: Fixes LoadingState and GraphResults between runs (#18986) * Refactor: Adds state to DataQueryResponse * Fix: Fixes so we do not empty results before new data arrives Fixes: #17409 * Transformations work * observable test data * remove single() from loki promise * Fixed comment * Explore: Fixes failing Loki and Prometheus unit tests (#18995) * Tests: Makes datasource tests work again * Fix: Fixes loki datasource so highligthing works * Chore: Runs Prettier * Fixed query runner tests * Delay loading state indication to 200ms * Fixed test * fixed unit tests * Clear cached calcs * Fixed bug getProcesedDataFrames * Fix the correct test is a better idea * Fix: Fixes so queries in Explore are only run if Graph/Table is shown (#19000) * Fix: Fixes so queries in Explore are only run if Graph/Table is shown Fixes: #18618 * Refactor: Removes unnecessary condition * PanelData: provide legacy data only when needed (#19018) * no legacy * invert logic... now compiles * merge getQueryResponseData and getDataRaw * update comment about query editor * use single getData() function * only send legacy when it is used in explore * pre process rather than post process * pre process rather than post process * Minor refactoring * Add missing tags to test datasource response * MixedDatasource: Adds query observable pattern to MixedDatasource (#19037) * start mixed datasource * Refactor: Refactors into observable parttern * Tests: Fixes tests * Tests: Removes console.log * Refactor: Adds unique requestId
2019-09-12 23:28:46 +08:00
let panelData = observable;
const dataSupport = this.dataConfigSource.getDataSupport();
if (dataSupport.alertStates || dataSupport.annotations) {
const panel = this.dataConfigSource as unknown as PanelModel;
panelData = mergePanelAndDashData(observable, getDashboardQueryRunner().getResult(panel.id));
}
this.subscription = panelData.subscribe({
next: (data) => {
const last = this.lastResult;
const next = skipPreProcess ? data : preProcessPanelData(data, last);
if (last != null && next.state !== LoadingState.Streaming) {
let sameSeries = compareArrayValues(last.series ?? [], next.series ?? [], (a, b) => a === b);
let sameAnnotations = compareArrayValues(last.annotations ?? [], next.annotations ?? [], (a, b) => a === b);
let sameState = last.state === next.state;
if (sameSeries) {
next.series = last.series;
}
if (sameAnnotations) {
next.annotations = last.annotations;
}
if (sameSeries && sameAnnotations && sameState) {
return;
}
}
this.lastResult = next;
// Store preprocessed query results for applying overrides later on in the pipeline
this.subject.next(next);
QueryProcessing: Observable query interface and RxJS for query & stream processing (#18899) * I needed to learn some rxjs and understand this more, so just playing around * Updated * Removed all the complete calls * Refactoring * StreamHandler -> observable start * progress * simple singal works * Handle update time range * added error handling * wrap old function * minor changes * handle data format in the subscribe function * Use replay subject to return last value to subscribers * Set loading state after no response in 50ms * added missing file * updated comment * Added cancelation of network requests * runRequest: Added unit test scenario framework * Progress on tests * minor refactor of unit tests * updated test * removed some old code * Shared queries work again, and also became so much simplier * unified query and observe methods * implict any fix * Fixed closed subject issue * removed comment * Use last returned data for loading state * WIP: Explore to runRequest makover step1 * Minor progress * Minor progress on explore and runRequest * minor progress * Things are starting to work in explore * Updated prometheus to use new observable query response, greatly simplified code * Revert refId change * Found better solution for key/refId/requestId problem * use observable with loki * tests compile * fix loki query prep * Explore: correct first response handling * Refactorings * Refactoring * Explore: Fixes LoadingState and GraphResults between runs (#18986) * Refactor: Adds state to DataQueryResponse * Fix: Fixes so we do not empty results before new data arrives Fixes: #17409 * Transformations work * observable test data * remove single() from loki promise * Fixed comment * Explore: Fixes failing Loki and Prometheus unit tests (#18995) * Tests: Makes datasource tests work again * Fix: Fixes loki datasource so highligthing works * Chore: Runs Prettier * Fixed query runner tests * Delay loading state indication to 200ms * Fixed test * fixed unit tests * Clear cached calcs * Fixed bug getProcesedDataFrames * Fix the correct test is a better idea * Fix: Fixes so queries in Explore are only run if Graph/Table is shown (#19000) * Fix: Fixes so queries in Explore are only run if Graph/Table is shown Fixes: #18618 * Refactor: Removes unnecessary condition * PanelData: provide legacy data only when needed (#19018) * no legacy * invert logic... now compiles * merge getQueryResponseData and getDataRaw * update comment about query editor * use single getData() function * only send legacy when it is used in explore * pre process rather than post process * pre process rather than post process * Minor refactoring * Add missing tags to test datasource response * MixedDatasource: Adds query observable pattern to MixedDatasource (#19037) * start mixed datasource * Refactor: Refactors into observable parttern * Tests: Fixes tests * Tests: Removes console.log * Refactor: Adds unique requestId
2019-09-12 23:28:46 +08:00
},
});
}
cancelQuery() {
if (!this.subscription) {
return;
}
this.subscription.unsubscribe();
// If we have an old result with loading or streaming state, send it with done state
if (
this.lastResult &&
(this.lastResult.state === LoadingState.Loading || this.lastResult.state === LoadingState.Streaming)
) {
this.subject.next({
...this.lastResult,
state: LoadingState.Done,
});
}
}
resendLastResult = () => {
if (this.lastResult) {
this.subject.next(this.lastResult);
}
};
clearLastResult() {
this.lastResult = undefined;
// A new subject is also needed since it's a replay subject that remembers/sends last value
this.subject = new ReplaySubject(1);
}
/**
* Called when the panel is closed
*/
destroy() {
// Tell anyone listening that we are done
if (this.subject) {
this.subject.complete();
}
QueryProcessing: Observable query interface and RxJS for query & stream processing (#18899) * I needed to learn some rxjs and understand this more, so just playing around * Updated * Removed all the complete calls * Refactoring * StreamHandler -> observable start * progress * simple singal works * Handle update time range * added error handling * wrap old function * minor changes * handle data format in the subscribe function * Use replay subject to return last value to subscribers * Set loading state after no response in 50ms * added missing file * updated comment * Added cancelation of network requests * runRequest: Added unit test scenario framework * Progress on tests * minor refactor of unit tests * updated test * removed some old code * Shared queries work again, and also became so much simplier * unified query and observe methods * implict any fix * Fixed closed subject issue * removed comment * Use last returned data for loading state * WIP: Explore to runRequest makover step1 * Minor progress * Minor progress on explore and runRequest * minor progress * Things are starting to work in explore * Updated prometheus to use new observable query response, greatly simplified code * Revert refId change * Found better solution for key/refId/requestId problem * use observable with loki * tests compile * fix loki query prep * Explore: correct first response handling * Refactorings * Refactoring * Explore: Fixes LoadingState and GraphResults between runs (#18986) * Refactor: Adds state to DataQueryResponse * Fix: Fixes so we do not empty results before new data arrives Fixes: #17409 * Transformations work * observable test data * remove single() from loki promise * Fixed comment * Explore: Fixes failing Loki and Prometheus unit tests (#18995) * Tests: Makes datasource tests work again * Fix: Fixes loki datasource so highligthing works * Chore: Runs Prettier * Fixed query runner tests * Delay loading state indication to 200ms * Fixed test * fixed unit tests * Clear cached calcs * Fixed bug getProcesedDataFrames * Fix the correct test is a better idea * Fix: Fixes so queries in Explore are only run if Graph/Table is shown (#19000) * Fix: Fixes so queries in Explore are only run if Graph/Table is shown Fixes: #18618 * Refactor: Removes unnecessary condition * PanelData: provide legacy data only when needed (#19018) * no legacy * invert logic... now compiles * merge getQueryResponseData and getDataRaw * update comment about query editor * use single getData() function * only send legacy when it is used in explore * pre process rather than post process * pre process rather than post process * Minor refactoring * Add missing tags to test datasource response * MixedDatasource: Adds query observable pattern to MixedDatasource (#19037) * start mixed datasource * Refactor: Refactors into observable parttern * Tests: Fixes tests * Tests: Removes console.log * Refactor: Adds unique requestId
2019-09-12 23:28:46 +08:00
if (this.subscription) {
this.subscription.unsubscribe();
}
}
useLastResultFrom(runner: PanelQueryRunner) {
this.lastResult = runner.getLastResult();
if (this.lastResult) {
// The subject is a replay subject so anyone subscribing will get this last result
this.subject.next(this.lastResult);
}
}
/** Useful from tests */
setLastResult(data: PanelData) {
this.lastResult = data;
}
getLastResult(): PanelData | undefined {
return this.lastResult;
}
getLastRequest(): DataQueryRequest | undefined {
return this.lastRequest;
}
}
async function getDataSource(
datasource: DataSourceRef | string | DataSourceApi | null,
scopedVars: ScopedVars
): Promise<DataSourceApi> {
if (datasource && typeof datasource === 'object' && 'query' in datasource) {
return datasource;
Public Dashboards: Pubdash panels get data from pubdash api (#50556) * Public dashboard query API * Create new API on service for building metric request * Flesh out testing, implement BuildPublicDashboardMetricRequest * Test for errors and missing panels * WIP: Test for multiple datasources * Refactor tests, add supporting code for multiple datasources * Gets the panel data from the pubdash query api * Adds tests to make sure we get the correct api url from retrieving panel data * Public dashboard query API * Create new API on service for building metric request * Flesh out testing, implement BuildPublicDashboardMetricRequest * Test for errors and missing panels * WIP: Test for multiple datasources * Refactor tests, add supporting code for multiple datasources * Handle queries from multiple datasources * Replace dashboard time range with pubdash time range settings * Fix comments from review, build failure * removes changes to DataSourceWithBackend.ts regarding getting the pubdash panel query url. Going to do this in a new class, PublicDashboardDataSource.ts * Include pubdash Uid in dashboard meta * Creates new PublicDashboardDataSource.ts and adds test * Passes pubdash uid down to PanelQueryRunner.ts to a PublicDashboardDatasource can be chosen when were looking at a public dashboard * removes comment * checks for error when unmarshalling json * Only replace dashboard time settings with pubdash time settings when pubdash time settings exist * formatting and added comment Co-authored-by: Jesse Weaver <jesse.weaver@grafana.com> Co-authored-by: Jeff Levin <jeff@levinology.com>
2022-06-14 08:03:43 +08:00
}
return await getDatasourceSrv().get(datasource, scopedVars);
}