mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Elasticsearch: Allow setting a custom limit for log queries (#32422)
This commit is contained in:
parent
b0c6cad637
commit
15978900a9
@ -72,6 +72,8 @@ export const SettingsEditor: FunctionComponent<Props> = ({ metric, previousMetri
|
|||||||
</InlineField>
|
</InlineField>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{metric.type === 'logs' && <SettingField label="Limit" metric={metric} settingName="limit" placeholder="500" />}
|
||||||
|
|
||||||
{metric.type === 'cardinality' && (
|
{metric.type === 'cardinality' && (
|
||||||
<SettingField label="Precision Threshold" metric={metric} settingName="precision_threshold" />
|
<SettingField label="Precision Threshold" metric={metric} settingName="precision_threshold" />
|
||||||
)}
|
)}
|
||||||
|
@ -148,6 +148,9 @@ export interface RawData extends BaseMetricAggregation {
|
|||||||
|
|
||||||
export interface Logs extends BaseMetricAggregation {
|
export interface Logs extends BaseMetricAggregation {
|
||||||
type: 'logs';
|
type: 'logs';
|
||||||
|
settings?: {
|
||||||
|
limit?: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BasePipelineMetricAggregation extends MetricAggregationWithField {
|
export interface BasePipelineMetricAggregation extends MetricAggregationWithField {
|
||||||
@ -289,11 +292,12 @@ export type MetricAggregationWithSettings =
|
|||||||
| Sum
|
| Sum
|
||||||
| Average
|
| Average
|
||||||
| MovingAverage
|
| MovingAverage
|
||||||
| MovingFunction;
|
| MovingFunction
|
||||||
|
| Logs;
|
||||||
|
|
||||||
export type MetricAggregationWithMeta = ExtendedStats;
|
export type MetricAggregationWithMeta = ExtendedStats;
|
||||||
|
|
||||||
export type MetricAggregation = Count | Logs | PipelineMetricAggregation | MetricAggregationWithSettings;
|
export type MetricAggregation = Count | PipelineMetricAggregation | MetricAggregationWithSettings;
|
||||||
|
|
||||||
// Guards
|
// Guards
|
||||||
// Given the structure of the aggregations (ie. `settings` field being always optional) we cannot
|
// Given the structure of the aggregations (ie. `settings` field being always optional) we cannot
|
||||||
|
@ -226,10 +226,15 @@ export const metricAggregationConfig: MetricsConfiguration = {
|
|||||||
isPipelineAgg: false,
|
isPipelineAgg: false,
|
||||||
supportsMissing: false,
|
supportsMissing: false,
|
||||||
supportsMultipleBucketPaths: false,
|
supportsMultipleBucketPaths: false,
|
||||||
hasSettings: false,
|
hasSettings: true,
|
||||||
|
isSingleMetric: true,
|
||||||
supportsInlineScript: false,
|
supportsInlineScript: false,
|
||||||
hasMeta: false,
|
hasMeta: false,
|
||||||
defaults: {},
|
defaults: {
|
||||||
|
settings: {
|
||||||
|
limit: '500',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import { metricAggregationConfig } from './components/QueryEditor/MetricAggregat
|
|||||||
import {
|
import {
|
||||||
isMetricAggregationWithField,
|
isMetricAggregationWithField,
|
||||||
isPipelineAggregationWithMultipleBucketPaths,
|
isPipelineAggregationWithMultipleBucketPaths,
|
||||||
|
Logs,
|
||||||
} from './components/QueryEditor/MetricAggregationsEditor/aggregations';
|
} from './components/QueryEditor/MetricAggregationsEditor/aggregations';
|
||||||
import { bucketAggregationConfig } from './components/QueryEditor/BucketAggregationsEditor/utils';
|
import { bucketAggregationConfig } from './components/QueryEditor/BucketAggregationsEditor/utils';
|
||||||
import { isBucketAggregationWithField } from './components/QueryEditor/BucketAggregationsEditor/aggregations';
|
import { isBucketAggregationWithField } from './components/QueryEditor/BucketAggregationsEditor/aggregations';
|
||||||
@ -549,10 +550,19 @@ export class ElasticDatasource extends DataSourceApi<ElasticsearchQuery, Elastic
|
|||||||
|
|
||||||
let queryObj;
|
let queryObj;
|
||||||
if (hasMetricOfType(target, 'logs')) {
|
if (hasMetricOfType(target, 'logs')) {
|
||||||
|
// FIXME: All this logic here should be in the query builder.
|
||||||
|
// When moving to the BE-only implementation we should remove this and let the BE
|
||||||
|
// Handle this.
|
||||||
|
// TODO: defaultBucketAgg creates a dete_histogram aggregation without a field, so it fallbacks to
|
||||||
|
// the configured timeField. we should allow people to use a different time field here.
|
||||||
target.bucketAggs = [defaultBucketAgg()];
|
target.bucketAggs = [defaultBucketAgg()];
|
||||||
|
|
||||||
|
const log = target.metrics?.find((m) => m.type === 'logs') as Logs;
|
||||||
|
const limit = log.settings?.limit ? parseInt(log.settings?.limit, 10) : 500;
|
||||||
|
|
||||||
target.metrics = [];
|
target.metrics = [];
|
||||||
// Setting this for metrics queries that are typed as logs
|
// Setting this for metrics queries that are typed as logs
|
||||||
queryObj = this.queryBuilder.getLogsQuery(target, adhocFilters, target.query);
|
queryObj = this.queryBuilder.getLogsQuery(target, limit, adhocFilters, target.query);
|
||||||
} else {
|
} else {
|
||||||
if (target.alias) {
|
if (target.alias) {
|
||||||
target.alias = this.templateSrv.replace(target.alias, options.scopedVars, 'lucene');
|
target.alias = this.templateSrv.replace(target.alias, options.scopedVars, 'lucene');
|
||||||
|
@ -415,7 +415,7 @@ export class ElasticQueryBuilder {
|
|||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
getLogsQuery(target: ElasticsearchQuery, adhocFilters?: any, querystring?: string) {
|
getLogsQuery(target: ElasticsearchQuery, limit: number, adhocFilters?: any, querystring?: string) {
|
||||||
let query: any = {
|
let query: any = {
|
||||||
size: 0,
|
size: 0,
|
||||||
query: {
|
query: {
|
||||||
@ -436,7 +436,7 @@ export class ElasticQueryBuilder {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
query = this.documentQuery(query, 500);
|
query = this.documentQuery(query, limit);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...query,
|
...query,
|
||||||
|
@ -680,7 +680,7 @@ describe('ElasticQueryBuilder', () => {
|
|||||||
|
|
||||||
describe('getLogsQuery', () => {
|
describe('getLogsQuery', () => {
|
||||||
it('should return query with defaults', () => {
|
it('should return query with defaults', () => {
|
||||||
const query = builder.getLogsQuery({ refId: 'A' }, null, '*');
|
const query = builder.getLogsQuery({ refId: 'A' }, 500, null, '*');
|
||||||
|
|
||||||
expect(query.size).toEqual(500);
|
expect(query.size).toEqual(500);
|
||||||
|
|
||||||
@ -714,7 +714,7 @@ describe('ElasticQueryBuilder', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('with querystring', () => {
|
it('with querystring', () => {
|
||||||
const query = builder.getLogsQuery({ refId: 'A', query: 'foo' }, null, 'foo');
|
const query = builder.getLogsQuery({ refId: 'A', query: 'foo' }, 500, null, 'foo');
|
||||||
|
|
||||||
const expectedQuery = {
|
const expectedQuery = {
|
||||||
bool: {
|
bool: {
|
||||||
@ -737,7 +737,7 @@ describe('ElasticQueryBuilder', () => {
|
|||||||
{ key: 'key5', operator: '=~', value: 'value5' },
|
{ key: 'key5', operator: '=~', value: 'value5' },
|
||||||
{ key: 'key6', operator: '!~', value: 'value6' },
|
{ key: 'key6', operator: '!~', value: 'value6' },
|
||||||
];
|
];
|
||||||
const query = builder.getLogsQuery({ refId: 'A' }, adhocFilters, '*');
|
const query = builder.getLogsQuery({ refId: 'A' }, 500, adhocFilters, '*');
|
||||||
|
|
||||||
expect(query.query.bool.must[0].match_phrase['key1'].query).toBe('value1');
|
expect(query.query.bool.must[0].match_phrase['key1'].query).toBe('value1');
|
||||||
expect(query.query.bool.must_not[0].match_phrase['key2'].query).toBe('value2');
|
expect(query.query.bool.must_not[0].match_phrase['key2'].query).toBe('value2');
|
||||||
|
Loading…
Reference in New Issue
Block a user