CloudWatch Logs: Fix to make log queries use a relative time if available (#65236)

This commit is contained in:
Kevin Yu 2023-03-23 13:11:12 -07:00 committed by GitHub
parent a02a28f229
commit 0871b6aea9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 9 deletions

View File

@ -2,11 +2,11 @@ import { of } from 'rxjs';
import { CustomVariableModel, DataFrame, DataSourceInstanceSettings } from '@grafana/data';
import { BackendDataSourceResponse, getBackendSrv, setBackendSrv } from '@grafana/runtime';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { CloudWatchLogsQueryRunner } from '../query-runner/CloudWatchLogsQueryRunner';
import { CloudWatchJsonData, CloudWatchLogsQueryStatus } from '../types';
import { CloudWatchJsonData, CloudWatchLogsQueryStatus, CloudWatchLogsRequest } from '../types';
import { CloudWatchSettings, setupMockedTemplateService } from './CloudWatchDataSource';
@ -17,11 +17,13 @@ export function setupMockedLogsQueryRunner({
variables,
mockGetVariableName = true,
settings = CloudWatchSettings,
timeSrv = getTimeSrv(),
}: {
data?: BackendDataSourceResponse;
variables?: CustomVariableModel[];
mockGetVariableName?: boolean;
settings?: DataSourceInstanceSettings<CloudWatchJsonData>;
timeSrv?: TimeSrv;
} = {}) {
let templateService = new TemplateSrv();
if (variables) {
@ -31,7 +33,7 @@ export function setupMockedLogsQueryRunner({
}
}
const runner = new CloudWatchLogsQueryRunner(settings, templateService, getTimeSrv());
const runner = new CloudWatchLogsQueryRunner(settings, templateService, timeSrv);
const fetchMock = jest.fn().mockReturnValue(of({ data }));
setBackendSrv({
...getBackendSrv(),
@ -66,3 +68,19 @@ export function genMockFrames(numResponses: number): DataFrame[] {
return mockFrames;
}
export function genMockCloudWatchLogsRequest(overrides: Partial<CloudWatchLogsRequest> = {}) {
const request: CloudWatchLogsRequest = {
queryString: 'fields @timestamp, @message | sort @timestamp desc',
logGroupNames: ['log-group-name-1', 'log-group-name-2'],
logGroups: [
{ arn: 'log-group-arn-1', name: 'log-group-name-1' },
{ arn: 'log-group-arn-2', name: 'log-group-name-2' },
],
refId: 'A',
region: 'us-east-1',
...overrides,
};
return request;
}

View File

@ -1,6 +1,15 @@
import { interval, lastValueFrom, of } from 'rxjs';
import { DataQueryErrorType, FieldType, LogLevel, LogRowModel, MutableDataFrame } from '@grafana/data';
import {
DataQueryErrorType,
FieldType,
LogLevel,
LogRowModel,
MutableDataFrame,
dateTime,
DataQueryRequest,
} from '@grafana/data';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import {
CloudWatchSettings,
@ -8,7 +17,7 @@ import {
logGroupNamesVariable,
regionVariable,
} from '../__mocks__/CloudWatchDataSource';
import { genMockFrames, setupMockedLogsQueryRunner } from '../__mocks__/LogsQueryRunner';
import { genMockFrames, genMockCloudWatchLogsRequest, setupMockedLogsQueryRunner } from '../__mocks__/LogsQueryRunner';
import { LogsRequestMock } from '../__mocks__/Request';
import { validLogsQuery } from '../__mocks__/queries';
import { CloudWatchLogsQuery, LogAction, StartQueryRequest } from '../types';
@ -272,7 +281,39 @@ describe('CloudWatchLogsQueryRunner', () => {
region: regionVariable.current.value as string,
},
];
expect(spy).toHaveBeenNthCalledWith(1, 'StartQuery', startQueryRequests);
expect(spy).toHaveBeenNthCalledWith(1, 'StartQuery', startQueryRequests, LogsRequestMock);
});
});
describe('makeLogActionRequest', () => {
it('should use the time range from the options if it is available', async () => {
const { runner } = setupMockedLogsQueryRunner();
const spy = jest.spyOn(runner, 'awsRequest');
const from = dateTime(0);
const to = dateTime(1000);
const options: DataQueryRequest<CloudWatchLogsQuery> = {
...LogsRequestMock,
range: { from, to, raw: { from, to } },
};
await lastValueFrom(runner.makeLogActionRequest('StartQuery', [genMockCloudWatchLogsRequest()], options));
expect(spy).toHaveBeenNthCalledWith(1, '/api/ds/query', expect.objectContaining({ from: '0', to: '1000' }), {
'X-Cache-Skip': 'true',
});
});
it('should use the time range from the timeSrv if the time range in the options is not available', async () => {
const timeSrv = getTimeSrv();
timeSrv.timeRange = jest.fn().mockReturnValue({
from: dateTime(1111),
to: dateTime(2222),
raw: { from: dateTime(1111), to: dateTime(2222) },
});
const { runner } = setupMockedLogsQueryRunner({ timeSrv });
const spy = jest.spyOn(runner, 'awsRequest');
await lastValueFrom(runner.makeLogActionRequest('StartQuery', [genMockCloudWatchLogsRequest()]));
expect(spy).toHaveBeenNthCalledWith(1, '/api/ds/query', expect.objectContaining({ from: '1111', to: '2222' }), {
'X-Cache-Skip': 'true',
});
});
});
});

View File

@ -118,7 +118,7 @@ export class CloudWatchLogsQueryRunner extends CloudWatchRequest {
return runWithRetry(
(targets: StartQueryRequest[]) => {
return this.makeLogActionRequest('StartQuery', targets);
return this.makeLogActionRequest('StartQuery', targets, options);
},
startQueryRequests,
timeoutFunc
@ -269,8 +269,12 @@ export class CloudWatchLogsQueryRunner extends CloudWatchRequest {
}
}
makeLogActionRequest(subtype: LogAction, queryParams: CloudWatchLogsRequest[]): Observable<DataFrame[]> {
const range = this.timeSrv.timeRange();
makeLogActionRequest(
subtype: LogAction,
queryParams: CloudWatchLogsRequest[],
options?: DataQueryRequest<CloudWatchQuery>
): Observable<DataFrame[]> {
const range = options?.range || this.timeSrv.timeRange();
const requestParams = {
from: range.from.valueOf().toString(),