diff --git a/public/app/plugins/datasource/loki/LanguageProvider.test.ts b/public/app/plugins/datasource/loki/LanguageProvider.test.ts index a8bd0b9ed97..040e2d48e2d 100644 --- a/public/app/plugins/datasource/loki/LanguageProvider.test.ts +++ b/public/app/plugins/datasource/loki/LanguageProvider.test.ts @@ -1,7 +1,7 @@ import { AbstractLabelOperator, DataFrame } from '@grafana/data'; import LanguageProvider from './LanguageProvider'; -import { LokiDatasource } from './datasource'; +import { DEFAULT_MAX_LINES_SAMPLE, LokiDatasource } from './datasource'; import { createLokiDatasource, createMetadataRequest } from './mocks'; import { extractLogParserFromDataFrame, @@ -275,6 +275,40 @@ describe('Query imports', () => { }); expect(extractLogParserFromDataFrameMock).not.toHaveBeenCalled(); }); + + it('calls dataSample with correct default maxLines', async () => { + jest.spyOn(datasource, 'getDataSamples').mockResolvedValue([]); + + expect(await languageProvider.getParserAndLabelKeys('{place="luna"}')).toEqual({ + extractedLabelKeys: [], + unwrapLabelKeys: [], + hasJSON: false, + hasLogfmt: false, + hasPack: false, + }); + expect(datasource.getDataSamples).toHaveBeenCalledWith({ + expr: '{place="luna"}', + maxLines: DEFAULT_MAX_LINES_SAMPLE, + refId: 'data-samples', + }); + }); + + it('calls dataSample with correctly set sampleSize', async () => { + jest.spyOn(datasource, 'getDataSamples').mockResolvedValue([]); + + expect(await languageProvider.getParserAndLabelKeys('{place="luna"}', { maxLines: 5 })).toEqual({ + extractedLabelKeys: [], + unwrapLabelKeys: [], + hasJSON: false, + hasLogfmt: false, + hasPack: false, + }); + expect(datasource.getDataSamples).toHaveBeenCalledWith({ + expr: '{place="luna"}', + maxLines: 5, + refId: 'data-samples', + }); + }); }); }); diff --git a/public/app/plugins/datasource/loki/LanguageProvider.ts b/public/app/plugins/datasource/loki/LanguageProvider.ts index f2753668ca9..070ec781161 100644 --- a/public/app/plugins/datasource/loki/LanguageProvider.ts +++ b/public/app/plugins/datasource/loki/LanguageProvider.ts @@ -4,7 +4,7 @@ import Prism from 'prismjs'; import { LanguageProvider, AbstractQuery, KeyValue } from '@grafana/data'; import { extractLabelMatchers, processLabels, toPromLikeExpr } from 'app/plugins/datasource/prometheus/language_utils'; -import { LokiDatasource } from './datasource'; +import { DEFAULT_MAX_LINES_SAMPLE, LokiDatasource } from './datasource'; import { extractLabelKeysFromDataFrame, extractLogParserFromDataFrame, @@ -251,11 +251,21 @@ export default class LokiLanguageProvider extends LanguageProvider { * - `unwrapLabelKeys`: An array of label keys that can be used for unwrapping log data. * * @param streamSelector - The selector for the log stream you want to analyze. + * @param {Object} [options] - Optional parameters. + * @param {number} [options.maxLines] - The number of log lines requested when determining parsers and label keys. + * Smaller maxLines is recommended for improved query performance. The default count is 10. * @returns A promise containing an object with parser and label key information. * @throws An error if the fetch operation fails. */ - async getParserAndLabelKeys(streamSelector: string): Promise { - const series = await this.datasource.getDataSamples({ expr: streamSelector, refId: 'data-samples' }); + async getParserAndLabelKeys( + streamSelector: string, + options?: { maxLines?: number } + ): Promise { + const series = await this.datasource.getDataSamples({ + expr: streamSelector, + refId: 'data-samples', + maxLines: options?.maxLines || DEFAULT_MAX_LINES_SAMPLE, + }); if (!series.length) { return { extractedLabelKeys: [], unwrapLabelKeys: [], hasJSON: false, hasLogfmt: false, hasPack: false }; diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index e75462608c2..615bd7e360e 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -99,6 +99,7 @@ import { LokiVariableSupport } from './variables'; export type RangeQueryOptions = DataQueryRequest | AnnotationQueryRequest; export const DEFAULT_MAX_LINES = 1000; +export const DEFAULT_MAX_LINES_SAMPLE = 10; export const LOKI_ENDPOINT = '/loki/api/v1'; export const REF_ID_DATA_SAMPLES = 'loki-data-samples'; export const REF_ID_STARTER_ANNOTATION = 'annotation-'; @@ -761,8 +762,7 @@ export class LokiDatasource expr: query.expr, queryType: LokiQueryType.Range, refId: REF_ID_DATA_SAMPLES, - // For samples we limit the request to 10 lines, so queries are small and fast - maxLines: 10, + maxLines: query.maxLines || DEFAULT_MAX_LINES_SAMPLE, supportingQueryType: SupportingQueryType.DataSample, }; diff --git a/public/app/plugins/datasource/loki/docs/app_plugin_developer_documentation.md b/public/app/plugins/datasource/loki/docs/app_plugin_developer_documentation.md index 04e8f996292..7dc09b6f771 100644 --- a/public/app/plugins/datasource/loki/docs/app_plugin_developer_documentation.md +++ b/public/app/plugins/datasource/loki/docs/app_plugin_developer_documentation.md @@ -138,10 +138,16 @@ try { * - `unwrapLabelKeys`: An array of label keys that can be used for unwrapping log data. * * @param streamSelector - The selector for the log stream you want to analyze. + * @param {Object} [options] - Optional parameters. + * @param {number} [options.maxLines] - The number of log lines requested when determining parsers and label keys. + * Smaller maxLines is recommended for improved query performance. The default count is 10. * @returns A promise containing an object with parser and label key information. * @throws An error if the fetch operation fails. */ -async function getParserAndLabelKeys(streamSelector: string): Promise<{ +async function getParserAndLabelKeys( + streamSelector: string, + options?: { maxLines?: number } +): Promise<{ extractedLabelKeys: string[]; hasJSON: boolean; hasLogfmt: boolean; @@ -154,7 +160,7 @@ async function getParserAndLabelKeys(streamSelector: string): Promise<{ */ const streamSelector = '{job="grafana"}'; try { - const parserAndLabelKeys = await getParserAndLabelKeys(streamSelector); + const parserAndLabelKeys = await getParserAndLabelKeys(streamSelector, { maxLines: 5 }); console.log(parserAndLabelKeys); } catch (error) { console.error(`Error fetching parser and label keys: ${error.message}`);