diff --git a/x-pack/plugins/uptime/server/lib/requests/get_pings.ts b/x-pack/plugins/uptime/server/lib/requests/get_pings.ts index 15c5cbd4181ac..03ec2d7343c9a 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_pings.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_pings.ts @@ -14,6 +14,43 @@ import { const DEFAULT_PAGE_SIZE = 25; +/** + * This branch of filtering is used for monitors of type `browser`. This monitor + * type represents an unbounded set of steps, with each `check_group` representing + * a distinct journey. The document containing the `summary` field is indexed last, and + * contains the data necessary for querying a journey. + * + * Because of this, when querying for "pings", it is important that we treat `browser` summary + * checks as the "ping" we want. Without this filtering, we will receive >= N pings for a journey + * of N steps, because an individual step may also contain multiple documents. + */ +const REMOVE_NON_SUMMARY_BROWSER_CHECKS = { + must_not: [ + { + bool: { + filter: [ + { + term: { + 'monitor.type': 'browser', + }, + }, + { + bool: { + must_not: [ + { + exists: { + field: 'summary', + }, + }, + ], + }, + }, + ], + }, + }, + ], +}; + export const getPings: UMElasticsearchQueryFn = async ({ callES, dynamicSettings, @@ -27,10 +64,7 @@ export const getPings: UMElasticsearchQueryFn = a }) => { const size = sizeParam ?? DEFAULT_PAGE_SIZE; const sortParam = { sort: [{ '@timestamp': { order: sort ?? 'desc' } }] }; - const filter: any[] = [ - { range: { '@timestamp': { gte: from, lte: to } } }, - { exists: { field: 'summary' } }, - ]; + const filter: any[] = [{ range: { '@timestamp': { gte: from, lte: to } } }]; if (monitorId) { filter.push({ term: { 'monitor.id': monitorId } }); } @@ -42,7 +76,12 @@ export const getPings: UMElasticsearchQueryFn = a if (location) { postFilterClause = { post_filter: { term: { 'observer.geo.name': location } } }; } - const queryContext = { bool: { filter } }; + const queryContext = { + bool: { + filter, + ...REMOVE_NON_SUMMARY_BROWSER_CHECKS, + }, + }; const params: any = { index: dynamicSettings.heartbeatIndices, body: {