diff --git a/public/app/plugins/datasource/loki/datasource.test.ts b/public/app/plugins/datasource/loki/datasource.test.ts index ddb4d6ed549..b7f67ffc0e7 100644 --- a/public/app/plugins/datasource/loki/datasource.test.ts +++ b/public/app/plugins/datasource/loki/datasource.test.ts @@ -1,10 +1,39 @@ import LokiDatasource from './datasource'; describe('LokiDatasource', () => { - const instanceSettings = { + const instanceSettings: any = { url: 'myloggingurl', }; + describe('when querying', () => { + const backendSrvMock = { datasourceRequest: jest.fn() }; + + const templateSrvMock = { + getAdhocFilters: () => [], + replace: a => a, + }; + + const range = { from: 'now-6h', to: 'now' }; + + test('should use default max lines when no limit given', () => { + const ds = new LokiDatasource(instanceSettings, backendSrvMock, templateSrvMock); + backendSrvMock.datasourceRequest = jest.fn(); + ds.query({ range, targets: [{ expr: 'foo' }] }); + expect(backendSrvMock.datasourceRequest.mock.calls.length).toBe(1); + expect(backendSrvMock.datasourceRequest.mock.calls[0][0].url).toContain('limit=1000'); + }); + + test('should use custom max lines if limit is set', () => { + const customData = { ...(instanceSettings.jsonData || {}), maxLines: 20 }; + const customSettings = { ...instanceSettings, jsonData: customData }; + const ds = new LokiDatasource(customSettings, backendSrvMock, templateSrvMock); + backendSrvMock.datasourceRequest = jest.fn(); + ds.query({ range, targets: [{ expr: 'foo' }] }); + expect(backendSrvMock.datasourceRequest.mock.calls.length).toBe(1); + expect(backendSrvMock.datasourceRequest.mock.calls[0][0].url).toContain('limit=20'); + }); + }); + describe('when performing testDataSource', () => { let ds; let result; diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index ebbe6bb4b56..eb33c7ef285 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -9,11 +9,11 @@ import LanguageProvider from './language_provider'; import { mergeStreamsToLogs } from './result_transformer'; import { formatQuery, parseQuery } from './query_utils'; -export const DEFAULT_LIMIT = 1000; +export const DEFAULT_MAX_LINES = 1000; const DEFAULT_QUERY_PARAMS = { direction: 'BACKWARD', - limit: DEFAULT_LIMIT, + limit: DEFAULT_MAX_LINES, regexp: '', query: '', }; @@ -29,10 +29,13 @@ function serializeParams(data: any) { export default class LokiDatasource { languageProvider: LanguageProvider; + maxLines: number; /** @ngInject */ constructor(private instanceSettings, private backendSrv, private templateSrv) { this.languageProvider = new LanguageProvider(this); + const settingsData = instanceSettings.jsonData || {}; + this.maxLines = parseInt(settingsData.maxLines, 10) || DEFAULT_MAX_LINES; } _request(apiUrl: string, data?, options?: any) { @@ -47,7 +50,7 @@ export default class LokiDatasource { } mergeStreams(streams: LogsStream[], intervalMs: number): LogsModel { - const logs = mergeStreamsToLogs(streams); + const logs = mergeStreamsToLogs(streams, this.maxLines); logs.series = makeSeriesForLogs(logs.rows, intervalMs); return logs; } @@ -61,6 +64,7 @@ export default class LokiDatasource { ...parseQuery(interpolated), start, end, + limit: this.maxLines, }; } @@ -77,6 +81,9 @@ export default class LokiDatasource { return Promise.all(queries).then((results: any[]) => { // Flatten streams from multiple queries const allStreams: LogsStream[] = results.reduce((acc, response, i) => { + if (!response) { + return acc; + } const streams: LogsStream[] = response.data.streams || []; // Inject search for match highlighting const search: string = queryTargets[i].regexp; diff --git a/public/app/plugins/datasource/loki/partials/config.html b/public/app/plugins/datasource/loki/partials/config.html index 8e79cc0adcc..d209b51730a 100644 --- a/public/app/plugins/datasource/loki/partials/config.html +++ b/public/app/plugins/datasource/loki/partials/config.html @@ -1,2 +1,16 @@ - \ No newline at end of file + + +
+
+
+ Maximum lines + + + Loki queries must contain a limit of the maximum number of lines returned (default: 1000). + Increase this limit to have a bigger result set for ad-hoc analysis. + Decrease this limit if your browser becomes sluggish when displaying the log results. + +
+
+
diff --git a/public/app/plugins/datasource/loki/result_transformer.ts b/public/app/plugins/datasource/loki/result_transformer.ts index b24f7d473b9..1f86f20d6fd 100644 --- a/public/app/plugins/datasource/loki/result_transformer.ts +++ b/public/app/plugins/datasource/loki/result_transformer.ts @@ -11,7 +11,7 @@ import { LogsStreamLabels, LogsMetaKind, } from 'app/core/logs_model'; -import { DEFAULT_LIMIT } from './datasource'; +import { DEFAULT_MAX_LINES } from './datasource'; /** * Returns the log level of a log line. @@ -140,7 +140,7 @@ export function processEntry( }; } -export function mergeStreamsToLogs(streams: LogsStream[], limit = DEFAULT_LIMIT): LogsModel { +export function mergeStreamsToLogs(streams: LogsStream[], limit = DEFAULT_MAX_LINES): LogsModel { // Unique model identifier const id = streams.map(stream => stream.labels).join();