[Alerting] Fixing null accessor error in index threshold alert (#98055)

* Fixing null accessor error in index threshold alert

* PR fixes

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
ymao1 2021-04-23 16:54:54 -04:00 committed by GitHub
parent a304bb3577
commit 26315aa751
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 155 additions and 5 deletions

View file

@ -175,7 +175,19 @@ export function getAlertType(
// console.log(`index_threshold: response: ${JSON.stringify(groupResults, null, 4)}`);
for (const groupResult of groupResults) {
const instanceId = groupResult.group;
const value = groupResult.metrics[0][1];
const metric =
groupResult.metrics && groupResult.metrics.length > 0 ? groupResult.metrics[0] : null;
const value = metric && metric.length === 2 ? metric[1] : null;
if (!value) {
logger.debug(
`alert ${ID}:${alertId} "${name}": no metrics found for group ${instanceId}} from groupResult ${JSON.stringify(
groupResult
)}`
);
continue;
}
const met = compareFn(value, params.threshold);
if (!met) continue;

View file

@ -7,8 +7,14 @@
// test error conditions of calling timeSeriesQuery - postive results tested in FT
import type { estypes } from '@elastic/elasticsearch';
import { loggingSystemMock } from '../../../../../../src/core/server/mocks';
import { TimeSeriesQueryParameters, TimeSeriesQuery, timeSeriesQuery } from './time_series_query';
import {
TimeSeriesQueryParameters,
TimeSeriesQuery,
timeSeriesQuery,
getResultFromEs,
} from './time_series_query';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from '../../../../../../src/core/server/elasticsearch/client/mocks';
@ -53,3 +59,135 @@ describe('timeSeriesQuery', () => {
);
});
});
describe('getResultFromEs', () => {
it('correctly parses time series results for count aggregation', () => {
expect(
getResultFromEs(true, false, {
took: 0,
timed_out: false,
_shards: { total: 1, successful: 1, skipped: 0, failed: 0 },
hits: { total: { value: 0, relation: 'eq' }, hits: [] },
aggregations: {
dateAgg: {
buckets: [
{
key: '2021-04-22T15:14:31.075Z-2021-04-22T15:19:31.075Z',
from: 1619104471075,
from_as_string: '2021-04-22T15:14:31.075Z',
to: 1619104771075,
to_as_string: '2021-04-22T15:19:31.075Z',
doc_count: 0,
},
],
},
},
} as estypes.SearchResponse<unknown>)
).toEqual({
results: [
{
group: 'all documents',
metrics: [['2021-04-22T15:19:31.075Z', 0]],
},
],
});
});
it('correctly parses time series results with no aggregation data for count aggregation', () => {
// this could happen with cross cluster searches when cluster permissions are incorrect
// the query completes but doesn't return any aggregations
expect(
getResultFromEs(true, false, {
took: 0,
timed_out: false,
_shards: { total: 0, successful: 0, skipped: 0, failed: 0 },
_clusters: { total: 1, successful: 1, skipped: 0 },
hits: { total: { value: 0, relation: 'eq' }, hits: [] },
} as estypes.SearchResponse<unknown>)
).toEqual({
results: [],
});
});
it('correctly parses time series results for group aggregation', () => {
expect(
getResultFromEs(false, true, {
took: 1,
timed_out: false,
_shards: { total: 1, successful: 1, skipped: 0, failed: 0 },
hits: { total: { value: 298, relation: 'eq' }, hits: [] },
aggregations: {
groupAgg: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{
key: 'host-2',
doc_count: 149,
sortValueAgg: { value: 0.5000000018251423 },
dateAgg: {
buckets: [
{
key: '2021-04-22T15:18:43.191Z-2021-04-22T15:23:43.191Z',
from: 1619104723191,
from_as_string: '2021-04-22T15:18:43.191Z',
to: 1619105023191,
to_as_string: '2021-04-22T15:23:43.191Z',
doc_count: 149,
metricAgg: { value: 0.5000000018251423 },
},
],
},
},
{
key: 'host-1',
doc_count: 149,
sortValueAgg: { value: 0.5000000011000857 },
dateAgg: {
buckets: [
{
key: '2021-04-22T15:18:43.191Z-2021-04-22T15:23:43.191Z',
from: 1619104723191,
from_as_string: '2021-04-22T15:18:43.191Z',
to: 1619105023191,
to_as_string: '2021-04-22T15:23:43.191Z',
doc_count: 149,
metricAgg: { value: 0.5000000011000857 },
},
],
},
},
],
},
},
} as estypes.SearchResponse<unknown>)
).toEqual({
results: [
{
group: 'host-2',
metrics: [['2021-04-22T15:23:43.191Z', 0.5000000018251423]],
},
{
group: 'host-1',
metrics: [['2021-04-22T15:23:43.191Z', 0.5000000011000857]],
},
],
});
});
it('correctly parses time series results with no aggregation data for group aggregation', () => {
// this could happen with cross cluster searches when cluster permissions are incorrect
// the query completes but doesn't return any aggregations
expect(
getResultFromEs(false, true, {
took: 0,
timed_out: false,
_shards: { total: 0, successful: 0, skipped: 0, failed: 0 },
_clusters: { total: 1, successful: 1, skipped: 0 },
hits: { total: { value: 0, relation: 'eq' }, hits: [] },
} as estypes.SearchResponse<unknown>)
).toEqual({
results: [],
});
});
});

View file

@ -147,7 +147,7 @@ export async function timeSeriesQuery(
return getResultFromEs(isCountAgg, isGroupAgg, esResult);
}
function getResultFromEs(
export function getResultFromEs(
isCountAgg: boolean,
isGroupAgg: boolean,
esResult: estypes.SearchResponse<unknown>
@ -155,8 +155,8 @@ function getResultFromEs(
const aggregations = esResult?.aggregations || {};
// add a fake 'all documents' group aggregation, if a group aggregation wasn't used
if (!isGroupAgg) {
const dateAgg = aggregations.dateAgg || {};
if (!isGroupAgg && aggregations.dateAgg) {
const dateAgg = aggregations.dateAgg;
aggregations.groupAgg = {
buckets: [{ key: 'all documents', dateAgg }],