Skip to content

Commit 3ba2457

Browse files
authored
Query splitting: Interpolate queries at the start of the process (#107534)
* Loki query splitting: interpolate queries before execution * Update tests * Prettier * shardQuerySplitting: remove unnecessary call
1 parent dcb853d commit 3ba2457

File tree

4 files changed

+48
-15
lines changed

4 files changed

+48
-15
lines changed

public/app/plugins/datasource/loki/querySplitting.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,21 @@ describe('runSplitQuery()', () => {
7272
});
7373
});
7474

75+
test('Interpolates queries before execution', async () => {
76+
const request = createRequest([{ expr: 'count_over_time({a="b"}[$__auto])', refId: 'A', step: '$step' }]);
77+
datasource = createLokiDatasource({
78+
replace: (input = '') => {
79+
return input.replace('$__auto', '5m').replace('$step', '5m');
80+
},
81+
getVariables: () => [],
82+
});
83+
jest.spyOn(datasource, 'runQuery').mockReturnValue(of({ data: [] }));
84+
await expect(runSplitQuery(datasource, request)).toEmitValuesWith(() => {
85+
expect(jest.mocked(datasource.runQuery).mock.calls[0][0].targets[0].expr).toBe('count_over_time({a="b"}[5m])');
86+
expect(jest.mocked(datasource.runQuery).mock.calls[0][0].targets[0].step).toBe('5m');
87+
});
88+
});
89+
7590
test('Skips partial updates as an option', async () => {
7691
await expect(runSplitQuery(datasource, request, { skipPartialUpdates: true })).toEmitValuesWith((emitted) => {
7792
// 3 days, 3 chunks, 3 requests.

public/app/plugins/datasource/loki/querySplitting.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,10 @@ export function runSplitQuery(
293293
request: DataQueryRequest<LokiQuery>,
294294
options: QuerySplittingOptions = {}
295295
) {
296-
const queries = request.targets.filter((query) => !query.hide).filter((query) => query.expr);
296+
const queries = request.targets
297+
.filter((query) => !query.hide)
298+
.filter((query) => query.expr)
299+
.map((query) => datasource.applyTemplateVariables(query, request.scopedVars, request.filters));
297300
const [nonSplittingQueries, normalQueries] = partition(queries, (query) => !querySupportsSplitting(query));
298301
const [logQueries, metricQueries] = partition(normalQueries, (query) => isLogsQuery(query.expr));
299302

public/app/plugins/datasource/loki/shardQuerySplitting.test.ts

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,9 @@ describe('runShardSplitQuery()', () => {
5353
request = createRequest([{ expr: '$SELECTOR', refId: 'A', direction: LokiQueryDirection.Scan }]);
5454
datasource = createLokiDatasource();
5555
datasource.languageProvider.fetchLabelValues = jest.fn();
56-
datasource.interpolateVariablesInQueries = jest.fn().mockImplementation((queries: LokiQuery[]) => {
57-
return queries.map((query) => {
58-
query.expr = query.expr.replace('$SELECTOR', '{a="b"}');
59-
return query;
60-
});
56+
datasource.applyTemplateVariables = jest.fn().mockImplementation((query: LokiQuery) => {
57+
query.expr = query.expr.replace('$SELECTOR', '{a="b"}');
58+
return query;
6159
});
6260
jest.mocked(datasource.languageProvider.fetchLabelValues).mockResolvedValue(['1', '10', '2', '20', '3']);
6361
const { metricFrameA } = getMockFrames();
@@ -83,6 +81,25 @@ describe('runShardSplitQuery()', () => {
8381
});
8482
});
8583

84+
test('Interpolates queries before execution', async () => {
85+
const request = createRequest([{ expr: 'count_over_time({a="b"}[$__auto])', refId: 'A', step: '$step' }]);
86+
datasource = createLokiDatasource({
87+
replace: (input = '') => {
88+
return input.replace('$__auto', '5m').replace('$step', '5m');
89+
},
90+
getVariables: () => [],
91+
});
92+
jest.spyOn(datasource, 'runQuery').mockReturnValue(of({ data: [] }));
93+
datasource.languageProvider.fetchLabelValues = jest.fn();
94+
jest.mocked(datasource.languageProvider.fetchLabelValues).mockResolvedValue(['1', '10', '2', '20', '3']);
95+
await expect(runShardSplitQuery(datasource, request)).toEmitValuesWith(() => {
96+
expect(jest.mocked(datasource.runQuery).mock.calls[0][0].targets[0].expr).toBe(
97+
'count_over_time({a="b", __stream_shard__=~"20|10"} | drop __stream_shard__[5m])'
98+
);
99+
expect(jest.mocked(datasource.runQuery).mock.calls[0][0].targets[0].step).toBe('5m');
100+
});
101+
});
102+
86103
test('Users query splitting for querying over a day', async () => {
87104
await expect(runShardSplitQuery(datasource, request)).toEmitValuesWith(() => {
88105
// 5 shards, 3 groups + empty shard group, 4 requests
@@ -92,7 +109,7 @@ describe('runShardSplitQuery()', () => {
92109

93110
test('Interpolates queries before running', async () => {
94111
await expect(runShardSplitQuery(datasource, request)).toEmitValuesWith(() => {
95-
expect(datasource.interpolateVariablesInQueries).toHaveBeenCalledTimes(1);
112+
expect(datasource.applyTemplateVariables).toHaveBeenCalledTimes(5);
96113

97114
expect(datasource.runQuery).toHaveBeenCalledWith({
98115
intervalMs: expect.any(Number),
@@ -153,11 +170,9 @@ describe('runShardSplitQuery()', () => {
153170
});
154171

155172
test('Sends the whole stream selector to fetch values', async () => {
156-
datasource.interpolateVariablesInQueries = jest.fn().mockImplementation((queries: LokiQuery[]) => {
157-
return queries.map((query) => {
158-
query.expr = query.expr.replace('$SELECTOR', '{service_name="test", filter="true"}');
159-
return query;
160-
});
173+
datasource.applyTemplateVariables = jest.fn().mockImplementation((query: LokiQuery) => {
174+
query.expr = query.expr.replace('$SELECTOR', '{service_name="test", filter="true"}');
175+
return query;
161176
});
162177

163178
await expect(runShardSplitQuery(datasource, request)).toEmitValuesWith(() => {

public/app/plugins/datasource/loki/shardQuerySplitting.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ import { LokiQuery } from './types';
4646
*/
4747

4848
export function runShardSplitQuery(datasource: LokiDatasource, request: DataQueryRequest<LokiQuery>) {
49-
const queries = datasource
50-
.interpolateVariablesInQueries(request.targets, request.scopedVars)
49+
const queries = request.targets
5150
.filter((query) => query.expr)
52-
.filter((query) => !query.hide);
51+
.filter((query) => !query.hide)
52+
.map((query) => datasource.applyTemplateVariables(query, request.scopedVars, request.filters));
5353

5454
return splitQueriesByStreamShard(datasource, request, queries);
5555
}

0 commit comments

Comments
 (0)