From 9a9cfc54264b19f9d7599d0e19a80050399e619f Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Fri, 19 Jul 2019 16:40:22 -0500 Subject: [PATCH] [Uptime] Fix filter status bar location selection (#41382) (#41591) The way this query worked was strange, this replaces it with a standard terms query and gets rid of the weird MonitorKey stuff. --- .../uptime/common/graphql/introspection.json | 18 ++++- .../plugins/uptime/common/graphql/types.ts | 4 +- .../__snapshots__/filter_bar.test.tsx.snap | 8 -- .../functional/__tests__/filter_bar.test.tsx | 33 ++++++--- .../components/functional/filter_bar.tsx | 12 +-- .../uptime/public/queries/filter_bar_query.ts | 6 +- .../server/graphql/monitors/schema.gql.ts | 4 +- .../elasticsearch_monitors_adapter.ts | 74 +++++-------------- .../apis/uptime/graphql/filter_bar.js | 5 +- .../uptime/graphql/fixtures/filter_list.json | 46 ++++++++---- 10 files changed, 105 insertions(+), 105 deletions(-) diff --git a/x-pack/legacy/plugins/uptime/common/graphql/introspection.json b/x-pack/legacy/plugins/uptime/common/graphql/introspection.json index 375ae090ae0d51..26fb47ef93df10 100644 --- a/x-pack/legacy/plugins/uptime/common/graphql/introspection.json +++ b/x-pack/legacy/plugins/uptime/common/graphql/introspection.json @@ -2427,7 +2427,7 @@ "ofType": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "MonitorKey", "ofType": null } + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } } }, "isDeprecated": false, @@ -2512,6 +2512,22 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "urls", + "description": "The list of URLs", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, diff --git a/x-pack/legacy/plugins/uptime/common/graphql/types.ts b/x-pack/legacy/plugins/uptime/common/graphql/types.ts index 3c8a3ed12406ea..7f0b33ebe383f2 100644 --- a/x-pack/legacy/plugins/uptime/common/graphql/types.ts +++ b/x-pack/legacy/plugins/uptime/common/graphql/types.ts @@ -461,7 +461,7 @@ export interface StatusData { /** The data used to enrich the filter bar. */ export interface FilterBar { /** A series of monitor IDs in the heartbeat indices. */ - ids?: MonitorKey[] | null; + ids?: string[] | null; /** The location values users have configured for the agents. */ locations?: string[] | null; /** The names users have configured for the monitors. */ @@ -472,6 +472,8 @@ export interface FilterBar { schemes?: string[] | null; /** The possible status values contained in the indices. */ statuses?: string[] | null; + /** The list of URLs */ + urls?: string[] | null; } /** A representation of an error state for a monitor. */ export interface ErrorListItem { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/filter_bar.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/filter_bar.test.tsx.snap index f7358d0b753dbe..eea9c5c049d248 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/filter_bar.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/filter_bar.test.tsx.snap @@ -137,10 +137,6 @@ exports[`FilterBar component renders the component without errors 1`] = ` "value": "https://www.wikipedia.org/", "view": "https://www.wikipedia.org/", }, - Object { - "value": "https://news.google.com/", - "view": "https://news.google.com/", - }, ], "searchThreshold": 2, "type": "field_value_selection", @@ -350,10 +346,6 @@ exports[`FilterBar component renders the component's error state when an error p "value": "https://www.wikipedia.org/", "view": "https://www.wikipedia.org/", }, - Object { - "value": "https://news.google.com/", - "view": "https://news.google.com/", - }, ], "searchThreshold": 2, "type": "field_value_selection", diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/filter_bar.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/filter_bar.test.tsx index 2b68e7ebf8c01f..bf22e483690d63 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/filter_bar.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/filter_bar.test.tsx @@ -9,23 +9,34 @@ import { shallowWithIntl } from 'test_utils/enzyme_helpers'; import { FilterBarComponent as FilterBar } from '../filter_bar'; describe('FilterBar component', () => { - const data = { + const data: any = { filterBar: { ports: [9200, 12349], ids: [ - { key: 'auto-tcp-0X81440A68E839814C', url: 'tcp://localhost:9200' }, - { key: 'auto-http-0X3675F89EF0612091', url: 'http://localhost:12349/' }, - { key: 'auto-http-0X970CBD2F2102BFA8', url: 'http://www.google.com/' }, - { key: 'auto-http-0X131221E73F825974', url: 'https://www.google.com/' }, - { key: 'auto-http-0X9CB71300ABD5A2A8', url: 'https://www.github.com/' }, - { key: 'auto-http-0XD9AE729FC1C1E04A', url: 'http://www.reddit.com/' }, - { key: 'auto-http-0XDD2D4E60FD4A61C3', url: 'https://www.elastic.co' }, - { key: 'auto-http-0XA8096548ECEB85B7', url: 'http://www.example.com/' }, - { key: 'auto-http-0XC9CDA429418EDC2B', url: 'https://www.wikipedia.org/' }, - { key: 'auto-http-0XE3B163481423197D', url: 'https://news.google.com/' }, + 'auto-tcp-0X81440A68E839814C', + 'auto-http-0X3675F89EF0612091', + 'auto-http-0X970CBD2F2102BFA8', + 'auto-http-0X131221E73F825974', + 'auto-http-0X9CB71300ABD5A2A8', + 'auto-http-0XD9AE729FC1C1E04A', + 'auto-http-0XDD2D4E60FD4A61C3', + 'auto-http-0XA8096548ECEB85B7', + 'auto-http-0XC9CDA429418EDC2B', + 'auto-http-0XE3B163481423197D', ], names: [], schemes: ['tcp', 'http'], + urls: [ + 'tcp://localhost:9200', + 'http://localhost:12349/', + 'http://www.google.com/', + 'https://www.google.com/', + 'https://www.github.com/', + 'http://www.reddit.com/', + 'https://www.elastic.co', + 'http://www.example.com/', + 'https://www.wikipedia.org/', + ], }, }; let currentQuery; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_bar.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/filter_bar.tsx index 2c9829431a88e8..9b03111c8ba863 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/filter_bar.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/filter_bar.tsx @@ -16,7 +16,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; -import { FilterBar as FilterBarType, MonitorKey } from '../../../common/graphql/types'; +import { FilterBar as FilterBarType } from '../../../common/graphql/types'; import { UptimeSearchBarQueryChangeHandler } from '../../pages/overview'; import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../higher_order'; import { filterBarQuery } from '../../queries'; @@ -42,7 +42,7 @@ export const FilterBarComponent = ({ currentQuery, data, error, updateQuery }: P return ; } const { - filterBar: { ids, locations, names, ports, schemes }, + filterBar: { ids, locations, names, ports, schemes, urls }, } = data; // TODO: add a factory function + type for these filter options const filters = [ @@ -82,9 +82,9 @@ export const FilterBarComponent = ({ currentQuery, data, error, updateQuery }: P }), multiSelect: false, options: ids - ? ids.map(({ key }: MonitorKey) => ({ - value: key, - view: key, + ? ids.map((id: string) => ({ + value: id, + view: id, })) : [], searchThreshold: SEARCH_THRESHOLD, @@ -108,7 +108,7 @@ export const FilterBarComponent = ({ currentQuery, data, error, updateQuery }: P defaultMessage: 'URL', }), multiSelect: false, - options: ids ? ids.map(({ url }: MonitorKey) => ({ value: url, view: url })) : [], + options: urls ? urls.map((url: string) => ({ value: url, view: url })) : [], searchThreshold: SEARCH_THRESHOLD, }, { diff --git a/x-pack/legacy/plugins/uptime/public/queries/filter_bar_query.ts b/x-pack/legacy/plugins/uptime/public/queries/filter_bar_query.ts index 0df2f9357b889a..cd844228a45981 100644 --- a/x-pack/legacy/plugins/uptime/public/queries/filter_bar_query.ts +++ b/x-pack/legacy/plugins/uptime/public/queries/filter_bar_query.ts @@ -9,14 +9,12 @@ import gql from 'graphql-tag'; export const filterBarQueryString = ` query FilterBar($dateRangeStart: String!, $dateRangeEnd: String!) { filterBar: getFilterBar(dateRangeStart: $dateRangeStart, dateRangeEnd: $dateRangeEnd) { - ids { - key - url - } + ids locations names ports schemes + urls } } `; diff --git a/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts b/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts index d2a07f68bc8417..e039ddd5060395 100644 --- a/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts +++ b/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts @@ -10,7 +10,7 @@ export const monitorsSchema = gql` "The data used to enrich the filter bar." type FilterBar { "A series of monitor IDs in the heartbeat indices." - ids: [MonitorKey!] + ids: [String!] "The location values users have configured for the agents." locations: [String!] "The names users have configured for the monitors." @@ -21,6 +21,8 @@ export const monitorsSchema = gql` schemes: [String!] "The possible status values contained in the indices." statuses: [String!] + "The list of URLs" + urls: [String!] } type HistogramDataPoint { diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts index 4e2dba61859e57..417757498eb59b 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts @@ -11,7 +11,6 @@ import { FilterBar, LatestMonitor, MonitorChart, - MonitorKey, MonitorPageTitle, MonitorSeriesPoint, Ping, @@ -436,18 +435,17 @@ export class ElasticsearchMonitorsAdapter implements UMMonitorsAdapter { dateRangeStart: string, dateRangeEnd: string ): Promise { + const fields: { [key: string]: string } = { + ids: 'monitor.id', + schemes: 'monitor.type', + urls: 'url.full', + ports: 'url.port', + locations: 'observer.geo.name', + }; const params = { index: INDEX_NAMES.HEARTBEAT, body: { - _source: [ - 'monitor.id', - 'monitor.type', - 'url.full', - 'url.port', - 'monitor.name', - 'observer.geo.name', - ], - size: 1000, + size: 0, query: { range: { '@timestamp': { @@ -456,55 +454,19 @@ export class ElasticsearchMonitorsAdapter implements UMMonitorsAdapter { }, }, }, - collapse: { - field: 'monitor.id', - }, - sort: { - '@timestamp': 'desc', - }, + aggs: Object.values(fields).reduce((acc: { [key: string]: any }, field) => { + acc[field] = { terms: { field, size: 20 } }; + return acc; + }, {}), }, }; - const result = await this.database.search(request, params); - const ids: MonitorKey[] = []; - const ports = new Set(); - const types = new Set(); - const names = new Set(); - const locations = new Set(); - - const hits = get(result, 'hits.hits', []); - hits.forEach((hit: any) => { - const key: string = get(hit, '_source.monitor.id'); - const url: string | null = get(hit, '_source.url.full', null); - const port: number | undefined = get(hit, '_source.url.port', undefined); - const type: string | undefined = get(hit, '_source.monitor.type', undefined); - const name: string | null = get(hit, '_source.monitor.name', null); - const location: string | null = get(hit, '_source.observer.geo.name', null); - - if (key) { - ids.push({ key, url }); - } - if (port) { - ports.add(port); - } - if (type) { - types.add(type); - } - if (name) { - names.add(name); - } - if (location) { - locations.add(location); - } - }); + const { aggregations } = await this.database.search(request, params); - return { - ids, - locations: Array.from(locations), - names: Array.from(names), - ports: Array.from(ports), - schemes: Array.from(types), - statuses: ['up', 'down'], - }; + return Object.keys(fields).reduce((acc: { [key: string]: any[] }, field) => { + const bucketName = fields[field]; + acc[field] = aggregations[bucketName].buckets.map((b: { key: string | number }) => b.key); + return acc; + }, {}); } /** diff --git a/x-pack/test/api_integration/apis/uptime/graphql/filter_bar.js b/x-pack/test/api_integration/apis/uptime/graphql/filter_bar.js index 4144219a5acc34..bcbee57b9fdc51 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/filter_bar.js +++ b/x-pack/test/api_integration/apis/uptime/graphql/filter_bar.js @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; +import { expectFixtureEql } from './expect_fixture_eql'; import { filterBarQueryString } from '../../../../../legacy/plugins/uptime/public/queries'; -import filterList from './fixtures/filter_list'; export default function ({ getService }) { describe('filterBar query', () => { @@ -27,7 +26,7 @@ export default function ({ getService }) { .post('/api/uptime/graphql') .set('kbn-xsrf', 'foo') .send({ ...getFilterBarQuery }); - expect(data).to.eql(filterList); + expectFixtureEql(data, 'filter_list'); }); }); } diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/filter_list.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/filter_list.json index 76f72cf581e416..3e1e7b32b28fb1 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/filter_list.json +++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/filter_list.json @@ -1,20 +1,38 @@ { "filterBar": { "ids": [ - { "key": "auto-tcp-0X81440A68E839814C", "url": "tcp://localhost:9200" }, - { "key": "auto-http-0X3675F89EF0612091", "url": "http://localhost:12349/" }, - { "key": "auto-http-0X970CBD2F2102BFA8", "url": "http://www.google.com/" }, - { "key": "auto-http-0X131221E73F825974", "url": "https://www.google.com/" }, - { "key": "auto-http-0X9CB71300ABD5A2A8", "url": "https://www.github.com/" }, - { "key": "auto-http-0XD9AE729FC1C1E04A", "url": "http://www.reddit.com/" }, - { "key": "auto-http-0XDD2D4E60FD4A61C3", "url": "https://www.elastic.co" }, - { "key": "auto-http-0XA8096548ECEB85B7", "url": "http://www.example.com/" }, - { "key": "auto-http-0XC9CDA429418EDC2B", "url": "https://www.wikipedia.org/" }, - { "key": "auto-http-0XE3B163481423197D", "url": "https://news.google.com/" } + "auto-tcp-0X81440A68E839814C", + "auto-http-0XD9AE729FC1C1E04A", + "auto-http-0XDD2D4E60FD4A61C3", + "auto-http-0X3675F89EF0612091", + "auto-http-0X131221E73F825974", + "auto-http-0X9CB71300ABD5A2A8", + "auto-http-0X970CBD2F2102BFA8", + "auto-http-0XA8096548ECEB85B7", + "auto-http-0XC9CDA429418EDC2B", + "auto-http-0XE3B163481423197D" ], "locations": [], - "names": [], - "ports": [9200, 12349], - "schemes": ["tcp", "http"] + "names": null, + "ports": [ + 9200, + 12349 + ], + "schemes": [ + "http", + "tcp" + ], + "urls": [ + "tcp://localhost:9200", + "http://www.reddit.com/", + "https://www.elastic.co", + "http://localhost:12349/", + "https://www.google.com/", + "https://www.github.com/", + "http://www.google.com/", + "http://www.example.com/", + "https://news.google.com/", + "https://www.wikipedia.org/" + ] } -} +} \ No newline at end of file