From f9bdf890ba85de33f136e6777cd905c133694ef0 Mon Sep 17 00:00:00 2001
From: "dave.snider@gmail.com"
Date: Thu, 4 Apr 2019 10:26:22 -0700
Subject: [PATCH] Design cleanup of Uptime app (#31663)
* uptime design cleanup
* uptime design cleanup
* test
* errorlist now styled
* errorlist now styled
* errorlist now styled
* cleanup
* replace color vars with correct naming
* some titles
* more cleanup
* clean up silly gray graph
* Address problems with UI update.
* Refresh jest snapshots.
* Fix busted types.
* Refresh jest snapshots broken by busted type fix.
* Rename duplicate localization key.
* Use same curve type for both check series on monitors page.
* Remove unused translations.
* Display name instead of ID in ErrorList component.
* Update x-pack/plugins/uptime/public/components/functional/ping_list.tsx
Co-Authored-By: snide
* Update x-pack/plugins/uptime/public/components/functional/ping_list.tsx
Co-Authored-By: snide
* Modify updated code to avoid flooding console log with errors.
* Get functional and unit tests passing.
* Fix busted unit test.
* Update jest snapshots.
* Add panel to empty state.
* Avoid rendering monitor list sparkline charts when downSeries has no values.
* Remove crosshair synchronization from monitor charts because of display bug. Provide default 0 value to series for check chart.
* Fix broken snapshot.
* Update monitor list and errors list to handle simple_query_string filters.
* Make FilterBar component incremental to avoid overwriting queries that are in progress of being edited.
* Update histogram query to support simple_text_query.
* Delete hardcoded height prop that was breaking UI in mobile-sized windows.
* Fix bug in check histogram function and add tests.
* Update API tests and functional UI tests.
* Fix type error in test file.
* Last few fixes
- Center empty prompt
- remove crosshairs from sparkline
- reconcile styles of text in table
* Update snaps
* WIP.
* Update snapshot query to avoid Apollo Query class and allow manual fetching.
* Update SnapshotLoading component to better reflect the actual shape of the Snapshot component.
* Introduce HOC to manage GraphQL querying.
* Remove unneeded code.
* Update monitor page query components to use new query paradigm.
* Remove remaining references to apollo query component.
* Update filter bar snapshot.
* Update empty state.
* Fix busted type in test.
* Update schema type to avoid server error.
* Remove obsolete translations.
* Remove more obsolete translations.
* Remove obsolete code from Snapshot component. Rewrite graphql HOC with hooks.
* Change loading state condition for filter bar.
* Simplify app refresh process.
* Update loading state for several components to avoid unnecessary renders.
* Add default sort order for getAll pings function.
* Add translation to bare UI string.
* Update API fixtures to handle new default sort direction.
* Fix type errors.
* Remove unused import.
* Change the way component passes children prop.
* Fix typing error.
---
.../translations/translations/zh-CN.json | 20 -
.../plugins/uptime/common/constants/index.ts | 1 +
.../plugins/uptime/common/constants/query.ts | 24 +
.../uptime/common/graphql/introspection.json | 22 +-
x-pack/plugins/uptime/common/graphql/types.ts | 8 +-
x-pack/plugins/uptime/public/breadcrumbs.ts | 12 +-
.../__snapshots__/error_list.test.tsx.snap | 185 +-
.../__snapshots__/filter_bar.test.tsx.snap | 384 +--
.../monitor_charts.test.tsx.snap | 116 +-
.../__snapshots__/monitor_list.test.tsx.snap | 2481 ++++++++---------
.../monitor_sparkline.test.tsx.snap | 43 +
.../__snapshots__/ping_list.test.tsx.snap | 160 +-
.../__snapshots__/snapshot.test.tsx.snap | 152 +-
.../snapshot_histogram.test.tsx.snap | 54 +-
.../functional/__tests__/error_list.test.tsx | 4 +
.../__tests__/format_sparkline_counts.test.ts | 5 +-
.../__tests__/monitor_charts.test.tsx | 7 +-
.../__tests__/monitor_list.test.tsx | 2 +-
.../__tests__/monitor_sparkline.test.tsx | 75 +
.../functional/__tests__/ping_list.test.tsx | 2 -
.../functional/__tests__/snapshot.test.tsx | 7 +-
.../__tests__/snapshot_histogram.test.tsx | 3 +-
.../__snapshots__/empty_state.test.tsx.snap | 713 +++--
.../__tests__/empty_state.test.tsx | 6 +-
.../functional/empty_state/empty_index.tsx | 88 +-
.../functional/empty_state/empty_state.tsx | 18 +-
.../empty_state/empty_state_error.tsx | 28 +-
.../empty_state/empty_state_loading.tsx | 39 +-
.../components/functional/error_list.tsx | 140 +-
.../components/functional/filter_bar.tsx | 35 +-
.../functional/format_sparkline_counts.ts | 15 +-
.../components/functional/monitor_charts.tsx | 74 +-
.../components/functional/monitor_list.tsx | 168 +-
.../functional/monitor_page_title.tsx | 17 +-
.../functional/monitor_sparkline.tsx | 54 +
.../components/functional/ping_list.tsx | 135 +-
.../public/components/functional/snapshot.tsx | 122 +-
.../functional/snapshot_histogram.tsx | 25 +-
.../functional/snapshot_loading.tsx | 90 +-
.../public/components/higher_order/index.ts | 7 +
.../higher_order/uptime_graphql_query.tsx | 61 +
.../queries/empty_state/empty_state_query.tsx | 61 +-
.../queries/error_list/error_list_query.tsx | 41 +-
.../queries/error_list/get_error_list.ts | 1 +
.../queries/filter_bar/filter_bar_query.tsx | 52 +-
.../monitor_charts/get_monitor_charts.ts | 2 +-
.../monitor_charts/monitor_charts_query.tsx | 90 +-
.../monitor_list/monitor_list_query.tsx | 59 +-
.../get_monitor_page_title.ts | 2 +-
.../monitor_page_title_query.tsx | 46 +-
.../monitor_status_bar_query.tsx | 87 +-
.../queries/ping_list/ping_list_query.tsx | 101 +-
.../queries/snapshot/snapshot_query.tsx | 82 +-
.../framework/kibana_framework_adapter.ts | 4 +-
.../format_error_string.test.ts.snap | 7 +
.../__test__/format_error_string.test.ts | 41 +
.../public/lib/helper/format_error_list.ts | 20 +
.../plugins/uptime/public/pages/monitor.tsx | 99 +-
.../plugins/uptime/public/pages/overview.tsx | 63 +-
x-pack/plugins/uptime/public/uptime_app.tsx | 135 +-
.../server/graphql/monitors/schema.gql.ts | 5 +-
.../uptime/server/graphql/pings/schema.gql.ts | 2 +-
.../elasticsearch_monitors_adapter.ts | 2 +
.../elasticsearch_pings_adapter.test.ts.snap | 82 +
.../elasticsearch_pings_adapter.test.ts | 301 +-
.../pings/elasticsearch_pings_adapter.ts | 17 +-
...get_filtered_query_and_status.test.ts.snap | 37 +
.../get_filtered_query_and_status.test.ts | 6 +
.../server/lib/helper/get_filtered_query.ts | 12 +-
.../helper/get_filtered_query_and_status.ts | 9 +-
.../apis/uptime/get_all_pings.js | 4 +-
.../apis/uptime/graphql/error_list.js | 2 +-
.../uptime/graphql/fixtures/error_list.json | 12 +-
.../fixtures/error_list_filtered_by_id.json | 3 +-
.../fixtures/error_list_filtered_by_port.json | 3 +-
.../error_list_filtered_by_port_and_type.json | 3 +-
.../uptime/graphql/fixtures/ping_list.json | 124 +-
.../graphql/fixtures/ping_list_count.json | 594 ++--
.../fixtures/ping_list_monitor_id.json | 158 +-
.../fixtures/snapshot_filtered_by_up.json | 6 +-
x-pack/test/functional/apps/uptime/monitor.ts | 3 +-
.../test/functional/apps/uptime/overview.ts | 1 +
.../functional/page_objects/uptime_page.ts | 6 +-
83 files changed, 4256 insertions(+), 3731 deletions(-)
create mode 100644 x-pack/plugins/uptime/common/constants/query.ts
create mode 100644 x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_sparkline.test.tsx.snap
create mode 100644 x-pack/plugins/uptime/public/components/functional/__tests__/monitor_sparkline.test.tsx
create mode 100644 x-pack/plugins/uptime/public/components/functional/monitor_sparkline.tsx
create mode 100644 x-pack/plugins/uptime/public/components/higher_order/index.ts
create mode 100644 x-pack/plugins/uptime/public/components/higher_order/uptime_graphql_query.tsx
create mode 100644 x-pack/plugins/uptime/public/lib/helper/__test__/__snapshots__/format_error_string.test.ts.snap
create mode 100644 x-pack/plugins/uptime/public/lib/helper/__test__/format_error_string.test.ts
create mode 100644 x-pack/plugins/uptime/public/lib/helper/format_error_list.ts
create mode 100644 x-pack/plugins/uptime/server/lib/adapters/pings/__tests__/__snapshots__/elasticsearch_pings_adapter.test.ts.snap
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 1c8103b49f848..e6bdf194019ca 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -7789,52 +7789,36 @@
"xpack.upgradeAssistant.tabs.incompleteCallout.calloutBody.breackingChangesDocButtonLabel": "弃用内容和重大更改",
"xpack.upgradeAssistant.tabs.incompleteCallout.calloutBody.calloutDetail": "Elasticsearch {nextEsVersion} 中的 {breakingChangesDocButton} 完整列表将在最终的 {currentEsVersion} 次要版本中提供。完成列表后,此警告将消失。",
"xpack.upgradeAssistant.tabs.incompleteCallout.calloutTitle": "问题列表可能不完整",
- "xpack.uptime.appHeader.uptimeLogoAriaLabel": "前往运行时间主页",
- "xpack.uptime.appHeader.uptimeLogoText": "运行时间",
- "xpack.uptime.appHeader.uptimeLogoTitle": "运行时间",
- "xpack.uptime.breadcrumbs.monitorBreadcrumbText": "监测",
"xpack.uptime.breadcrumbs.overviewBreadcrumbText": "概览",
"xpack.uptime.emptyState.configureHeartbeatLinkText": "配置 Heartbeat",
"xpack.uptime.emptyState.configureHeartbeatToGetStartedMessage": "{configureHeartbeatLink} 以开始记录运行时间数据。",
- "xpack.uptime.emptyState.errorMessage": "错误 {message}",
"xpack.uptime.emptyState.loadingMessage": "正在加载……",
"xpack.uptime.emptyState.noDataTitle": "没有运行时间数据",
"xpack.uptime.errorList.CountColumnLabel": "计数",
- "xpack.uptime.errorList.errorMessage": "错误 {message}",
"xpack.uptime.errorList.errorTypeColumnLabel": "错误类型",
- "xpack.uptime.errorList.latestErrorColumnLabel": "最新错误",
"xpack.uptime.errorList.latestMessageColumnLabel": "最新消息",
"xpack.uptime.errorList.monitorIdColumnLabel": "监测 ID",
"xpack.uptime.errorList.statusCodeColumnLabel": "状态代码",
"xpack.uptime.errorList.title": "错误列表",
"xpack.uptime.featureCatalogueDescription": "执行终端节点运行状况检查和运行时间监测。",
- "xpack.uptime.filterBar.errorMessage": "错误 {message}",
"xpack.uptime.filterBar.filterDownLabel": "关闭",
"xpack.uptime.filterBar.filterUpLabel": "运行",
"xpack.uptime.filterBar.loadingMessage": "正在加载……",
"xpack.uptime.filterBar.options.portLabel": "端口",
- "xpack.uptime.header.helpLinkAriaLabel": "前往我们的讨论页",
- "xpack.uptime.header.helpLinkText": "讨论",
"xpack.uptime.monitorCharts.checkStatus.series.downCountLabel": "关闭计数",
"xpack.uptime.monitorCharts.checkStatus.series.upCountLabel": "运行计数",
"xpack.uptime.monitorCharts.checkStatus.title": "检查状态",
- "xpack.uptime.monitorCharts.errorMessage": "错误 {message}",
"xpack.uptime.monitorCharts.loadingMessage": "正在加载……",
"xpack.uptime.monitorCharts.monitorDuration.series.durationRangeLabel": "持续时间范围",
"xpack.uptime.monitorCharts.monitorDuration.series.meanDurationLabel": "平均持续时间",
"xpack.uptime.monitorCharts.monitorDuration.titleLabel": "监测持续时间 (ms)",
"xpack.uptime.monitorList.downLineSeries.downLabel": "关闭",
- "xpack.uptime.monitorList.errorMessage": "错误 {message}",
- "xpack.uptime.monitorList.ipColumnLabel": "IP",
- "xpack.uptime.monitorList.lastUpdatedColumnLabel": "最后更新时间:1/23/2016",
"xpack.uptime.monitorList.monitorHistoryColumnLabel": "监测历史记录",
"xpack.uptime.monitorList.monitoringStatusTitle": "检测状态",
"xpack.uptime.monitorList.statusColumn.downLabel": "关闭",
"xpack.uptime.monitorList.statusColumn.upLabel": "运行",
"xpack.uptime.monitorList.statusColumnLabel": "状态",
- "xpack.uptime.monitorList.upLineSeries.upLabel": "运行",
"xpack.uptime.monitorStatusBar.durationTextAriaLabel": "监测持续时间(毫秒)",
- "xpack.uptime.monitorStatusBar.errorMessage": "错误 {message}",
"xpack.uptime.monitorStatusBar.healthStatus.durationInMillisecondsMessage": "{duration}ms",
"xpack.uptime.monitorStatusBar.healthStatusMessage.downLabel": "关闭",
"xpack.uptime.monitorStatusBar.healthStatusMessage.upLabel": "运行",
@@ -7843,10 +7827,8 @@
"xpack.uptime.pingList.checkHistoryTitle": "检查历史记录",
"xpack.uptime.pingList.columns.errorMessageTooltipTitle": "错误消息",
"xpack.uptime.pingList.durationMsColumnLabel": "持续时间 (ms)",
- "xpack.uptime.pingList.errorMessage": "错误 {message}",
"xpack.uptime.pingList.errorMessageColumnLabel": "错误消息",
"xpack.uptime.pingList.errorTypeColumnLabel": "错误类型",
- "xpack.uptime.pingList.idColumnLabel": "ID",
"xpack.uptime.pingList.ipAddressColumnLabel": "IP",
"xpack.uptime.pingList.responseCodeColumnLabel": "响应代码",
"xpack.uptime.pingList.statusColumnHealthDownLabel": "关闭",
@@ -7856,10 +7838,8 @@
"xpack.uptime.pingList.statusOptions.allStatusOptionLabel": "全部",
"xpack.uptime.pingList.statusOptions.downStatusOptionLabel": "关闭",
"xpack.uptime.pingList.statusOptions.upStatusOptionLabel": "运行",
- "xpack.uptime.pingList.timestampColumnLabel": "时间戳",
"xpack.uptime.pluginDescription": "运行时间监测",
"xpack.uptime.snapshot.endpointStatusTitle": "终端节点状态",
- "xpack.uptime.snapshot.errorMessage": "错误 {message}",
"xpack.uptime.snapshot.noDataDescription": "抱歉,没有可用于该直方图的数据",
"xpack.uptime.snapshot.noDataTitle": "没有可用的直方图数据",
"xpack.uptime.snapshot.stats.downDescription": "关闭",
diff --git a/x-pack/plugins/uptime/common/constants/index.ts b/x-pack/plugins/uptime/common/constants/index.ts
index da3cf73059c17..5a421651eb7ac 100644
--- a/x-pack/plugins/uptime/common/constants/index.ts
+++ b/x-pack/plugins/uptime/common/constants/index.ts
@@ -6,3 +6,4 @@
export { INDEX_NAMES } from './index_names';
export { PLUGIN } from './plugin';
+export { QUERY } from './query';
diff --git a/x-pack/plugins/uptime/common/constants/query.ts b/x-pack/plugins/uptime/common/constants/query.ts
new file mode 100644
index 0000000000000..8021d0cc0da60
--- /dev/null
+++ b/x-pack/plugins/uptime/common/constants/query.ts
@@ -0,0 +1,24 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+/**
+ * These are the fields that will be used when users enter simple_query_string
+ * searches into the FilterBar component.
+ */
+export const QUERY = {
+ SIMPLE_QUERY_STRING_FIELDS: [
+ 'monitor.id',
+ 'monitor.url',
+ 'monitor.type',
+ 'monitor.status',
+ 'monitor.name',
+ 'url.full',
+ 'url.path',
+ 'url.scheme',
+ 'url.domain',
+ 'error.type',
+ ],
+};
diff --git a/x-pack/plugins/uptime/common/graphql/introspection.json b/x-pack/plugins/uptime/common/graphql/introspection.json
index 59428b55e6fbd..38f17e6343a78 100644
--- a/x-pack/plugins/uptime/common/graphql/introspection.json
+++ b/x-pack/plugins/uptime/common/graphql/introspection.json
@@ -425,7 +425,7 @@
"name": "millisFromNow",
"description": "Milliseconds from the timestamp to the current time",
"args": [],
- "type": { "kind": "SCALAR", "name": "Int", "ofType": null },
+ "type": { "kind": "SCALAR", "name": "UnsignedInteger", "ofType": null },
"isDeprecated": false,
"deprecationReason": null
},
@@ -1600,7 +1600,11 @@
"type": {
"kind": "LIST",
"name": null,
- "ofType": { "kind": "OBJECT", "name": "MonitorSeriesPoint", "ofType": null }
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "OBJECT", "name": "MonitorSeriesPoint", "ofType": null }
+ }
},
"isDeprecated": false,
"deprecationReason": null
@@ -1612,7 +1616,11 @@
"type": {
"kind": "LIST",
"name": null,
- "ofType": { "kind": "OBJECT", "name": "MonitorSeriesPoint", "ofType": null }
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "OBJECT", "name": "MonitorSeriesPoint", "ofType": null }
+ }
},
"isDeprecated": false,
"deprecationReason": null
@@ -2160,6 +2168,14 @@
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "",
+ "args": [],
+ "type": { "kind": "SCALAR", "name": "String", "ofType": null },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
diff --git a/x-pack/plugins/uptime/common/graphql/types.ts b/x-pack/plugins/uptime/common/graphql/types.ts
index 07b44eafb3d98..a4a531f2894b7 100644
--- a/x-pack/plugins/uptime/common/graphql/types.ts
+++ b/x-pack/plugins/uptime/common/graphql/types.ts
@@ -45,7 +45,7 @@ export interface Ping {
/** The timestamp of the ping's creation */
timestamp: string;
/** Milliseconds from the timestamp to the current time */
- millisFromNow?: number | null;
+ millisFromNow?: UnsignedInteger | null;
/** The agent that recorded the ping */
beat?: Beat | null;
@@ -314,9 +314,9 @@ export interface LatestMonitor {
/** Information from the latest document. */
ping?: Ping | null;
/** Buckets of recent up count status data. */
- upSeries?: (MonitorSeriesPoint | null)[] | null;
+ upSeries?: MonitorSeriesPoint[] | null;
/** Buckets of recent down count status data. */
- downSeries?: (MonitorSeriesPoint | null)[] | null;
+ downSeries?: MonitorSeriesPoint[] | null;
}
export interface MonitorKey {
@@ -417,6 +417,8 @@ export interface ErrorListItem {
statusCode?: string | null;
timestamp?: string | null;
+
+ name?: string | null;
}
export interface MonitorPageTitle {
diff --git a/x-pack/plugins/uptime/public/breadcrumbs.ts b/x-pack/plugins/uptime/public/breadcrumbs.ts
index 9e7aba684c533..316163aec4e84 100644
--- a/x-pack/plugins/uptime/public/breadcrumbs.ts
+++ b/x-pack/plugins/uptime/public/breadcrumbs.ts
@@ -11,22 +11,16 @@ export interface UMBreadcrumb {
href?: string;
}
-export const monitorBreadcrumb: UMBreadcrumb = {
- text: i18n.translate('xpack.uptime.breadcrumbs.monitorBreadcrumbText', {
- defaultMessage: 'Monitor',
- }),
-};
-
export const overviewBreadcrumb: UMBreadcrumb = {
text: i18n.translate('xpack.uptime.breadcrumbs.overviewBreadcrumbText', {
- defaultMessage: 'Overview',
+ defaultMessage: 'Uptime',
}),
href: '#/',
};
export const getOverviewPageBreadcrumbs = (): UMBreadcrumb[] => [overviewBreadcrumb];
-export const getMonitorPageBreadcrumb = (): UMBreadcrumb[] => [
+export const getMonitorPageBreadcrumb = (name: string): UMBreadcrumb[] => [
overviewBreadcrumb,
- monitorBreadcrumb,
+ { text: name },
];
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/error_list.test.tsx.snap b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/error_list.test.tsx.snap
index da36de70ea46b..8f35b1e358a21 100644
--- a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/error_list.test.tsx.snap
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/error_list.test.tsx.snap
@@ -1,109 +1,110 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ErrorList component renders the error list without errors 1`] = `
-
+
-
-
-
-
+ }
+ responsive={true}
+ sorting={false}
+ />
+
`;
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/filter_bar.test.tsx.snap b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/filter_bar.test.tsx.snap
index 36ec82f063c28..59ae6d0494b2f 100644
--- a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/filter_bar.test.tsx.snap
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/filter_bar.test.tsx.snap
@@ -1,196 +1,196 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FilterBar component renders the component without errors 1`] = `
-
-
-
-
-
+
`;
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_charts.test.tsx.snap b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_charts.test.tsx.snap
index 66b72b4029fdc..65f9473168d07 100644
--- a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_charts.test.tsx.snap
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_charts.test.tsx.snap
@@ -2,43 +2,44 @@
exports[`MonitorCharts component renders the component without errors 1`] = `
-
+
-
-
-
-
-
+
+
+
+
+
@@ -175,41 +176,40 @@ exports[`MonitorCharts component renders the component without errors 1`] = `
-
-
-
-
-
+
+
+
+
+
+
-
-
+
-
-
+ }
+ responsive={true}
+ sorting={false}
+ />
+
`;
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_sparkline.test.tsx.snap b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_sparkline.test.tsx.snap
new file mode 100644
index 0000000000000..0134f2a523d8a
--- /dev/null
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_sparkline.test.tsx.snap
@@ -0,0 +1,43 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`MonitorSparkline component renders a series when there are down items 1`] = `
+
+
+
+`;
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/ping_list.test.tsx.snap b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/ping_list.test.tsx.snap
index 307bff663781e..58183d76e124a 100644
--- a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/ping_list.test.tsx.snap
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/ping_list.test.tsx.snap
@@ -2,78 +2,96 @@
exports[`PingList component renders sorted list without errors 1`] = `
-
-
-
-
-
-
-
-
-
-
- 9231
-
-
-
-
-
-
+
+
-
+
+
+
+
+
+
+
+
+ 9231
+
+
+
+
+
+
+
-
+ >
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot_histogram.test.tsx.snap b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot_histogram.test.tsx.snap
index fcb1b3f17264e..14498b5d4bd6e 100644
--- a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot_histogram.test.tsx.snap
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot_histogram.test.tsx.snap
@@ -2,137 +2,137 @@
exports[`SnapshotHistogram component renders the component without errors 1`] = `
`;
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/error_list.test.tsx b/x-pack/plugins/uptime/public/components/functional/__tests__/error_list.test.tsx
index b692c10dd4c12..086255165b35a 100644
--- a/x-pack/plugins/uptime/public/components/functional/__tests__/error_list.test.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/error_list.test.tsx
@@ -22,6 +22,7 @@ describe('ErrorList component', () => {
count: 843,
statusCode: null,
timestamp: '2019-01-28T18:43:15.077Z',
+ name: null,
},
{
latestMessage: 'dial tcp 127.0.0.1:9200: connect: connection refused',
@@ -30,6 +31,7 @@ describe('ErrorList component', () => {
count: 748,
statusCode: null,
timestamp: '2019-01-28T17:59:34.075Z',
+ name: null,
},
{
latestMessage: 'lookup www.reddit.com: no such host',
@@ -38,6 +40,7 @@ describe('ErrorList component', () => {
count: 1,
statusCode: null,
timestamp: '2019-01-28T18:03:10.077Z',
+ name: null,
},
{
latestMessage: 'received status code 301 expecting 200',
@@ -46,6 +49,7 @@ describe('ErrorList component', () => {
count: 645,
statusCode: '301',
timestamp: '2019-01-28T18:43:07.078Z',
+ name: null,
},
],
};
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/format_sparkline_counts.test.ts b/x-pack/plugins/uptime/public/components/functional/__tests__/format_sparkline_counts.test.ts
index f66342f8b5168..2a35b97de8941 100644
--- a/x-pack/plugins/uptime/public/components/functional/__tests__/format_sparkline_counts.test.ts
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/format_sparkline_counts.test.ts
@@ -4,10 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { formatSparklineCounts, PingCount } from '../format_sparkline_counts';
+import { MonitorSeriesPoint } from '../../../../common/graphql/types';
+import { formatSparklineCounts } from '../format_sparkline_counts';
describe('formatSparklineCounts', () => {
- let counts: PingCount[];
+ let counts: MonitorSeriesPoint[];
beforeEach(() => {
counts = [
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/monitor_charts.test.tsx b/x-pack/plugins/uptime/public/components/functional/__tests__/monitor_charts.test.tsx
index f78fb6e6a3d29..40500d037470d 100644
--- a/x-pack/plugins/uptime/public/components/functional/__tests__/monitor_charts.test.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/monitor_charts.test.tsx
@@ -61,9 +61,10 @@ describe('MonitorCharts component', () => {
checkDomainLimits={[0, 75]}
danger="dangerColor"
durationDomainLimits={[0, 75]}
- monitorChartData={chartResponse.monitorChartsData}
- primary="primaryColor"
- secondary="secondaryColor"
+ monitorChartsData={chartResponse.monitorChartsData}
+ mean="mean"
+ range="range"
+ success="success"
/>
);
expect(component).toMatchSnapshot();
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/monitor_list.test.tsx b/x-pack/plugins/uptime/public/components/functional/__tests__/monitor_list.test.tsx
index a0d5dc2e84f06..47b9c6a0f599e 100644
--- a/x-pack/plugins/uptime/public/components/functional/__tests__/monitor_list.test.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/monitor_list.test.tsx
@@ -443,8 +443,8 @@ describe('MonitorList component', () => {
const { monitors } = monitorResult;
const component = shallowWithIntl(
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/monitor_sparkline.test.tsx b/x-pack/plugins/uptime/public/components/functional/__tests__/monitor_sparkline.test.tsx
new file mode 100644
index 0000000000000..b2092d53d6e93
--- /dev/null
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/monitor_sparkline.test.tsx
@@ -0,0 +1,75 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { shallowWithIntl } from 'test_utils/enzyme_helpers';
+import { MonitorSparkline, MonitorSparklineProps } from '../monitor_sparkline';
+
+describe('MonitorSparkline component', () => {
+ let props: MonitorSparklineProps;
+ beforeEach(() => {
+ props = {
+ dangerColor: 'A danger color',
+ monitor: {
+ id: {
+ key: 'test',
+ url: null,
+ },
+ downSeries: [
+ {
+ x: 123,
+ y: 1,
+ },
+ {
+ x: 124,
+ y: 1,
+ },
+ {
+ x: 125,
+ y: 1,
+ },
+ ],
+ ping: null,
+ },
+ };
+ });
+
+ it('renders a series when there are down items', () => {
+ const component = shallowWithIntl( );
+ expect(component).toMatchSnapshot();
+ });
+
+ it('renders null when there are no down items', () => {
+ props.monitor.downSeries = [];
+ const component = shallowWithIntl( );
+ expect(component).toEqual({});
+ });
+
+ it('renders null when downSeries is null', () => {
+ props.monitor.downSeries = null;
+ const component = shallowWithIntl( );
+ expect(component).toEqual({});
+ });
+
+ it('renders nothing if the down count has no counts', () => {
+ props.monitor.downSeries = [
+ {
+ x: 123,
+ y: 0,
+ },
+ {
+ x: 124,
+ y: null,
+ },
+ {
+ x: 125,
+ y: 0,
+ },
+ ];
+ const component = shallowWithIntl( );
+ expect(component).toEqual({});
+ });
+});
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/ping_list.test.tsx b/x-pack/plugins/uptime/public/components/functional/__tests__/ping_list.test.tsx
index 8512cbf39034a..45dd32b4f33e4 100644
--- a/x-pack/plugins/uptime/public/components/functional/__tests__/ping_list.test.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/ping_list.test.tsx
@@ -190,9 +190,7 @@ describe('PingList component', () => {
const component = shallowWithIntl(
{
it('renders without errors', () => {
const wrapper = shallowWithIntl(
-
+
);
expect(wrapper).toMatchSnapshot();
});
diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/snapshot_histogram.test.tsx b/x-pack/plugins/uptime/public/components/functional/__tests__/snapshot_histogram.test.tsx
index db6d89874f659..cf6f80bd3ff3a 100644
--- a/x-pack/plugins/uptime/public/components/functional/__tests__/snapshot_histogram.test.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/__tests__/snapshot_histogram.test.tsx
@@ -10,9 +10,8 @@ import { SnapshotHistogram, SnapshotHistogramProps } from '../snapshot_histogram
describe('SnapshotHistogram component', () => {
const props: SnapshotHistogramProps = {
- primaryColor: '#FEFEFE',
+ successColor: '#FEFEFE',
dangerColor: '#FF00FF',
- windowWidth: 1200,
histogram: [
{ upCount: 7, downCount: 3, x: 1548697920000, x0: 1548697620000, y: 1 },
{ upCount: 7, downCount: 3, x: 1548698220000, x0: 1548697920000, y: 1 },
diff --git a/x-pack/plugins/uptime/public/components/functional/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap b/x-pack/plugins/uptime/public/components/functional/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap
index 512529d27691c..5e34e27990427 100644
--- a/x-pack/plugins/uptime/public/components/functional/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap
+++ b/x-pack/plugins/uptime/public/components/functional/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap
@@ -106,51 +106,25 @@ exports[`EmptyState component doesn't render child components when count is fals
}
}
>
-
+
-
-
-
- ,
- }
- }
- />
-
+
+
+
+
+ Loading…
+
+
}
iconColor="subdued"
- title={
-
-
-
-
-
- }
>
-
-
-
-
- No uptime data available
-
-
-
-
-
-
-
-
-
-
- ,
- }
- }
+
+
+
+
+
+
+
+
-
+ Loading…
+
+
-
+
`;
@@ -267,10 +189,10 @@ exports[`EmptyState component renders child components when count is truthy 1`]
`;
-exports[`EmptyState component renders empty state with appropriate base path 1`] = `
+exports[`EmptyState component renders children while loading 1`] = `
-
-
-
-
-
- ,
- }
- }
- />
-
-
- }
- iconColor="subdued"
- title={
-
-
-
-
-
- }
- >
-
-
-
-
-
-
-
- No uptime data available
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ Should appear even while loading...
+
`;
-exports[`EmptyState component renders message while loading 1`] = `
+exports[`EmptyState component renders empty state with appropriate base path 1`] = `
-
-
-
-
-
- Loading…
-
-
-
-
-
-
-
- }
+
+
-
-
-
-
+
+
+
-
+
+
+
+ ,
+ }
+ }
+ />
+
+
+ }
+ iconColor="subdued"
+ iconType="uptimeApp"
+ title={
+
+
+
+
+
+ }
>
-
-
+
-
-
- Loading…
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ No uptime data available
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
`;
+
exports[`EmptyState component renders the message when an error occurs 1`] = `
-
- An error occurred
-
- }
- iconColor="subdued"
- title={
-
-
- Error
-
-
- }
+
-
-
+
+ An error occurred
+
+ }
+ iconColor="subdued"
+ title={
-
-
- Error
-
-
+
+ Error
+
-
-
-
-
+
+
-
-
- An error occurred
-
-
-
-
-
+
+
+
+ Error
+
+
+
+
+
+
+
+
+
+ An error occurred
+
+
+
+
+
+
+
-
+
`;
diff --git a/x-pack/plugins/uptime/public/components/functional/empty_state/__tests__/empty_state.test.tsx b/x-pack/plugins/uptime/public/components/functional/empty_state/__tests__/empty_state.test.tsx
index 6be918dd63549..aeecb5bff4331 100644
--- a/x-pack/plugins/uptime/public/components/functional/empty_state/__tests__/empty_state.test.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/empty_state/__tests__/empty_state.test.tsx
@@ -21,7 +21,7 @@ describe('EmptyState component', () => {
});
it(`doesn't render child components when count is falsey`, () => {
const component = mountWithIntl(
-
+
Shouldn't be rendered
);
@@ -35,10 +35,10 @@ describe('EmptyState component', () => {
);
expect(component).toMatchSnapshot();
});
- it('renders message while loading', () => {
+ it('renders children while loading', () => {
const component = mountWithIntl(
- Shouldn't appear...
+ Should appear even while loading...
);
expect(component).toMatchSnapshot();
diff --git a/x-pack/plugins/uptime/public/components/functional/empty_state/empty_index.tsx b/x-pack/plugins/uptime/public/components/functional/empty_state/empty_index.tsx
index 8377f880c7c1d..0141198ec15e0 100644
--- a/x-pack/plugins/uptime/public/components/functional/empty_state/empty_index.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/empty_state/empty_index.tsx
@@ -4,7 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiEmptyPrompt, EuiLink, EuiTitle } from '@elastic/eui';
+import {
+ EuiEmptyPrompt,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiLink,
+ EuiPanel,
+ EuiSpacer,
+ EuiTitle,
+} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { Fragment } from 'react';
@@ -13,39 +21,47 @@ interface EmptyIndexProps {
}
export const EmptyIndex = ({ basePath }: EmptyIndexProps) => (
-
-
-
-
-
- }
- body={
-
-
-
-
-
- ),
- }}
- />
-
-
- }
- />
+
+
+
+
+
+
+
+
+
+ }
+ body={
+
+
+
+
+
+ ),
+ }}
+ />
+
+
+ }
+ />
+
+
+
);
diff --git a/x-pack/plugins/uptime/public/components/functional/empty_state/empty_state.tsx b/x-pack/plugins/uptime/public/components/functional/empty_state/empty_state.tsx
index 6f9c97de03955..746405f3f75bd 100644
--- a/x-pack/plugins/uptime/public/components/functional/empty_state/empty_state.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/empty_state/empty_state.tsx
@@ -12,7 +12,7 @@ import { EmptyStateLoading } from './empty_state_loading';
interface EmptyStateProps {
basePath: string;
children: JSX.Element[] | JSX.Element;
- count: number | undefined;
+ count?: number;
error?: string;
loading?: boolean;
}
@@ -21,10 +21,18 @@ export const EmptyState = ({ basePath, children, count, error, loading }: EmptyS
if (error) {
return ;
}
- if (loading) {
- return ;
- } else if (!count) {
+ /**
+ * We choose to render the children any time the count > 0, even if
+ * the component is loading. If we render the loading state for this component,
+ * it will blow away the state of child components and trigger an ugly
+ * jittery UX any time the components refresh. This way we'll keep the stale
+ * state displayed during the fetching process.
+ */
+ if (count) {
+ return {children} ;
+ }
+ if (count === 0) {
return ;
}
- return {children} ;
+ return ;
};
diff --git a/x-pack/plugins/uptime/public/components/functional/empty_state/empty_state_error.tsx b/x-pack/plugins/uptime/public/components/functional/empty_state/empty_state_error.tsx
index b410fa844bb35..d4c62ee336f6f 100644
--- a/x-pack/plugins/uptime/public/components/functional/empty_state/empty_state_error.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/empty_state/empty_state_error.tsx
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiEmptyPrompt, EuiTitle } from '@elastic/eui';
+import { EuiEmptyPrompt, EuiPanel, EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
@@ -13,16 +13,18 @@ interface EmptyStateErrorProps {
}
export const EmptyStateError = ({ errorMessage }: EmptyStateErrorProps) => (
-
-
- {i18n.translate('xpack.uptime.emptyStateError.title', {
- defaultMessage: 'Error',
- })}
-
-
- }
- body={{errorMessage ? errorMessage : ''}
}
- />
+
+
+
+ {i18n.translate('xpack.uptime.emptyStateError.title', {
+ defaultMessage: 'Error',
+ })}
+
+
+ }
+ body={{errorMessage ? errorMessage : ''}
}
+ />
+
);
diff --git a/x-pack/plugins/uptime/public/components/functional/empty_state/empty_state_loading.tsx b/x-pack/plugins/uptime/public/components/functional/empty_state/empty_state_loading.tsx
index 4c502ab469fea..3d6516d659429 100644
--- a/x-pack/plugins/uptime/public/components/functional/empty_state/empty_state_loading.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/empty_state/empty_state_loading.tsx
@@ -4,33 +4,24 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- EuiEmptyPrompt,
- EuiFlexGroup,
- EuiFlexItem,
- EuiLoadingSpinner,
- EuiTitle,
-} from '@elastic/eui';
+import { EuiEmptyPrompt, EuiLoadingSpinner, EuiSpacer, EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import React from 'react';
+import React, { Fragment } from 'react';
-export const EmptyStateLoading = (props: any) => (
+export const EmptyStateLoading = () => (
-
-
-
- {i18n.translate('xpack.uptime.emptyState.loadingMessage', {
- defaultMessage: 'Loading…',
- })}
-
-
-
-
-
-
-
+ body={
+
+
+
+
+
+ {i18n.translate('xpack.uptime.emptyState.loadingMessage', {
+ defaultMessage: 'Loading…',
+ })}
+
+
+
}
/>
);
diff --git a/x-pack/plugins/uptime/public/components/functional/error_list.tsx b/x-pack/plugins/uptime/public/components/functional/error_list.tsx
index 361515245f391..de549fe9fa137 100644
--- a/x-pack/plugins/uptime/public/components/functional/error_list.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/error_list.tsx
@@ -4,75 +4,101 @@
* you may not use this file except in compliance with the Elastic License.
*/
-// @ts-ignore missing typings
-import { EuiInMemoryTable, EuiPanel, EuiTitle } from '@elastic/eui';
+import {
+ EuiBadge,
+ EuiCodeBlock,
+ EuiInMemoryTable,
+ EuiLink,
+ EuiPanel,
+ EuiText,
+ EuiTextColor,
+ EuiTitle,
+} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import moment from 'moment';
-import React, { Fragment } from 'react';
+import React from 'react';
import { Link } from 'react-router-dom';
-import { ErrorListItem } from '../../../common/graphql/types';
+import { ErrorListItem, Ping } from '../../../common/graphql/types';
interface ErrorListProps {
loading: boolean;
- errorList: ErrorListItem[];
+ errorList?: ErrorListItem[];
}
export const ErrorList = ({ loading, errorList }: ErrorListProps) => (
-
+
-
+
-
- {id},
- width: '25%',
- },
- {
- field: 'count',
- name: i18n.translate('xpack.uptime.errorList.CountColumnLabel', {
- defaultMessage: 'Count',
- }),
- },
- {
- field: 'timestamp',
- name: i18n.translate('xpack.uptime.errorList.latestErrorColumnLabel', {
- defaultMessage: 'Latest error',
- }),
- render: (timestamp: string) => moment(timestamp).fromNow(),
- },
- {
- field: 'statusCode',
- name: i18n.translate('xpack.uptime.errorList.statusCodeColumnLabel', {
- defaultMessage: 'Status code',
- }),
- },
- {
- field: 'latestMessage',
- name: i18n.translate('xpack.uptime.errorList.latestMessageColumnLabel', {
- defaultMessage: 'Latest message',
- }),
- width: '40%',
- },
- ]}
- pagination={{ initialPageSize: 10, pageSizeOptions: [5, 10, 20, 50] }}
- />
-
-
+ (
+
+
+ {count} errors
+
+
+ Latest was {moment(item.timestamp).fromNow()}
+
+
+ ),
+ },
+ {
+ field: 'type',
+ name: i18n.translate('xpack.uptime.errorList.errorTypeColumnLabel', {
+ defaultMessage: 'Error type',
+ }),
+ },
+ {
+ field: 'monitorId',
+ name: i18n.translate('xpack.uptime.errorList.monitorIdColumnLabel', {
+ defaultMessage: 'Monitor ID',
+ }),
+ render: (id: string, { name }: ErrorListItem) => (
+
+ {name || id}
+
+ ),
+ width: '25%',
+ },
+ {
+ field: 'statusCode',
+ name: i18n.translate('xpack.uptime.errorList.statusCodeColumnLabel', {
+ defaultMessage: 'Status code',
+ }),
+ render: (statusCode: string) => (statusCode ? {statusCode} : null),
+ },
+ {
+ field: 'latestMessage',
+ name: i18n.translate('xpack.uptime.errorList.latestMessageColumnLabel', {
+ defaultMessage: 'Latest message',
+ }),
+ width: '40%',
+ render: (message: string) => (
+
+ {
+ // TODO: remove this ignore when prop is defined on type
+ // @ts-ignore size is not currently defined on the type for EuiCodeBlock
+
+ {message}
+
+ }
+
+ ),
+ },
+ ]}
+ pagination={{ initialPageSize: 10, pageSizeOptions: [5, 10, 20, 50] }}
+ />
+
);
diff --git a/x-pack/plugins/uptime/public/components/functional/filter_bar.tsx b/x-pack/plugins/uptime/public/components/functional/filter_bar.tsx
index b87437dd1301d..400992f7d3746 100644
--- a/x-pack/plugins/uptime/public/components/functional/filter_bar.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/filter_bar.tsx
@@ -5,20 +5,23 @@
*/
// @ts-ignore No typings for EuiSearchBar
-import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSearchBar, EuiToolTip } from '@elastic/eui';
+import { EuiIcon, EuiSearchBar, EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { FilterBar as FilterBarType, MonitorKey } from '../../../common/graphql/types';
+import { UptimeSearchBarQueryChangeHandler } from '../../pages/overview';
import { filterBarSearchSchema } from './search_schema';
interface FilterBarProps {
+ currentQuery?: object;
filterBar: FilterBarType;
- updateQuery: (query: object | undefined) => void;
+ updateQuery: UptimeSearchBarQueryChangeHandler;
}
const SEARCH_THRESHOLD = 2;
export const FilterBar = ({
+ currentQuery,
filterBar: { names, ports, ids, schemes },
updateQuery,
}: FilterBarProps) => {
@@ -112,25 +115,13 @@ export const FilterBar = ({
},
];
return (
-
-
- {
- try {
- let esQuery;
- if (query && query.text) {
- esQuery = EuiSearchBar.Query.toESQuery(query);
- }
- updateQuery(esQuery);
- } catch (e) {
- updateQuery(undefined);
- }
- }}
- filters={filters}
- schema={filterBarSearchSchema}
- />
-
-
+
);
};
diff --git a/x-pack/plugins/uptime/public/components/functional/format_sparkline_counts.ts b/x-pack/plugins/uptime/public/components/functional/format_sparkline_counts.ts
index 9f64150d6e6a7..2f1079afdac7b 100644
--- a/x-pack/plugins/uptime/public/components/functional/format_sparkline_counts.ts
+++ b/x-pack/plugins/uptime/public/components/functional/format_sparkline_counts.ts
@@ -4,23 +4,20 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export interface PingCount {
- x: number;
- y: number;
-}
+import { MonitorSeriesPoint } from '../../../common/graphql/types';
-export const formatSparklineCounts = (counts: PingCount[]) => {
+export const formatSparklineCounts = (seriesPoints: MonitorSeriesPoint[]) => {
let defaultSize = 0;
- const { length } = counts;
+ const { length } = seriesPoints;
// assume points are uniform, use this
// for the last element's span
if (length > 1) {
- defaultSize = Math.max(counts[1].x - counts[0].x, 0);
+ defaultSize = Math.max(seriesPoints[1].x - seriesPoints[0].x, 0);
} else if (length === 1) {
// wait for another point
return [];
}
- return counts.map(({ x: x0, y }, index, array) => {
+ return seriesPoints.map(({ x: x0, y: yVal }, index, array) => {
let x;
const nextIndex = index + 1;
if (nextIndex === array.length) {
@@ -29,6 +26,6 @@ export const formatSparklineCounts = (counts: PingCount[]) => {
const { x: nextX } = array[nextIndex];
x = nextX;
}
- return { x, x0, y };
+ return { x, x0, y: yVal || 0 };
});
};
diff --git a/x-pack/plugins/uptime/public/components/functional/monitor_charts.tsx b/x-pack/plugins/uptime/public/components/functional/monitor_charts.tsx
index a60d1034f474c..ad96917c70ba3 100644
--- a/x-pack/plugins/uptime/public/components/functional/monitor_charts.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/monitor_charts.tsx
@@ -31,42 +31,44 @@ interface MonitorChartsProps {
checkDomainLimits: number[];
danger: string;
durationDomainLimits: number[];
- monitorChartData: MonitorChart;
- primary: string;
- secondary: string;
+ monitorChartsData: MonitorChart;
+ mean: string;
+ range: string;
+ success: string;
}
export const MonitorCharts = ({
checkDomainLimits,
danger,
durationDomainLimits,
- monitorChartData: { durationArea, durationLine, status },
- primary,
- secondary,
+ monitorChartsData: { durationArea, durationLine, status },
+ mean,
+ range,
+ success,
}: MonitorChartsProps) => (
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
({ x, y: up }))}
- curve="curveBasis"
- color={primary}
+ data={status.map(({ x, up }) => ({ x, y: up || 0 }))}
+ color={success}
/>
({ x, y: down }))}
+ data={status.map(({ x, down }) => ({ x, y: down || 0 }))}
color={danger}
/>
diff --git a/x-pack/plugins/uptime/public/components/functional/monitor_list.tsx b/x-pack/plugins/uptime/public/components/functional/monitor_list.tsx
index c3238019b6ec9..0c1bd0a45886f 100644
--- a/x-pack/plugins/uptime/public/components/functional/monitor_list.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/monitor_list.tsx
@@ -8,6 +8,7 @@ import {
EuiHealth,
// @ts-ignore missing type definition
EuiHistogramSeries,
+ EuiIcon,
// @ts-ignore missing type definition
EuiInMemoryTable,
EuiLink,
@@ -16,18 +17,21 @@ import {
EuiSeriesChart,
// @ts-ignore missing type definition
EuiSeriesChartUtils,
+ EuiSpacer,
+ EuiText,
EuiTitle,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
+import { get } from 'lodash';
import moment from 'moment';
-import React, { Fragment } from 'react';
+import React from 'react';
import { Link } from 'react-router-dom';
-import { LatestMonitor } from '../../../common/graphql/types';
-import { formatSparklineCounts } from './format_sparkline_counts';
+import { LatestMonitor, MonitorSeriesPoint } from '../../../common/graphql/types';
+import { MonitorSparkline } from './monitor_sparkline';
interface MonitorListProps {
- primaryColor: string;
+ successColor: string;
dangerColor: string;
loading: boolean;
monitors: LatestMonitor[];
@@ -40,8 +44,8 @@ const monitorListPagination = {
pageSizeOptions: [5, 10, 20, 50],
};
-export const MonitorList = ({ dangerColor, loading, monitors, primaryColor }: MonitorListProps) => (
-
+export const MonitorList = ({ dangerColor, loading, monitors }: MonitorListProps) => (
+
-
- (
-
+
+ (
+
+
{status === 'up'
? i18n.translate('xpack.uptime.monitorList.statusColumn.upLabel', {
defaultMessage: 'Up',
@@ -68,87 +77,60 @@ export const MonitorList = ({ dangerColor, loading, monitors, primaryColor }: Mo
defaultMessage: 'Down',
})}
- ),
- },
- {
- field: 'ping.timestamp',
- name: i18n.translate('xpack.uptime.monitorList.lastUpdatedColumnLabel', {
- defaultMessage: 'Last updated',
- }),
- render: (timestamp: string) => moment(timestamp).fromNow(),
- },
- {
- field: 'ping.monitor.id',
- name: i18n.translate('xpack.uptime.monitorList.idColumnLabel', {
- defaultMessage: 'ID',
- }),
- render: (id: string, monitor: LatestMonitor) => (
+
+ {moment(get(monitor, 'ping.monitor.timestamp', undefined)).fromNow()}
+
+
+ ),
+ },
+ {
+ field: 'ping.monitor.id',
+ name: i18n.translate('xpack.uptime.monitorList.idColumnLabel', {
+ defaultMessage: 'ID',
+ }),
+ render: (id: string, monitor: LatestMonitor) => (
+
{monitor.ping && monitor.ping.monitor && monitor.ping.monitor.name
? monitor.ping.monitor.name
: id}
- ),
- },
- {
- field: 'ping.url.full',
- name: i18n.translate('xpack.uptime.monitorList.urlColumnLabel', {
- defaultMessage: 'URL',
- }),
- render: (url: string) => (
-
- {url}
+
+ ),
+ },
+ {
+ field: 'ping.url.full',
+ name: i18n.translate('xpack.uptime.monitorList.urlColumnLabel', {
+ defaultMessage: 'URL',
+ }),
+ render: (url: string, monitor: LatestMonitor) => (
+
+
+ {url}
- ),
- },
- {
- field: 'ping.monitor.ip',
- name: i18n.translate('xpack.uptime.monitorList.ipColumnLabel', {
- defaultMessage: 'IP',
- }),
- },
- {
- field: 'upSeries',
- name: i18n.translate('xpack.uptime.monitorList.monitorHistoryColumnLabel', {
- defaultMessage: 'Monitor History',
- }),
- // @ts-ignore TODO fix typing
- render: (upSeries, monitor) => {
- const { downSeries } = monitor;
- return (
-
-
-
-
- );
- },
- },
- ]}
- loading={loading}
- items={monitors}
- pagination={monitorListPagination}
- />
-
-
+ {monitor.ping && monitor.ping.monitor && monitor.ping.monitor.ip ? (
+
+ {monitor.ping.monitor.ip}
+
+ ) : null}
+
+ ),
+ },
+ {
+ field: 'upSeries',
+ width: '180px',
+ align: 'right',
+ name: i18n.translate('xpack.uptime.monitorList.monitorHistoryColumnLabel', {
+ defaultMessage: 'Downtime history',
+ }),
+ render: (downSeries: MonitorSeriesPoint, monitor: LatestMonitor) => (
+
+ ),
+ },
+ ]}
+ loading={loading}
+ items={monitors}
+ pagination={monitorListPagination}
+ />
+
);
diff --git a/x-pack/plugins/uptime/public/components/functional/monitor_page_title.tsx b/x-pack/plugins/uptime/public/components/functional/monitor_page_title.tsx
index 4b6b876b61b8d..170aa584696e4 100644
--- a/x-pack/plugins/uptime/public/components/functional/monitor_page_title.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/monitor_page_title.tsx
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui';
+import { EuiTextColor, EuiTitle } from '@elastic/eui';
import React from 'react';
import { MonitorPageTitle as TitleType } from '../../../common/graphql/types';
@@ -13,14 +13,9 @@ interface MonitorPageTitleProps {
}
export const MonitorPageTitle = ({ pageTitle: { name, url, id } }: MonitorPageTitleProps) => (
-
-
-
- {name ? name : url}
-
-
-
- {id}
-
-
+
+
+ {id}
+
+
);
diff --git a/x-pack/plugins/uptime/public/components/functional/monitor_sparkline.tsx b/x-pack/plugins/uptime/public/components/functional/monitor_sparkline.tsx
new file mode 100644
index 0000000000000..90b10a5e44a89
--- /dev/null
+++ b/x-pack/plugins/uptime/public/components/functional/monitor_sparkline.tsx
@@ -0,0 +1,54 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+// @ts-ignore missing type definition
+import { EuiHistogramSeries, EuiSeriesChart, EuiSeriesChartUtils } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import React from 'react';
+import { LatestMonitor, MonitorSeriesPoint } from '../../../common/graphql/types';
+import { formatSparklineCounts } from './format_sparkline_counts';
+
+export interface MonitorSparklineProps {
+ dangerColor: string;
+ monitor: LatestMonitor;
+}
+
+const seriesHasCounts = (series: MonitorSeriesPoint[]) => {
+ return series.some(point => !!point.y);
+};
+
+/**
+ * There is a specific focus on the monitor's down count, the up series is not shown,
+ * so we will only render the series component if there are down counts for the selected monitor.
+ * @param props - the values for the monitor this sparkline reflects
+ */
+export const MonitorSparkline = ({
+ dangerColor,
+ monitor: { downSeries },
+}: MonitorSparklineProps) => {
+ return downSeries && seriesHasCounts(downSeries) ? (
+
+
+
+ ) : null;
+};
diff --git a/x-pack/plugins/uptime/public/components/functional/ping_list.tsx b/x-pack/plugins/uptime/public/components/functional/ping_list.tsx
index a79ab46603557..be5109db0eeee 100644
--- a/x-pack/plugins/uptime/public/components/functional/ping_list.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/ping_list.tsx
@@ -9,11 +9,12 @@ import {
EuiComboBoxOptionProps,
EuiFlexGroup,
EuiFlexItem,
- EuiFormRow,
EuiHealth,
// @ts-ignore
EuiInMemoryTable,
EuiPanel,
+ EuiSpacer,
+ EuiText,
EuiTitle,
EuiToolTip,
} from '@elastic/eui';
@@ -27,9 +28,7 @@ import { convertMicrosecondsToMilliseconds as microsToMillis } from '../../lib/h
interface PingListProps {
loading: boolean;
- maxSearchSize: number;
- pingResults: PingResults;
- searchSizeOnBlur: (e: React.FocusEvent) => void;
+ pingResults?: PingResults;
selectedOption: EuiComboBoxOptionProps;
selectedOptionChanged: (selectedOptions: EuiComboBoxOptionProps[]) => void;
statusOptions: EuiComboBoxOptionProps[];
@@ -37,9 +36,7 @@ interface PingListProps {
export const PingList = ({
loading,
- maxSearchSize,
pingResults,
- searchSizeOnBlur,
selectedOption,
selectedOptionChanged,
statusOptions,
@@ -50,44 +47,39 @@ export const PingList = ({
name: i18n.translate('xpack.uptime.pingList.statusColumnLabel', {
defaultMessage: 'Status',
}),
- render: (pingStatus: string) => (
-
- {pingStatus === 'up'
- ? i18n.translate('xpack.uptime.pingList.statusColumnHealthUpLabel', {
- defaultMessage: 'Up',
- })
- : i18n.translate('xpack.uptime.pingList.statusColumnHealthDownLabel', {
- defaultMessage: 'Down',
- })}
-
+ render: (pingStatus: string, item: Ping) => (
+
+
+ {pingStatus === 'up'
+ ? i18n.translate('xpack.uptime.pingList.statusColumnHealthUpLabel', {
+ defaultMessage: 'Up',
+ })
+ : i18n.translate('xpack.uptime.pingList.statusColumnHealthDownLabel', {
+ defaultMessage: 'Down',
+ })}
+
+
+ {i18n.translate('xpack.uptime.pingList.recencyMessage', {
+ values: { fromNow: moment(item.timestamp).fromNow() },
+ defaultMessage: 'Checked {fromNow}',
+ description:
+ 'A string used to inform our users how long ago Heartbeat pinged the selected host.',
+ })}
+
+
),
},
- {
- field: 'timestamp',
- name: i18n.translate('xpack.uptime.pingList.timestampColumnLabel', {
- defaultMessage: 'Timestamp',
- }),
- render: (timestamp: string) => moment(timestamp).fromNow(),
- },
{
field: 'monitor.ip',
+ dataType: 'number',
name: i18n.translate('xpack.uptime.pingList.ipAddressColumnLabel', {
defaultMessage: 'IP',
}),
},
- {
- field: 'monitor.id',
- name: i18n.translate('xpack.uptime.pingList.idColumnLabel', {
- defaultMessage: 'Id',
- }),
- dataType: 'string',
- width: '20%',
- },
{
field: 'monitor.duration.us',
name: i18n.translate('xpack.uptime.pingList.durationMsColumnLabel', {
- defaultMessage: 'Duration ms',
- description: 'The "ms" in the default message is an abbreviation for milliseconds',
+ defaultMessage: 'Duration',
}),
render: (duration: number) => microsToMillis(duration),
},
@@ -111,10 +103,12 @@ export const PingList = ({
})}
content={{message}
}
>
- {message.slice(0, 24)}…
+ {message.slice(0, 24)}…
) : (
- message
+
+ {message}
+
),
},
];
@@ -131,55 +125,62 @@ export const PingList = ({
if (hasStatus) {
columns.push({
field: 'http.response.status_code',
+ // @ts-ignore "align" property missing on type definition for column type
+ align: 'right',
name: i18n.translate('xpack.uptime.pingList.responseCodeColumnLabel', {
defaultMessage: 'Response code',
}),
+ render: (statusCode: string) => {statusCode} ,
});
}
}
return (
-
-
-
-
-
-
-
-
- {!!total && (
+
+
- {total}
+
+
+
+
+
+
+
+
+ {!!total && (
+
+ {total}
+
+ )}
+
- )}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/x-pack/plugins/uptime/public/components/functional/snapshot.tsx b/x-pack/plugins/uptime/public/components/functional/snapshot.tsx
index 773588fb02fec..c5d683e9b4994 100644
--- a/x-pack/plugins/uptime/public/components/functional/snapshot.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/snapshot.tsx
@@ -18,6 +18,7 @@ import {
EuiStat,
EuiTitle,
} from '@elastic/eui';
+import { EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
@@ -26,86 +27,83 @@ import { SnapshotHistogram } from './snapshot_histogram';
interface SnapshotProps {
dangerColor: string;
- primaryColor: string;
+ successColor: string;
snapshot: SnapshotType;
- windowWidth: number;
}
export const Snapshot = ({
dangerColor,
- primaryColor,
+ successColor,
snapshot: { up, down, total, histogram },
- windowWidth,
}: SnapshotProps) => (
-
+
-
-
-
-
-
-
-
-
- {/* TODO: this is a UI hack that needs to be replaced */}
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
- {/* TODO: this is a UI hack that should be replaced */}
-
+
+
+
+
+
+
+
+
{histogram && (
)}
{!histogram && (
diff --git a/x-pack/plugins/uptime/public/components/functional/snapshot_histogram.tsx b/x-pack/plugins/uptime/public/components/functional/snapshot_histogram.tsx
index 317db3575932b..55b744fe6ed70 100644
--- a/x-pack/plugins/uptime/public/components/functional/snapshot_histogram.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/snapshot_histogram.tsx
@@ -11,8 +11,7 @@ import React from 'react';
import { HistogramDataPoint } from '../../../common/graphql/types';
export interface SnapshotHistogramProps {
- windowWidth: number;
- primaryColor: string;
+ successColor: string;
dangerColor: string;
histogram: HistogramDataPoint[];
}
@@ -22,34 +21,32 @@ export interface SnapshotHistogramProps {
* working with our app, so temporarily we will use this ratio to auto-resize
* the histogram. When we upgrade the charts we will delete this.
*/
-const windowRatio = 0.545238095238095;
export const SnapshotHistogram = ({
dangerColor,
histogram,
- primaryColor,
- windowWidth,
+ successColor,
}: SnapshotHistogramProps) => (
({ x, x0, y: upCount }))}
- name={i18n.translate('xpack.uptime.snapshotHistogram.series.upLabel', {
- defaultMessage: 'Up',
- })}
- color={primaryColor}
- />
- ({ x, x0, y: downCount }))}
+ data={histogram.map(({ x, x0, downCount }) => ({ x, x0, y: downCount || 0 }))}
name={i18n.translate('xpack.uptime.snapshotHistogram.series.downLabel', {
defaultMessage: 'Down',
})}
color={dangerColor}
/>
+ ({ x, x0, y: upCount || 0 }))}
+ name={i18n.translate('xpack.uptime.snapshotHistogram.series.upLabel', {
+ defaultMessage: 'Up',
+ })}
+ color={successColor}
+ />
);
diff --git a/x-pack/plugins/uptime/public/components/functional/snapshot_loading.tsx b/x-pack/plugins/uptime/public/components/functional/snapshot_loading.tsx
index 6833cb5815965..24c11b9a27dbf 100644
--- a/x-pack/plugins/uptime/public/components/functional/snapshot_loading.tsx
+++ b/x-pack/plugins/uptime/public/components/functional/snapshot_loading.tsx
@@ -11,53 +11,53 @@ import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
export const SnapshotLoading = () => (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/x-pack/plugins/uptime/public/components/higher_order/index.ts b/x-pack/plugins/uptime/public/components/higher_order/index.ts
new file mode 100644
index 0000000000000..c5b712e0ae674
--- /dev/null
+++ b/x-pack/plugins/uptime/public/components/higher_order/index.ts
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { UptimeGraphQLQueryProps, withUptimeGraphQL } from './uptime_graphql_query';
diff --git a/x-pack/plugins/uptime/public/components/higher_order/uptime_graphql_query.tsx b/x-pack/plugins/uptime/public/components/higher_order/uptime_graphql_query.tsx
new file mode 100644
index 0000000000000..1976585fec6c4
--- /dev/null
+++ b/x-pack/plugins/uptime/public/components/higher_order/uptime_graphql_query.tsx
@@ -0,0 +1,61 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { OperationVariables } from 'apollo-client';
+import { GraphQLError } from 'graphql';
+import React, { Fragment, useEffect, useState } from 'react';
+import { withApollo, WithApolloClient } from 'react-apollo';
+import { formatUptimeGraphQLErrorList } from '../../lib/helper/format_error_list';
+
+export interface UptimeGraphQLQueryProps {
+ loading: boolean;
+ data?: T;
+ errors?: GraphQLError[];
+}
+
+interface UptimeGraphQLProps {
+ implementsCustomErrorState?: boolean;
+ lastRefresh?: number;
+ variables: OperationVariables;
+}
+
+/**
+ * This HOC abstracts the task of querying our GraphQL endpoint,
+ * which eliminates the need for a lot of boilerplate code in the other components.
+ *
+ * @type T - the expected result's type
+ * @type P - any props the wrapped component will require
+ * @param WrappedComponent - the consuming component
+ * @param query - the graphQL query
+ */
+export function withUptimeGraphQL(WrappedComponent: any, query: any) {
+ type Props = UptimeGraphQLProps & WithApolloClient & P;
+
+ return withApollo((props: Props) => {
+ const [loading, setLoading] = useState(true);
+ const [data, setData] = useState(undefined);
+ const [errors, setErrors] = useState(undefined);
+ const { client, implementsCustomErrorState, variables, lastRefresh } = props;
+ const fetch = () => {
+ setLoading(true);
+ client.query({ fetchPolicy: 'network-only', query, variables }).then((result: any) => {
+ setData(result.data);
+ setLoading(result.loading);
+ setErrors(result.errors);
+ });
+ };
+ useEffect(
+ () => {
+ fetch();
+ },
+ [variables, lastRefresh]
+ );
+ if (!implementsCustomErrorState && errors && errors.length > 0) {
+ return {formatUptimeGraphQLErrorList(errors)} ;
+ }
+ return ;
+ });
+}
diff --git a/x-pack/plugins/uptime/public/components/queries/empty_state/empty_state_query.tsx b/x-pack/plugins/uptime/public/components/queries/empty_state/empty_state_query.tsx
index 29070d1a6d92f..d9a446230c4e2 100644
--- a/x-pack/plugins/uptime/public/components/queries/empty_state/empty_state_query.tsx
+++ b/x-pack/plugins/uptime/public/components/queries/empty_state/empty_state_query.tsx
@@ -4,49 +4,44 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import React from 'react';
-import { Query } from 'react-apollo';
+import { formatUptimeGraphQLErrorList } from '../../../lib/helper/format_error_list';
import { UptimeCommonProps } from '../../../uptime_app';
import { EmptyState } from '../../functional/empty_state';
+import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../../higher_order';
import { getDocCountQuery } from './get_doc_count';
+interface EmptyStateQueryResult {
+ data?: {
+ getDocCount: {
+ count: number;
+ };
+ };
+}
+
interface EmptyStateProps {
basePath: string;
children: JSX.Element[];
}
-type Props = EmptyStateProps & UptimeCommonProps;
+type Props = EmptyStateProps & UptimeCommonProps & UptimeGraphQLQueryProps;
+
+export const makeEmptyStateQuery = ({ basePath, children, data, errors, loading }: Props) => {
+ const count = get(data, 'getDocCount.count', 0);
+ return (
+
+ {children}
+
+ );
+};
-export const EmptyStateQuery = ({
- autorefreshInterval,
- autorefreshIsPaused,
- basePath,
- children,
-}: Props) => (
-
- {({ loading, error, data }) => {
- const count = get(data, 'getDocCount.count', 0);
- return (
-
- );
- }}
-
+export const EmptyStateQuery = withUptimeGraphQL(
+ makeEmptyStateQuery,
+ getDocCountQuery
);
diff --git a/x-pack/plugins/uptime/public/components/queries/error_list/error_list_query.tsx b/x-pack/plugins/uptime/public/components/queries/error_list/error_list_query.tsx
index 3a2b454f4759e..dd7fe829af0c3 100644
--- a/x-pack/plugins/uptime/public/components/queries/error_list/error_list_query.tsx
+++ b/x-pack/plugins/uptime/public/components/queries/error_list/error_list_query.tsx
@@ -4,40 +4,25 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { i18n } from '@kbn/i18n';
import React from 'react';
-import { Query } from 'react-apollo';
+import { ErrorListItem } from '../../../../common/graphql/types';
import { UptimeCommonProps } from '../../../uptime_app';
import { ErrorList } from '../../functional';
+import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../../higher_order';
import { getErrorListQuery } from './get_error_list';
-interface ErrorListProps {
- filters?: string;
+interface ErrorListQueryResult {
+ errorList?: ErrorListItem[];
}
-type Props = ErrorListProps & UptimeCommonProps;
+type Props = UptimeCommonProps & UptimeGraphQLQueryProps;
-export const ErrorListQuery = ({
- autorefreshInterval,
- autorefreshIsPaused,
- dateRangeStart,
- dateRangeEnd,
- filters,
-}: Props) => (
-
- {({ loading, error, data }) => {
- if (error) {
- return i18n.translate('xpack.uptime.errorList.errorMessage', {
- values: { message: error.message },
- defaultMessage: 'Error {message}',
- });
- }
- const { errorList } = data;
- return ;
- }}
-
+export const makeErrorListQuery = ({ data, loading }: Props) => {
+ const errorList: ErrorListItem[] | undefined = data ? data.errorList : undefined;
+ return ;
+};
+
+export const ErrorListQuery = withUptimeGraphQL(
+ makeErrorListQuery,
+ getErrorListQuery
);
diff --git a/x-pack/plugins/uptime/public/components/queries/error_list/get_error_list.ts b/x-pack/plugins/uptime/public/components/queries/error_list/get_error_list.ts
index 57773200eafb5..328efe010b2ff 100644
--- a/x-pack/plugins/uptime/public/components/queries/error_list/get_error_list.ts
+++ b/x-pack/plugins/uptime/public/components/queries/error_list/get_error_list.ts
@@ -19,6 +19,7 @@ query ErrorList($dateRangeStart: String!, $dateRangeEnd: String!, $filters: Stri
count
statusCode
timestamp
+ name
}
}
`;
diff --git a/x-pack/plugins/uptime/public/components/queries/filter_bar/filter_bar_query.tsx b/x-pack/plugins/uptime/public/components/queries/filter_bar/filter_bar_query.tsx
index 5b1265ae57403..8242bf63ff90f 100644
--- a/x-pack/plugins/uptime/public/components/queries/filter_bar/filter_bar_query.tsx
+++ b/x-pack/plugins/uptime/public/components/queries/filter_bar/filter_bar_query.tsx
@@ -4,43 +4,35 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { i18n } from '@kbn/i18n';
import React from 'react';
-import { Query } from 'react-apollo';
+import { FilterBar as FilterBarType } from '../../../../common/graphql/types';
+import { UptimeSearchBarQueryChangeHandler } from '../../../pages/overview';
import { UptimeCommonProps } from '../../../uptime_app';
import { FilterBar, FilterBarLoading } from '../../functional';
+import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../../higher_order';
import { getFilterBarQuery } from './get_filter_bar';
+interface FilterBarQueryResult {
+ filterBar?: FilterBarType;
+}
+
interface FilterBarProps {
- updateQuery: (query: object | undefined) => void;
+ currentQuery?: object;
+ updateQuery: UptimeSearchBarQueryChangeHandler;
}
-type Props = FilterBarProps & UptimeCommonProps;
+type Props = FilterBarProps & UptimeCommonProps & UptimeGraphQLQueryProps;
+
+export const makeFilterBarQuery = ({ currentQuery, data, updateQuery }: Props) => {
+ if (data && data.filterBar) {
+ return (
+
+ );
+ }
+ return ;
+};
-export const FilterBarQuery = ({
- autorefreshInterval,
- autorefreshIsPaused,
- dateRangeStart,
- dateRangeEnd,
- updateQuery,
-}: Props) => (
-
- {({ loading, error, data }) => {
- if (loading) {
- return ;
- }
- if (error) {
- return i18n.translate('xpack.uptime.filterBar.errorMessage', {
- values: { message: error.message },
- defaultMessage: 'Error {message}',
- });
- }
- const { filterBar } = data;
- return ;
- }}
-
+export const FilterBarQuery = withUptimeGraphQL(
+ makeFilterBarQuery,
+ getFilterBarQuery
);
diff --git a/x-pack/plugins/uptime/public/components/queries/monitor_charts/get_monitor_charts.ts b/x-pack/plugins/uptime/public/components/queries/monitor_charts/get_monitor_charts.ts
index 7fffec4440703..03d7800ca9aff 100644
--- a/x-pack/plugins/uptime/public/components/queries/monitor_charts/get_monitor_charts.ts
+++ b/x-pack/plugins/uptime/public/components/queries/monitor_charts/get_monitor_charts.ts
@@ -34,6 +34,6 @@ query MonitorCharts($dateRangeStart: String!, $dateRangeEnd: String!, $monitorId
}
`;
-export const createGetMonitorChartsQuery = gql`
+export const getMonitorChartsQuery = gql`
${getMonitorChartsQueryString}
`;
diff --git a/x-pack/plugins/uptime/public/components/queries/monitor_charts/monitor_charts_query.tsx b/x-pack/plugins/uptime/public/components/queries/monitor_charts/monitor_charts_query.tsx
index 53442c3fd6b4b..275b0f1deea27 100644
--- a/x-pack/plugins/uptime/public/components/queries/monitor_charts/monitor_charts_query.tsx
+++ b/x-pack/plugins/uptime/public/components/queries/monitor_charts/monitor_charts_query.tsx
@@ -6,67 +6,55 @@
import { i18n } from '@kbn/i18n';
import React from 'react';
-import { Query } from 'react-apollo';
import { MonitorChart } from '../../../../common/graphql/types';
import { convertMicrosecondsToMilliseconds as microsToMillis } from '../../../lib/helper';
import { UptimeCommonProps } from '../../../uptime_app';
import { MonitorCharts } from '../../functional';
-import { createGetMonitorChartsQuery } from './get_monitor_charts';
+import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../../higher_order';
+import { getMonitorChartsQuery } from './get_monitor_charts';
+
+interface MonitorChartsQueryResult {
+ monitorChartsData?: MonitorChart;
+}
interface MonitorChartsProps {
monitorId: string;
}
-type Props = MonitorChartsProps & UptimeCommonProps;
+type Props = MonitorChartsProps &
+ UptimeCommonProps &
+ UptimeGraphQLQueryProps;
-export const MonitorChartsQuery = ({
- colors: { primary, secondary, danger },
- dateRangeStart,
- dateRangeEnd,
- monitorId,
- autorefreshIsPaused,
- autorefreshInterval,
-}: Props) => {
- return (
-
- {({ loading, error, data }) => {
- if (loading) {
- return i18n.translate('xpack.uptime.monitorCharts.loadingMessage', {
- defaultMessage: 'Loading…',
- });
- }
- if (error) {
- return i18n.translate('xpack.uptime.monitorCharts.errorMessage', {
- values: { message: error.message },
- defaultMessage: 'Error {message}',
- });
- }
+const makeMonitorCharts = ({ colors: { success, range, mean, danger }, data }: Props) => {
+ if (data && data.monitorChartsData) {
+ const {
+ monitorChartsData,
+ monitorChartsData: { durationMaxValue, statusMaxCount },
+ } = data;
- const {
- monitorChartsData,
- monitorChartsData: { durationMaxValue, statusMaxCount },
- }: { monitorChartsData: MonitorChart } = data;
+ const durationMax = microsToMillis(durationMaxValue);
+ // These limits provide domain sizes for the charts
+ const checkDomainLimits = [0, statusMaxCount];
+ const durationDomainLimits = [0, durationMax ? durationMax : 0];
- const durationMax = microsToMillis(durationMaxValue);
- // These limits provide domain sizes for the charts
- const checkDomainLimits = [0, statusMaxCount];
- const durationDomainLimits = [0, durationMax ? durationMax : 0];
-
- return (
-
- );
- }}
-
- );
+ return (
+
+ );
+ }
+ return i18n.translate('xpack.uptime.monitorCharts.loadingMessage', {
+ defaultMessage: 'Loading…',
+ });
};
+
+export const MonitorChartsQuery = withUptimeGraphQL(
+ makeMonitorCharts,
+ getMonitorChartsQuery
+);
diff --git a/x-pack/plugins/uptime/public/components/queries/monitor_list/monitor_list_query.tsx b/x-pack/plugins/uptime/public/components/queries/monitor_list/monitor_list_query.tsx
index 74509dae81023..194e53a4ec7f0 100644
--- a/x-pack/plugins/uptime/public/components/queries/monitor_list/monitor_list_query.tsx
+++ b/x-pack/plugins/uptime/public/components/queries/monitor_list/monitor_list_query.tsx
@@ -4,50 +4,37 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import React from 'react';
-import { Query } from 'react-apollo';
import { LatestMonitor } from '../../../../common/graphql/types';
import { UptimeCommonProps } from '../../../uptime_app';
import { MonitorList } from '../../functional/monitor_list';
+import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../../higher_order';
import { getMonitorListQuery } from './get_monitor_list';
-interface MonitorListProps {
- filters?: string;
+interface MonitorListQueryResult {
+ // TODO: clean up this ugly result data shape, there should be no nesting
+ monitorStatus?: {
+ monitors: LatestMonitor[];
+ };
}
-type Props = MonitorListProps & UptimeCommonProps;
+type Props = UptimeCommonProps & UptimeGraphQLQueryProps;
-export const MonitorListQuery = ({
- autorefreshInterval,
- autorefreshIsPaused,
- colors: { primary, danger },
- dateRangeStart,
- dateRangeEnd,
- filters,
-}: Props) => (
-
- {({ loading, error, data }) => {
- if (error) {
- return i18n.translate('xpack.uptime.monitorList.errorMessage', {
- values: { message: error.message },
- defaultMessage: 'Error {message}',
- });
- }
- const monitors: LatestMonitor[] | undefined = get(data, 'monitorStatus.monitors', undefined);
- return (
-
- );
- }}
-
+const makeMonitorListQuery = ({ colors: { success, danger }, data, loading }: Props) => {
+ const monitors: LatestMonitor[] | undefined = get(data, 'monitorStatus.monitors');
+
+ return (
+
+ );
+};
+
+export const MonitorListQuery = withUptimeGraphQL(
+ makeMonitorListQuery,
+ getMonitorListQuery
);
diff --git a/x-pack/plugins/uptime/public/components/queries/monitor_page_title/get_monitor_page_title.ts b/x-pack/plugins/uptime/public/components/queries/monitor_page_title/get_monitor_page_title.ts
index 5d5446ffa6992..a54af690c37c7 100644
--- a/x-pack/plugins/uptime/public/components/queries/monitor_page_title/get_monitor_page_title.ts
+++ b/x-pack/plugins/uptime/public/components/queries/monitor_page_title/get_monitor_page_title.ts
@@ -6,7 +6,7 @@
import gql from 'graphql-tag';
-export const getMonitorPageTitle = gql`
+export const getMonitorPageTitleQuery = gql`
query MonitorPageTitle($monitorId: String!) {
monitorPageTitle: getMonitorPageTitle(monitorId: $monitorId) {
id
diff --git a/x-pack/plugins/uptime/public/components/queries/monitor_page_title/monitor_page_title_query.tsx b/x-pack/plugins/uptime/public/components/queries/monitor_page_title/monitor_page_title_query.tsx
index dcbe79cfaa27a..5c36793dfc465 100644
--- a/x-pack/plugins/uptime/public/components/queries/monitor_page_title/monitor_page_title_query.tsx
+++ b/x-pack/plugins/uptime/public/components/queries/monitor_page_title/monitor_page_title_query.tsx
@@ -6,37 +6,33 @@
import { EuiLoadingSpinner } from '@elastic/eui';
import React from 'react';
-import { Query } from 'react-apollo';
import { MonitorPageTitle as TitleType } from '../../../../common/graphql/types';
import { UptimeCommonProps } from '../../../uptime_app';
import { MonitorPageTitle } from '../../functional';
-import { getMonitorPageTitle } from './get_monitor_page_title';
+import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../../higher_order';
+import { getMonitorPageTitleQuery } from './get_monitor_page_title';
+
+interface MonitorPageTitleQueryResult {
+ monitorPageTitle?: TitleType;
+}
interface MonitorPageTitleProps {
monitorId: string;
}
-type Props = MonitorPageTitleProps & UptimeCommonProps;
+type Props = MonitorPageTitleProps &
+ UptimeCommonProps &
+ UptimeGraphQLQueryProps;
+
+export const makeMonitorPageTitleQuery = ({ data }: Props) => {
+ if (data && data.monitorPageTitle) {
+ const { monitorPageTitle } = data;
+ return ;
+ }
+ return ;
+};
-export const MonitorPageTitleQuery = ({
- autorefreshInterval,
- autorefreshIsPaused,
- monitorId,
-}: Props) => (
-
- {({ loading, error, data }) => {
- if (loading) {
- return ;
- }
- if (error) {
- return error;
- }
- const monitorPageTitle: TitleType = data.monitorPageTitle;
- return ;
- }}
-
-);
+export const MonitorPageTitleQuery = withUptimeGraphQL<
+ MonitorPageTitleQueryResult,
+ MonitorPageTitleProps
+>(makeMonitorPageTitleQuery, getMonitorPageTitleQuery);
diff --git a/x-pack/plugins/uptime/public/components/queries/monitor_status_bar/monitor_status_bar_query.tsx b/x-pack/plugins/uptime/public/components/queries/monitor_status_bar/monitor_status_bar_query.tsx
index d6e86111313c4..7b40d5960e614 100644
--- a/x-pack/plugins/uptime/public/components/queries/monitor_status_bar/monitor_status_bar_query.tsx
+++ b/x-pack/plugins/uptime/public/components/queries/monitor_status_bar/monitor_status_bar_query.tsx
@@ -5,70 +5,53 @@
*/
import { i18n } from '@kbn/i18n';
-import { ApolloError } from 'apollo-client';
import { get } from 'lodash';
import React from 'react';
-import { Query } from 'react-apollo';
import { Ping } from '../../../../common/graphql/types';
import { convertMicrosecondsToMilliseconds as microsToMillis } from '../../../lib/helper';
import { UptimeCommonProps } from '../../../uptime_app';
import { EmptyStatusBar, MonitorStatusBar } from '../../functional';
+import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../../higher_order';
import { getMonitorStatusBarQuery } from './get_monitor_status_bar';
-interface MonitorStatusBarProps {
- monitorId: string;
+interface MonitorStatusBarQueryResult {
+ monitorStatus?: Ping[];
}
-interface MonitorStatusBarQueryParams {
- loading: boolean;
- error?: ApolloError | any;
- data?: { monitorStatus: Ping[] };
+interface MonitorStatusBarProps {
+ monitorId: string;
}
-type Props = MonitorStatusBarProps & UptimeCommonProps;
+type Props = MonitorStatusBarProps &
+ UptimeCommonProps &
+ UptimeGraphQLQueryProps;
-export const MonitorStatusBarQuery = ({
- dateRangeStart,
- dateRangeEnd,
- monitorId,
- autorefreshIsPaused,
- autorefreshInterval,
-}: Props) => (
-
- {({ loading, error, data }: MonitorStatusBarQueryParams) => {
- if (loading) {
- return (
-
- );
- }
- if (error) {
- return i18n.translate('xpack.uptime.monitorStatusBar.errorMessage', {
- values: { message: error.message },
- defaultMessage: 'Error {message}',
- });
- }
+const makeMonitorStatusBar = ({ monitorId, data }: Props) => {
+ if (data && data.monitorStatus) {
+ const { monitorStatus } = data;
+ if (!monitorStatus.length) {
+ return ;
+ }
+ const { monitor, timestamp, url } = monitorStatus[0];
+ const status = get(monitor, 'status', undefined);
+ const duration = microsToMillis(get(monitor, 'duration.us', null));
+ const full = get(url, 'full', undefined);
- const monitorStatus: Ping[] = get(data, 'monitorStatus');
- if (!monitorStatus || !monitorStatus.length) {
- return ;
- }
- const { monitor, timestamp, url } = monitorStatus[0];
- const status = get(monitor, 'status', undefined);
- const duration = microsToMillis(get(monitor, 'duration.us', null));
- const full = get(url, 'full', undefined);
+ return (
+
+ );
+ }
+ return (
+
+ );
+};
- return (
-
- );
- }}
-
-);
+export const MonitorStatusBarQuery = withUptimeGraphQL<
+ MonitorStatusBarQueryResult,
+ MonitorStatusBarProps
+>(makeMonitorStatusBar, getMonitorStatusBarQuery);
diff --git a/x-pack/plugins/uptime/public/components/queries/ping_list/ping_list_query.tsx b/x-pack/plugins/uptime/public/components/queries/ping_list/ping_list_query.tsx
index 69d8295bd6675..f06aeaf38b06f 100644
--- a/x-pack/plugins/uptime/public/components/queries/ping_list/ping_list_query.tsx
+++ b/x-pack/plugins/uptime/public/components/queries/ping_list/ping_list_query.tsx
@@ -6,34 +6,41 @@
import { EuiComboBoxOptionProps } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
+import { get } from 'lodash';
import React from 'react';
-import { Query } from 'react-apollo';
import { UMPingSortDirectionArg } from '../../../../common/domain_types';
+import { PingResults } from '../../../../common/graphql/types';
import { UptimeCommonProps } from '../../../uptime_app';
import { PingList } from '../../functional';
+import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../../higher_order';
import { getPingsQuery } from './get_pings';
-const DEFAULT_MAX_SEARCH_SIZE = 100;
+interface PingListQueryResult {
+ allPings?: PingResults;
+}
interface PingListProps {
monitorId?: string;
+ selectedOption?: EuiComboBoxOptionProps;
sort?: UMPingSortDirectionArg;
size?: number;
+ onStatusSelectionChange: (selectedOptions: EuiComboBoxOptionProps[]) => void;
}
-type Props = PingListProps & UptimeCommonProps;
+type Props = PingListProps &
+ UptimeCommonProps &
+ UptimeGraphQLQueryProps &
+ PingListProps;
interface PingListState {
statusOptions: EuiComboBoxOptionProps[];
- selectedOption: EuiComboBoxOptionProps;
- maxSearchSize: number;
}
-export class PingListQuery extends React.Component {
+export class Query extends React.Component {
constructor(props: Props) {
super(props);
- const statusOptions = [
+ const statusOptions: EuiComboBoxOptionProps[] = [
{
label: i18n.translate('xpack.uptime.pingList.statusOptions.allStatusOptionLabel', {
defaultMessage: 'All',
@@ -55,74 +62,26 @@ export class PingListQuery extends React.Component {
];
this.state = {
statusOptions,
- selectedOption: statusOptions[2],
- maxSearchSize: DEFAULT_MAX_SEARCH_SIZE,
};
+ this.props.onStatusSelectionChange([this.state.statusOptions[2]]);
}
+
public render() {
- const {
- monitorId,
- dateRangeStart,
- dateRangeEnd,
- autorefreshIsPaused,
- autorefreshInterval,
- sort,
- size,
- } = this.props;
- const { selectedOption } = this.state;
+ const { loading, data } = this.props;
+ const allPings: PingResults | undefined = get(data, 'allPings', undefined);
return (
-
- {({ loading, error, data }) => {
- if (error) {
- return i18n.translate('xpack.uptime.pingList.errorMessage', {
- values: { message: error.message },
- defaultMessage: 'Error {message}',
- });
- }
- const { allPings } = data;
- return (
-
- );
- }}
-
+
);
}
-
- private onSearchSizeBlur = (e: React.FocusEvent) => {
- const sanitizedValue = parseInt(e.target.value, 10);
- if (!isNaN(sanitizedValue)) {
- this.setState({
- maxSearchSize: sanitizedValue >= 10000 ? 10000 : sanitizedValue,
- });
- }
- };
-
- private onSelectedOptionChange = (selectedOptions: EuiComboBoxOptionProps[]) => {
- if (selectedOptions[0]) {
- this.setState({ selectedOption: selectedOptions[0] });
- }
- };
}
+
+export const PingListQuery = withUptimeGraphQL(
+ Query,
+ getPingsQuery
+);
diff --git a/x-pack/plugins/uptime/public/components/queries/snapshot/snapshot_query.tsx b/x-pack/plugins/uptime/public/components/queries/snapshot/snapshot_query.tsx
index c00be54952362..18ebea9594a5a 100644
--- a/x-pack/plugins/uptime/public/components/queries/snapshot/snapshot_query.tsx
+++ b/x-pack/plugins/uptime/public/components/queries/snapshot/snapshot_query.tsx
@@ -4,82 +4,28 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { i18n } from '@kbn/i18n';
import React from 'react';
-import { Query } from 'react-apollo';
import { Snapshot as SnapshotType } from '../../../../common/graphql/types';
import { UptimeCommonProps } from '../../../uptime_app';
import { Snapshot, SnapshotLoading } from '../../functional';
+import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../../higher_order';
import { getSnapshotQuery } from './get_snapshot';
-interface SnapshotQueryProps {
- filters?: string;
+interface SnapshotQueryResult {
+ snapshot?: SnapshotType;
}
-interface SnapshotQueryState {
- windowWidth: number;
-}
-
-type Props = SnapshotQueryProps & UptimeCommonProps;
-
-export class SnapshotQuery extends React.Component {
- constructor(props: Props) {
- super(props);
- this.state = {
- windowWidth: window.innerWidth,
- };
- }
-
- public componentDidMount() {
- window.addEventListener('resize', this.updateWindowSize);
- }
+type Props = UptimeCommonProps & UptimeGraphQLQueryProps;
- public componentWillUnmount() {
- window.removeEventListener('resize', this.updateWindowSize);
+const Query = (props: Props) => {
+ const {
+ colors: { success, danger },
+ data,
+ } = props;
+ if (data && data.snapshot) {
+ return ;
}
+ return ;
+};
- public render() {
- const {
- autorefreshIsPaused,
- autorefreshInterval,
- colors: { primary, danger },
- dateRangeStart,
- dateRangeEnd,
- filters,
- } = this.props;
-
- return (
-
- {({ loading, error, data }) => {
- if (loading) {
- return ;
- }
- if (error) {
- return i18n.translate('xpack.uptime.snapshot.errorMessage', {
- values: { message: error.message },
- defaultMessage: 'Error {message}',
- });
- }
- const { snapshot }: { snapshot: SnapshotType } = data;
-
- return (
-
- );
- }}
-
- );
- }
-
- private updateWindowSize = () => {
- this.setState({ windowWidth: window.innerWidth });
- };
-}
+export const SnapshotQuery = withUptimeGraphQL(Query, getSnapshotQuery);
diff --git a/x-pack/plugins/uptime/public/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/uptime/public/lib/adapters/framework/kibana_framework_adapter.ts
index d3ef8cf4b7fbe..29630cc4ba9f8 100644
--- a/x-pack/plugins/uptime/public/lib/adapters/framework/kibana_framework_adapter.ts
+++ b/x-pack/plugins/uptime/public/lib/adapters/framework/kibana_framework_adapter.ts
@@ -114,10 +114,10 @@ export class UMKibanaFrameworkAdapter implements UMFrameworkAdapter {
renderComponent({
basePath,
darkMode,
- updateBreadcrumbs: chrome.breadcrumbs.set,
+ setBreadcrumbs: chrome.breadcrumbs.set,
kibanaBreadcrumbs,
routerBasename,
- graphQLClient,
+ client: graphQLClient,
initialAutorefreshIsPaused: autorefreshIsPaused,
initialAutorefreshInterval: autorefreshInterval,
initialDateRangeStart: dateRangeStart,
diff --git a/x-pack/plugins/uptime/public/lib/helper/__test__/__snapshots__/format_error_string.test.ts.snap b/x-pack/plugins/uptime/public/lib/helper/__test__/__snapshots__/format_error_string.test.ts.snap
new file mode 100644
index 0000000000000..8519157e4039e
--- /dev/null
+++ b/x-pack/plugins/uptime/public/lib/helper/__test__/__snapshots__/format_error_string.test.ts.snap
@@ -0,0 +1,7 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`formatErrorString returns a formatted string containing each error 1`] = `
+"Error: foo is bar
+Error: bar is not foo
+"
+`;
diff --git a/x-pack/plugins/uptime/public/lib/helper/__test__/format_error_string.test.ts b/x-pack/plugins/uptime/public/lib/helper/__test__/format_error_string.test.ts
new file mode 100644
index 0000000000000..ba437c05cbe2b
--- /dev/null
+++ b/x-pack/plugins/uptime/public/lib/helper/__test__/format_error_string.test.ts
@@ -0,0 +1,41 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { formatUptimeGraphQLErrorList } from '../format_error_list';
+
+describe('formatErrorString', () => {
+ it('returns an empty string for empty array', () => {
+ const result = formatUptimeGraphQLErrorList([]);
+ expect(result).toEqual('');
+ });
+ it('returns a formatted string containing each error', () => {
+ const result = formatUptimeGraphQLErrorList([
+ {
+ message: 'foo is bar',
+ locations: undefined,
+ path: undefined,
+ nodes: undefined,
+ source: undefined,
+ positions: undefined,
+ originalError: undefined,
+ extensions: undefined,
+ name: 'test error',
+ },
+ {
+ message: 'bar is not foo',
+ locations: undefined,
+ path: undefined,
+ nodes: undefined,
+ source: undefined,
+ positions: undefined,
+ originalError: undefined,
+ extensions: undefined,
+ name: 'test error',
+ },
+ ]);
+ expect(result).toMatchSnapshot();
+ });
+});
diff --git a/x-pack/plugins/uptime/public/lib/helper/format_error_list.ts b/x-pack/plugins/uptime/public/lib/helper/format_error_list.ts
new file mode 100644
index 0000000000000..a23122c5eead5
--- /dev/null
+++ b/x-pack/plugins/uptime/public/lib/helper/format_error_list.ts
@@ -0,0 +1,20 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { i18n } from '@kbn/i18n';
+import { GraphQLError } from 'graphql';
+
+export const formatUptimeGraphQLErrorList = (errors: GraphQLError[]) =>
+ errors.reduce(
+ (errorString, error) =>
+ errorString.concat(
+ `${i18n.translate('xpack.uptime.errorMessage', {
+ values: { message: error.message },
+ defaultMessage: 'Error: {message}',
+ })}\n`
+ ),
+ ''
+ );
diff --git a/x-pack/plugins/uptime/public/pages/monitor.tsx b/x-pack/plugins/uptime/public/pages/monitor.tsx
index 09a276d580c02..25d4c3df0fdea 100644
--- a/x-pack/plugins/uptime/public/pages/monitor.tsx
+++ b/x-pack/plugins/uptime/public/pages/monitor.tsx
@@ -5,11 +5,14 @@
*/
import {
+ EuiComboBoxOptionProps,
// @ts-ignore No typings for EuiSpacer
EuiSpacer,
// @ts-ignore No typings for EuiSuperSelect
EuiSuperSelect,
} from '@elastic/eui';
+import { ApolloQueryResult, OperationVariables, QueryOptions } from 'apollo-client';
+import gql from 'graphql-tag';
import React, { Fragment } from 'react';
import { getMonitorPageBreadcrumb } from '../breadcrumbs';
import {
@@ -18,41 +21,107 @@ import {
MonitorStatusBarQuery,
PingListQuery,
} from '../components/queries';
-import { UMUpdateBreadcrumbs } from '../lib/lib';
import { UptimeCommonProps } from '../uptime_app';
interface MonitorPageProps {
- updateBreadcrumbs: UMUpdateBreadcrumbs;
history: { push: any };
location: { pathname: string };
match: { params: { id: string } };
+ // this is the query function provided by Apollo's Client API
+ query: (
+ options: QueryOptions
+ ) => Promise>;
}
type Props = MonitorPageProps & UptimeCommonProps;
-export class MonitorPage extends React.Component {
+interface MonitorPageState {
+ monitorId: string;
+ selectedPingListOption?: EuiComboBoxOptionProps;
+}
+
+export class MonitorPage extends React.Component {
constructor(props: Props) {
super(props);
+
+ // TODO: this is a hack because the id field's characters mess up react router's
+ // inner params parsing, when we add a synthetic ID for monitors this problem should go away
+ this.state = {
+ monitorId: this.props.location.pathname.replace(/^(\/monitor\/)/, ''),
+ };
}
- public componentWillMount() {
- this.props.updateBreadcrumbs(getMonitorPageBreadcrumb());
+ public componentDidMount() {
+ const { query, setBreadcrumbs, setHeadingText } = this.props;
+ const { monitorId } = this.state;
+
+ query({
+ query: gql`
+ query MonitorPageTitle($monitorId: String!) {
+ monitorPageTitle: getMonitorPageTitle(monitorId: $monitorId) {
+ id
+ url
+ name
+ }
+ }
+ `,
+ variables: { monitorId },
+ }).then((result: any) => {
+ const { name, url, id } = result.data.monitorPageTitle;
+ const heading: string = name || url || id;
+ setBreadcrumbs(getMonitorPageBreadcrumb(heading));
+ setHeadingText(heading);
+ });
}
public render() {
- // TODO: this is a hack because the id field's characters mess up react router's
- // inner params parsing, when we add a synthetic ID for monitors this problem should go away
- const id = this.props.location.pathname.replace(/^(\/monitor\/)/, '');
+ const { dateRangeStart, dateRangeEnd } = this.props;
+ const { monitorId } = this.state;
+
return (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
}
+
+ private onPingListStatusSelectionChange = (selectedOptions: EuiComboBoxOptionProps[]) => {
+ if (selectedOptions[0]) {
+ this.setState({ selectedPingListOption: selectedOptions[0] }, () => this.props.refreshApp());
+ }
+ };
}
diff --git a/x-pack/plugins/uptime/public/pages/overview.tsx b/x-pack/plugins/uptime/public/pages/overview.tsx
index b654353fcf8de..761f305120d8f 100644
--- a/x-pack/plugins/uptime/public/pages/overview.tsx
+++ b/x-pack/plugins/uptime/public/pages/overview.tsx
@@ -4,7 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiSpacer } from '@elastic/eui';
+// @ts-ignore EuiSearchBar missing
+import { EuiSearchBar, EuiSpacer } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
import React, { Fragment } from 'react';
import { getOverviewPageBreadcrumbs } from '../breadcrumbs';
import {
@@ -25,9 +27,12 @@ interface OverviewPageProps {
type Props = OverviewPageProps & UptimeCommonProps;
interface OverviewPageState {
+ currentFilterObj?: object;
currentFilterQuery?: string;
}
+export type UptimeSearchBarQueryChangeHandler = ({ query }: { query?: { text: string } }) => void;
+
export class OverviewPage extends React.Component {
constructor(props: Props) {
super(props);
@@ -38,25 +43,63 @@ export class OverviewPage extends React.Component {
public componentWillMount() {
this.props.setBreadcrumbs(getOverviewPageBreadcrumbs());
+ this.props.setHeadingText(
+ i18n.translate('xpack.uptime.overviewPage.headerText', {
+ defaultMessage: 'Overview',
+ description: `The text that will be displayed in the app's heading when the Overview page loads.`,
+ })
+ );
}
public render() {
+ const commonVariables = {
+ dateRangeStart: this.props.dateRangeStart,
+ dateRangeEnd: this.props.dateRangeEnd,
+ filters: this.state.currentFilterQuery,
+ };
return (
-
+
{
- this.setState({ currentFilterQuery: query ? JSON.stringify(query) : query });
- }}
+ currentQuery={this.state.currentFilterObj}
+ updateQuery={this.onFilterQueryChange}
+ variables={commonVariables}
/>
-
-
-
-
-
+
+
+
+
+
+
);
}
+
+ private onFilterQueryChange: UptimeSearchBarQueryChangeHandler = ({
+ query,
+ }: {
+ query?: { text: string };
+ }) => {
+ try {
+ let esQuery;
+ if (query && query.text) {
+ esQuery = EuiSearchBar.Query.toESQuery(query);
+ }
+ this.setState(
+ {
+ currentFilterObj: query,
+ currentFilterQuery: esQuery ? JSON.stringify(esQuery) : esQuery,
+ },
+ () => this.props.refreshApp()
+ );
+ } catch (e) {
+ this.setState({ currentFilterQuery: undefined });
+ }
+ };
}
diff --git a/x-pack/plugins/uptime/public/uptime_app.tsx b/x-pack/plugins/uptime/public/uptime_app.tsx
index 90cc368939a93..fbaf27632f97d 100644
--- a/x-pack/plugins/uptime/public/uptime_app.tsx
+++ b/x-pack/plugins/uptime/public/uptime_app.tsx
@@ -5,25 +5,25 @@
*/
import {
- EuiHeader,
+ EuiFlexGroup,
+ EuiFlexItem,
// @ts-ignore missing typings for EuiHeaderLink
EuiHeaderLink,
// @ts-ignore missing typings for EuiHeaderLinks
- EuiHeaderLinks,
- // @ts-ignore missing typings for EuiHeaderLogo
EuiHeaderLogo,
- EuiHeaderSection,
- // @ts-ignore missing typings for EuiHeaderSectionItem
+ // @ts-ignore missing typings for EuiHeaderLogo
EuiHeaderSectionItem,
+ // @ts-ignore missing typings for EuiHeaderSectionItem
EuiPage,
- EuiPageContent,
+ EuiSpacer,
// @ts-ignore missing typings for EuiSuperDatePicker
EuiSuperDatePicker,
+ EuiTitle,
} from '@elastic/eui';
import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
-import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n/react';
+import { NormalizedCacheObject } from 'apollo-cache-inmemory';
+import ApolloClient from 'apollo-client';
import React from 'react';
import { ApolloProvider } from 'react-apollo';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
@@ -34,17 +34,23 @@ import { MonitorPage, OverviewPage } from './pages';
interface UptimeAppColors {
danger: string;
- primary: string;
- secondary: string;
+ success: string;
+ range: string;
+ mean: string;
}
// TODO: these props are global to this app, we should put them in a context
export interface UptimeCommonProps {
autorefreshIsPaused: boolean;
autorefreshInterval: number;
+ client: ApolloClient;
+ colors: UptimeAppColors;
dateRangeStart: string;
dateRangeEnd: string;
- colors: UptimeAppColors;
+ lastRefresh?: number;
+ refreshApp: () => void;
+ setBreadcrumbs: UMUpdateBreadcrumbs;
+ setHeadingText: (text: string) => void;
}
export interface UptimePersistedState {
@@ -58,14 +64,14 @@ export interface UptimeAppProps {
// TODO: if we add a context to the Uptime UI, this should be included in it
basePath: string;
darkMode: boolean;
- graphQLClient: UMGraphQLClient;
+ client: UMGraphQLClient;
initialDateRangeStart: string;
initialDateRangeEnd: string;
initialAutorefreshInterval: number;
initialAutorefreshIsPaused: boolean;
kibanaBreadcrumbs: UMBreadcrumb[];
routerBasename: string;
- updateBreadcrumbs: UMUpdateBreadcrumbs;
+ setBreadcrumbs: UMUpdateBreadcrumbs;
persistState(state: UptimePersistedState): void;
renderGlobalHelpControls(): void;
}
@@ -77,6 +83,8 @@ interface UptimeAppState {
colors: UptimeAppColors;
dateRangeStart: string;
dateRangeEnd: string;
+ headingText?: string;
+ lastRefresh?: number;
}
// TODO: when EUI exports types for this, this should be replaced
@@ -102,23 +110,25 @@ class Application extends React.Component {
initialDateRangeStart: dateRangeStart,
initialDateRangeEnd: dateRangeEnd,
kibanaBreadcrumbs,
- updateBreadcrumbs,
+ setBreadcrumbs,
} = props;
- this.setBreadcrumbs = updateBreadcrumbs;
+ this.setBreadcrumbs = setBreadcrumbs;
let colors: UptimeAppColors;
if (darkMode) {
colors = {
- primary: euiDarkVars.euiColorVis1,
- secondary: euiDarkVars.euiColorVis0,
- danger: euiDarkVars.euiColorVis9,
+ success: euiDarkVars.euiColorSuccess,
+ range: euiDarkVars.euiFocusBackgroundColor,
+ mean: euiDarkVars.euiColorPrimary,
+ danger: euiDarkVars.euiColorDanger,
};
} else {
colors = {
- primary: euiLightVars.euiColorVis1,
- secondary: euiLightVars.euiColorVis0,
- danger: euiLightVars.euiColorVis9,
+ success: euiLightVars.euiColorSuccess,
+ range: euiLightVars.euiFocusBackgroundColor,
+ mean: euiLightVars.euiColorPrimary,
+ danger: euiLightVars.euiColorDanger,
};
}
@@ -141,44 +151,22 @@ class Application extends React.Component {
}
public render() {
- const { basePath, routerBasename, graphQLClient } = this.props;
+ const { basePath, routerBasename, client } = this.props;
return (
-
-
-
- {/*
- // @ts-ignore TODO no typings for grow prop */}
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+ {this.state.headingText}
+
+
+
+ {
+ // @ts-ignore onRefresh is not defined on EuiSuperDatePicker's type yet
{
{ dateRangeStart: start, dateRangeEnd: end },
this.persistState
);
+ this.refreshApp();
}}
+ // @ts-ignore onRefresh is not defined on EuiSuperDatePicker's type yet
+ onRefresh={() => this.refreshApp()}
onRefreshChange={({
isPaused,
refreshInterval,
@@ -203,13 +194,11 @@ class Application extends React.Component {
this.persistState
);
}}
- showUpdateButton={false}
/>
-
-
-
-
-
+ }
+
+
+
{
)}
/>
@@ -228,13 +219,16 @@ class Application extends React.Component {
render={props => (
)}
/>
-
+
@@ -242,6 +236,10 @@ class Application extends React.Component {
);
}
+ private setHeadingText = (headingText: string): void => {
+ this.setState({ headingText });
+ };
+
private persistState = (): void => {
const { autorefreshIsPaused, autorefreshInterval, dateRangeStart, dateRangeEnd } = this.state;
this.props.persistState({
@@ -251,6 +249,13 @@ class Application extends React.Component {
dateRangeEnd,
});
};
+
+ private refreshApp = () => {
+ this.setState(state => ({
+ ...state,
+ lastRefresh: Date.now(),
+ }));
+ };
}
export const UptimeApp = (props: UptimeAppProps) => ;
diff --git a/x-pack/plugins/uptime/server/graphql/monitors/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/monitors/schema.gql.ts
index eb8109841dee6..d799889956be6 100644
--- a/x-pack/plugins/uptime/server/graphql/monitors/schema.gql.ts
+++ b/x-pack/plugins/uptime/server/graphql/monitors/schema.gql.ts
@@ -96,9 +96,9 @@ export const monitorsSchema = gql`
"Information from the latest document."
ping: Ping
"Buckets of recent up count status data."
- upSeries: [MonitorSeriesPoint]
+ upSeries: [MonitorSeriesPoint!]
"Buckets of recent down count status data."
- downSeries: [MonitorSeriesPoint]
+ downSeries: [MonitorSeriesPoint!]
}
type LatestMonitorsResult {
@@ -112,6 +112,7 @@ export const monitorsSchema = gql`
count: Int
statusCode: String
timestamp: String
+ name: String
}
type MonitorPageTitle {
diff --git a/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts
index d43f890b2e2bb..8ff7a5040068c 100644
--- a/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts
+++ b/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts
@@ -207,7 +207,7 @@ export const pingsSchema = gql`
"The timestamp of the ping's creation"
timestamp: String!
"Milliseconds from the timestamp to the current time"
- millisFromNow: Int
+ millisFromNow: UnsignedInteger
"The agent that recorded the ping"
beat: Beat
docker: Docker
diff --git a/x-pack/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts b/x-pack/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts
index 8fda903ea26cf..209c6e0642f29 100644
--- a/x-pack/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts
+++ b/x-pack/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts
@@ -483,6 +483,7 @@ export class ElasticsearchMonitorsAdapter implements UMMonitorsAdapter {
const errorMessage = get(source, 'error.message', null);
const statusCode = get(source, 'http.response.status_code', null);
const timestamp = get(source, '@timestamp', null);
+ const name = get(source, 'monitor.name', null);
errorsList.push({
latestMessage: errorMessage,
monitorId,
@@ -490,6 +491,7 @@ export class ElasticsearchMonitorsAdapter implements UMMonitorsAdapter {
count,
statusCode,
timestamp,
+ name: name === '' ? null : name,
});
});
}
diff --git a/x-pack/plugins/uptime/server/lib/adapters/pings/__tests__/__snapshots__/elasticsearch_pings_adapter.test.ts.snap b/x-pack/plugins/uptime/server/lib/adapters/pings/__tests__/__snapshots__/elasticsearch_pings_adapter.test.ts.snap
new file mode 100644
index 0000000000000..a7526739c95ac
--- /dev/null
+++ b/x-pack/plugins/uptime/server/lib/adapters/pings/__tests__/__snapshots__/elasticsearch_pings_adapter.test.ts.snap
@@ -0,0 +1,82 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ElasticsearchPingsAdapter class getPingHistogram handles simple_text_query without issues 1`] = `
+Array [
+ Object {
+ "downCount": 1,
+ "key": 1,
+ "upCount": 2,
+ "x": 2,
+ "x0": 1,
+ "y": 1,
+ },
+ Object {
+ "downCount": 2,
+ "key": 2,
+ "upCount": 1,
+ "x": 3,
+ "x0": 2,
+ "y": 1,
+ },
+]
+`;
+
+exports[`ElasticsearchPingsAdapter class getPingHistogram handles status + additional user queries 1`] = `
+Array [
+ Object {
+ "downCount": 1,
+ "key": 1,
+ "upCount": 0,
+ "x": 2,
+ "x0": 1,
+ "y": 1,
+ },
+ Object {
+ "downCount": 2,
+ "key": 2,
+ "upCount": 0,
+ "x": 3,
+ "x0": 2,
+ "y": 1,
+ },
+]
+`;
+
+exports[`ElasticsearchPingsAdapter class getPingHistogram returns a down-filtered array for when filtered by down status 1`] = `
+Array [
+ Object {
+ "downCount": 1,
+ "key": 1,
+ "upCount": 0,
+ "x": 2,
+ "x0": 1,
+ "y": 1,
+ },
+]
+`;
+
+exports[`ElasticsearchPingsAdapter class getPingHistogram returns a down-filtered array for when filtered by up status 1`] = `
+Array [
+ Object {
+ "downCount": 0,
+ "key": 1,
+ "upCount": 2,
+ "x": 2,
+ "x0": 1,
+ "y": 1,
+ },
+]
+`;
+
+exports[`ElasticsearchPingsAdapter class getPingHistogram returns expected result for no status filter 1`] = `
+Array [
+ Object {
+ "downCount": 1,
+ "key": 1,
+ "upCount": 2,
+ "x": 2,
+ "x0": 1,
+ "y": 1,
+ },
+]
+`;
diff --git a/x-pack/plugins/uptime/server/lib/adapters/pings/__tests__/elasticsearch_pings_adapter.test.ts b/x-pack/plugins/uptime/server/lib/adapters/pings/__tests__/elasticsearch_pings_adapter.test.ts
index 0de453e2027c8..f1500e69a9335 100644
--- a/x-pack/plugins/uptime/server/lib/adapters/pings/__tests__/elasticsearch_pings_adapter.test.ts
+++ b/x-pack/plugins/uptime/server/lib/adapters/pings/__tests__/elasticsearch_pings_adapter.test.ts
@@ -55,6 +55,296 @@ describe('ElasticsearchPingsAdapter class', () => {
};
});
+ describe('getPingHistogram', () => {
+ it('returns an empty array for <= 1 bucket', async () => {
+ expect.assertions(2);
+ const search = jest.fn();
+ search.mockReturnValue({
+ aggregations: {
+ timeseries: {
+ buckets: [
+ {
+ key: 1,
+ bucket_total: {
+ value: 2,
+ },
+ down: {
+ bucket_count: {
+ value: 1,
+ },
+ },
+ },
+ ],
+ },
+ },
+ });
+ const pingDatabase = { search, count: jest.fn() };
+ const pingAdapter = new ElasticsearchPingsAdapter(pingDatabase);
+ const result = await pingAdapter.getPingHistogram(serverRequest, '1234', '5678', null);
+ expect(pingDatabase.search).toHaveBeenCalledTimes(1);
+ expect(result).toEqual([]);
+ });
+
+ it('returns expected result for no status filter', async () => {
+ expect.assertions(2);
+ const search = jest.fn();
+ search.mockReturnValue({
+ aggregations: {
+ timeseries: {
+ buckets: [
+ {
+ key: 1,
+ bucket_total: {
+ value: 3,
+ },
+ down: {
+ bucket_count: {
+ value: 1,
+ },
+ },
+ },
+ {
+ key: 2,
+ bucket_total: {
+ value: 3,
+ },
+ down: {
+ bucket_count: {
+ value: 1,
+ },
+ },
+ },
+ ],
+ },
+ },
+ });
+ const pingDatabase = { search, count: jest.fn() };
+ const pingAdapter = new ElasticsearchPingsAdapter(pingDatabase);
+ const result = await pingAdapter.getPingHistogram(serverRequest, '1234', '5678', null);
+
+ expect(pingDatabase.search).toHaveBeenCalledTimes(1);
+ expect(result).toMatchSnapshot();
+ });
+
+ it('handles status + additional user queries', async () => {
+ expect.assertions(2);
+ const search = jest.fn();
+ search.mockReturnValue({
+ aggregations: {
+ timeseries: {
+ buckets: [
+ {
+ key: 1,
+ bucket_total: {
+ value: 3,
+ },
+ down: {
+ bucket_count: {
+ value: 1,
+ },
+ },
+ },
+ {
+ key: 2,
+ bucket_total: {
+ value: 3,
+ },
+ down: {
+ bucket_count: {
+ value: 2,
+ },
+ },
+ },
+ {
+ key: 3,
+ bucket_total: {
+ value: 3,
+ },
+ down: {
+ bucket_count: {
+ value: 1,
+ },
+ },
+ },
+ ],
+ },
+ },
+ });
+ const searchFilter = {
+ bool: {
+ must: [
+ { match: { 'monitor.status': { query: 'down', operator: 'and' } } },
+ { match: { 'monitor.id': { query: 'auto-http-0X89BB0F9A6C81D178', operator: 'and' } } },
+ { match: { 'monitor.name': { query: 'my-new-test-site-name', operator: 'and' } } },
+ ],
+ },
+ };
+ const pingDatabase = { search, count: jest.fn() };
+ const pingAdapter = new ElasticsearchPingsAdapter(pingDatabase);
+ const result = await pingAdapter.getPingHistogram(
+ serverRequest,
+ '1234',
+ '5678',
+ JSON.stringify(searchFilter)
+ );
+
+ expect(pingDatabase.search).toHaveBeenCalledTimes(1);
+ expect(result).toMatchSnapshot();
+ });
+
+ it('handles simple_text_query without issues', async () => {
+ expect.assertions(2);
+ const search = jest.fn();
+ search.mockReturnValue({
+ aggregations: {
+ timeseries: {
+ buckets: [
+ {
+ key: 1,
+ bucket_total: {
+ value: 3,
+ },
+ down: {
+ bucket_count: {
+ value: 1,
+ },
+ },
+ },
+ {
+ key: 2,
+ bucket_total: {
+ value: 3,
+ },
+ down: {
+ bucket_count: {
+ value: 2,
+ },
+ },
+ },
+ {
+ key: 3,
+ bucket_total: {
+ value: 3,
+ },
+ down: {
+ bucket_count: {
+ value: 1,
+ },
+ },
+ },
+ ],
+ },
+ },
+ });
+ const searchFilter = `{"bool":{"must":[{"simple_query_string":{"query":"http"}}]}}`;
+ const pingDatabase = { search, count: jest.fn() };
+ const pingAdapter = new ElasticsearchPingsAdapter(pingDatabase);
+ const result = await pingAdapter.getPingHistogram(
+ serverRequest,
+ '1234',
+ '5678',
+ searchFilter
+ );
+
+ expect(pingDatabase.search).toHaveBeenCalledTimes(1);
+ expect(result).toMatchSnapshot();
+ });
+
+ it('returns a down-filtered array for when filtered by down status', async () => {
+ expect.assertions(2);
+ const search = jest.fn();
+ search.mockReturnValue({
+ aggregations: {
+ timeseries: {
+ buckets: [
+ {
+ key: 1,
+ bucket_total: {
+ value: 3,
+ },
+ down: {
+ bucket_count: {
+ value: 1,
+ },
+ },
+ },
+ {
+ key: 2,
+ bucket_total: {
+ value: 3,
+ },
+ down: {
+ bucket_count: {
+ value: 1,
+ },
+ },
+ },
+ ],
+ },
+ },
+ });
+ const searchFilter = `{"bool":{"must":[{"match":{"monitor.status":{"query":"down","operator":"and"}}}]}}`;
+ const pingDatabase = { search, count: jest.fn() };
+ const pingAdapter = new ElasticsearchPingsAdapter(pingDatabase);
+ const result = await pingAdapter.getPingHistogram(
+ serverRequest,
+ '1234',
+ '5678',
+ searchFilter
+ );
+
+ expect(pingDatabase.search).toHaveBeenCalledTimes(1);
+ expect(result).toMatchSnapshot();
+ });
+
+ it('returns a down-filtered array for when filtered by up status', async () => {
+ expect.assertions(2);
+ const search = jest.fn();
+ search.mockReturnValue({
+ aggregations: {
+ timeseries: {
+ buckets: [
+ {
+ key: 1,
+ bucket_total: {
+ value: 3,
+ },
+ down: {
+ bucket_count: {
+ value: 1,
+ },
+ },
+ },
+ {
+ key: 2,
+ bucket_total: {
+ value: 3,
+ },
+ down: {
+ bucket_count: {
+ value: 1,
+ },
+ },
+ },
+ ],
+ },
+ },
+ });
+ const searchFilter = `{"bool":{"must":[{"match":{"monitor.status":{"query":"up","operator":"and"}}}]}}`;
+ const pingDatabase = { search, count: jest.fn() };
+ const pingAdapter = new ElasticsearchPingsAdapter(pingDatabase);
+ const result = await pingAdapter.getPingHistogram(
+ serverRequest,
+ '1234',
+ '5678',
+ searchFilter
+ );
+
+ expect(pingDatabase.search).toHaveBeenCalledTimes(1);
+ expect(result).toMatchSnapshot();
+ });
+ });
+
describe('getDocCount', () => {
it('returns data in appropriate shape', async () => {
const { count } = await adapter.getDocCount(serverRequest);
@@ -75,7 +365,7 @@ describe('ElasticsearchPingsAdapter class', () => {
filter: [{ range: { '@timestamp': { gte: 'now-1h', lte: 'now' } } }],
},
},
- sort: [{ '@timestamp': { order: 'asc' } }],
+ sort: [{ '@timestamp': { order: 'desc' } }],
size: 12,
},
};
@@ -104,8 +394,8 @@ describe('ElasticsearchPingsAdapter class', () => {
it('creates appropriate sort and size parameters', async () => {
database.search = getAllSearchMock;
-
await adapter.getAll(serverRequest, 'now-1h', 'now', undefined, undefined, 'asc', 12);
+ set(expectedGetAllParams, 'body.sort[0]', { '@timestamp': { order: 'asc' } });
expect(database.search).toHaveBeenCalledTimes(1);
expect(database.search).toHaveBeenCalledWith(serverRequest, expectedGetAllParams);
@@ -114,7 +404,7 @@ describe('ElasticsearchPingsAdapter class', () => {
it('omits the sort param when no sort passed', async () => {
database.search = getAllSearchMock;
await adapter.getAll(serverRequest, 'now-1h', 'now', undefined, undefined, undefined, 12);
- delete expectedGetAllParams.body.sort;
+
expect(database.search).toHaveBeenCalledWith(serverRequest, expectedGetAllParams);
});
@@ -123,6 +413,7 @@ describe('ElasticsearchPingsAdapter class', () => {
await adapter.getAll(serverRequest, 'now-1h', 'now', undefined, undefined, 'desc');
delete expectedGetAllParams.body.size;
set(expectedGetAllParams, 'body.sort[0].@timestamp.order', 'desc');
+
expect(database.search).toHaveBeenCalledWith(serverRequest, expectedGetAllParams);
});
@@ -130,8 +421,8 @@ describe('ElasticsearchPingsAdapter class', () => {
database.search = getAllSearchMock;
await adapter.getAll(serverRequest, 'now-1h', 'now', 'testmonitorid');
delete expectedGetAllParams.body.size;
- delete expectedGetAllParams.body.sort;
expectedGetAllParams.body.query.bool.filter.push({ term: { 'monitor.id': 'testmonitorid' } });
+
expect(database.search).toHaveBeenCalledWith(serverRequest, expectedGetAllParams);
});
@@ -139,8 +430,8 @@ describe('ElasticsearchPingsAdapter class', () => {
database.search = getAllSearchMock;
await adapter.getAll(serverRequest, 'now-1h', 'now', undefined, 'down');
delete expectedGetAllParams.body.size;
- delete expectedGetAllParams.body.sort;
expectedGetAllParams.body.query.bool.filter.push({ term: { 'monitor.status': 'down' } });
+
expect(database.search).toHaveBeenCalledWith(serverRequest, expectedGetAllParams);
});
});
diff --git a/x-pack/plugins/uptime/server/lib/adapters/pings/elasticsearch_pings_adapter.ts b/x-pack/plugins/uptime/server/lib/adapters/pings/elasticsearch_pings_adapter.ts
index 2d0f659264bbe..545ffda8bc3ee 100644
--- a/x-pack/plugins/uptime/server/lib/adapters/pings/elasticsearch_pings_adapter.ts
+++ b/x-pack/plugins/uptime/server/lib/adapters/pings/elasticsearch_pings_adapter.ts
@@ -8,8 +8,7 @@ import { get } from 'lodash';
import moment from 'moment';
import { INDEX_NAMES } from '../../../../common/constants';
import { DocCount, HistogramDataPoint, Ping, PingResults } from '../../../../common/graphql/types';
-import { formatEsBucketsForHistogram } from '../../helper';
-import { getFilterFromMust } from '../../helper/get_filter_from_must';
+import { formatEsBucketsForHistogram, getFilteredQueryAndStatusFilter } from '../../helper';
import { DatabaseAdapter, HistogramQueryResult } from '../database';
import { UMPingsAdapter } from './adapter_types';
@@ -36,10 +35,10 @@ export class ElasticsearchPingsAdapter implements UMPingsAdapter {
dateRangeEnd: string,
monitorId?: string | null,
status?: string | null,
- sort?: string | null,
+ sort: string | null = 'desc',
size?: number | null
): Promise {
- const sortParam = sort ? { sort: [{ '@timestamp': { order: sort } }] } : undefined;
+ const sortParam = { sort: [{ '@timestamp': { order: sort } }] };
const sizeParam = size ? { size } : undefined;
const filter: any[] = [{ range: { '@timestamp': { gte: dateRangeStart, lte: dateRangeEnd } } }];
if (monitorId) {
@@ -165,7 +164,11 @@ export class ElasticsearchPingsAdapter implements UMPingsAdapter {
dateRangeEnd: string,
filters?: string | null
): Promise {
- const query = getFilterFromMust(dateRangeStart, dateRangeEnd, filters);
+ const { statusFilter, query } = getFilteredQueryAndStatusFilter(
+ dateRangeStart,
+ dateRangeEnd,
+ filters
+ );
const params = {
index: INDEX_NAMES.HEARTBEAT,
body: {
@@ -212,8 +215,8 @@ export class ElasticsearchPingsAdapter implements UMPingsAdapter {
const downCount: number = get(bucket, 'down.bucket_count.value');
return {
key,
- downCount,
- upCount: total - downCount,
+ downCount: statusFilter && statusFilter !== 'down' ? 0 : downCount,
+ upCount: statusFilter && statusFilter !== 'up' ? 0 : total - downCount,
y: 1,
};
});
diff --git a/x-pack/plugins/uptime/server/lib/helper/__test__/__snapshots__/get_filtered_query_and_status.test.ts.snap b/x-pack/plugins/uptime/server/lib/helper/__test__/__snapshots__/get_filtered_query_and_status.test.ts.snap
index 777f86068ef86..4c5b9f9e754a5 100644
--- a/x-pack/plugins/uptime/server/lib/helper/__test__/__snapshots__/get_filtered_query_and_status.test.ts.snap
+++ b/x-pack/plugins/uptime/server/lib/helper/__test__/__snapshots__/get_filtered_query_and_status.test.ts.snap
@@ -1,5 +1,42 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`getFilteredQueryAndStatusFilter handles simple_query_string 1`] = `
+Object {
+ "query": Object {
+ "bool": Object {
+ "filter": Array [
+ Object {
+ "simple_query_string": Object {
+ "fields": Array [
+ "monitor.id",
+ "monitor.url",
+ "monitor.type",
+ "monitor.status",
+ "monitor.name",
+ "url.full",
+ "url.path",
+ "url.scheme",
+ "url.domain",
+ "error.type",
+ ],
+ "query": "http",
+ },
+ },
+ Object {
+ "range": Object {
+ "@timestamp": Object {
+ "gte": "startRange",
+ "lte": "endRange",
+ },
+ },
+ },
+ ],
+ },
+ },
+ "statusFilter": undefined,
+}
+`;
+
exports[`getFilteredQueryAndStatusFilter returns a range + id filter when status filter is absent 1`] = `
Object {
"query": Object {
diff --git a/x-pack/plugins/uptime/server/lib/helper/__test__/get_filtered_query_and_status.test.ts b/x-pack/plugins/uptime/server/lib/helper/__test__/get_filtered_query_and_status.test.ts
index 7598b575cf657..89fba9b773cc0 100644
--- a/x-pack/plugins/uptime/server/lib/helper/__test__/get_filtered_query_and_status.test.ts
+++ b/x-pack/plugins/uptime/server/lib/helper/__test__/get_filtered_query_and_status.test.ts
@@ -39,4 +39,10 @@ describe('getFilteredQueryAndStatusFilter', () => {
const result = getFilteredQueryAndStatusFilter(dateRangeStart, dateRangeEnd, filters);
expect(result).toMatchSnapshot();
});
+
+ it('handles simple_query_string', () => {
+ filters = `{"bool":{"must":[{"simple_query_string":{"query":"http"}}]}}`;
+ const result = getFilteredQueryAndStatusFilter(dateRangeStart, dateRangeEnd, filters);
+ expect(result).toMatchSnapshot();
+ });
});
diff --git a/x-pack/plugins/uptime/server/lib/helper/get_filtered_query.ts b/x-pack/plugins/uptime/server/lib/helper/get_filtered_query.ts
index 3222f6a0dfd80..980804331f665 100644
--- a/x-pack/plugins/uptime/server/lib/helper/get_filtered_query.ts
+++ b/x-pack/plugins/uptime/server/lib/helper/get_filtered_query.ts
@@ -5,6 +5,7 @@
*/
import { get, set } from 'lodash';
+import { QUERY } from '../../../common/constants';
export const getFilteredQuery = (
dateRangeStart: string,
@@ -19,7 +20,16 @@ export const getFilteredQuery = (
filtersObj = filters;
}
if (get(filtersObj, 'bool.must', undefined)) {
- const userFilters = get(filtersObj, 'bool.must', []);
+ const userFilters = get(filtersObj, 'bool.must', []).map((filter: any) =>
+ filter.simple_query_string
+ ? {
+ simple_query_string: {
+ ...filter.simple_query_string,
+ fields: QUERY.SIMPLE_QUERY_STRING_FIELDS,
+ },
+ }
+ : filter
+ );
delete filtersObj.bool.must;
filtersObj.bool.filter = [...userFilters];
}
diff --git a/x-pack/plugins/uptime/server/lib/helper/get_filtered_query_and_status.ts b/x-pack/plugins/uptime/server/lib/helper/get_filtered_query_and_status.ts
index ca8a03f130241..79f47c7582408 100644
--- a/x-pack/plugins/uptime/server/lib/helper/get_filtered_query_and_status.ts
+++ b/x-pack/plugins/uptime/server/lib/helper/get_filtered_query_and_status.ts
@@ -14,7 +14,9 @@ import { getFilteredQuery } from './get_filtered_query';
const getMonitorsListFilteredQuery = (filters: any): string | undefined => {
const must = get(filters, 'bool.must', []);
if (must && must.length) {
- const statusFilter = filters.bool.must.filter((filter: any) => filter.match['monitor.status']);
+ const statusFilter = filters.bool.must.filter(
+ (filter: any) => filter.match && filter.match['monitor.status']
+ );
if (statusFilter.length) {
return statusFilter[0].match['monitor.status'].query;
}
@@ -42,7 +44,10 @@ export const getFilteredQueryAndStatusFilter = (
filterObject = JSON.parse(filters);
nonStatusFiters = getFilteredQuery(dateRangeStart, dateRangeEnd, {
bool: {
- must: filterObject.bool.must.filter((filter: any) => !filter.match['monitor.status']),
+ must: filterObject.bool.must.filter(
+ (filter: any) =>
+ (filter.match && !filter.match['monitor.status']) || filter.simple_query_string
+ ),
},
});
statusFilter = getMonitorsListFilteredQuery(filterObject);
diff --git a/x-pack/test/api_integration/apis/uptime/get_all_pings.js b/x-pack/test/api_integration/apis/uptime/get_all_pings.js
index d2c7cd3b3f5c3..ccb4f4584ca11 100644
--- a/x-pack/test/api_integration/apis/uptime/get_all_pings.js
+++ b/x-pack/test/api_integration/apis/uptime/get_all_pings.js
@@ -16,8 +16,8 @@ export default function ({ getService }) {
describe('get_all_pings', () => {
const archive = 'uptime/pings';
- before(() => esArchiver.load(archive));
- after(() => esArchiver.unload(archive));
+ before('load heartbeat data', async () => await esArchiver.load(archive));
+ after('unload heartbeat data', async () => await esArchiver.unload(archive));
it('should get all pings stored in index', async () => {
const { body: apiResponse } = await supertest
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/error_list.js b/x-pack/test/api_integration/apis/uptime/graphql/error_list.js
index 862cfefec4df0..1efa04678e5b2 100644
--- a/x-pack/test/api_integration/apis/uptime/graphql/error_list.js
+++ b/x-pack/test/api_integration/apis/uptime/graphql/error_list.js
@@ -71,7 +71,7 @@ export default function ({ getService }) {
expect(data).to.eql(errorListFilteredByPort);
});
- it('returns an error list filtered by port/scheme', async () => {
+ it('returns an error list filtered by port/type', async () => {
const getErrorListQuery = {
operationName: 'ErrorList',
query: getErrorListQueryString,
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list.json
index c21b764c51c21..30dcd12623f50 100644
--- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list.json
+++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list.json
@@ -6,7 +6,8 @@
"type": "io",
"count": 843,
"statusCode": null,
- "timestamp": "2019-01-28T18:43:15.077Z"
+ "timestamp": "2019-01-28T18:43:15.077Z",
+ "name": null
},
{
"latestMessage": "dial tcp 127.0.0.1:9200: connect: connection refused",
@@ -14,7 +15,8 @@
"type": "io",
"count": 748,
"statusCode": null,
- "timestamp": "2019-01-28T17:59:34.075Z"
+ "timestamp": "2019-01-28T17:59:34.075Z",
+ "name": null
},
{
"latestMessage": "lookup www.reddit.com: no such host",
@@ -22,7 +24,8 @@
"type": "io",
"count": 1,
"statusCode": null,
- "timestamp": "2019-01-28T18:03:10.077Z"
+ "timestamp": "2019-01-28T18:03:10.077Z",
+ "name": null
},
{
"latestMessage": "received status code 301 expecting 200",
@@ -30,7 +33,8 @@
"type": "validate",
"count": 645,
"statusCode": "301",
- "timestamp": "2019-01-28T18:43:07.078Z"
+ "timestamp": "2019-01-28T18:43:07.078Z",
+ "name": null
}
]
}
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list_filtered_by_id.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list_filtered_by_id.json
index 8fc0ff94bea81..7a26dd39a0078 100644
--- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list_filtered_by_id.json
+++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list_filtered_by_id.json
@@ -6,7 +6,8 @@
"type": "io",
"count": 843,
"statusCode": null,
- "timestamp": "2019-01-28T18:43:15.077Z"
+ "timestamp": "2019-01-28T18:43:15.077Z",
+ "name": null
}
]
}
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list_filtered_by_port.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list_filtered_by_port.json
index 94e1f4fbdfbf5..eb5d0fe721d3a 100644
--- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list_filtered_by_port.json
+++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list_filtered_by_port.json
@@ -6,7 +6,8 @@
"type": "io",
"count": 748,
"statusCode": null,
- "timestamp": "2019-01-28T17:59:34.075Z"
+ "timestamp": "2019-01-28T17:59:34.075Z",
+ "name": null
}
]
}
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list_filtered_by_port_and_type.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list_filtered_by_port_and_type.json
index 8fc0ff94bea81..7a26dd39a0078 100644
--- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list_filtered_by_port_and_type.json
+++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/error_list_filtered_by_port_and_type.json
@@ -6,7 +6,8 @@
"type": "io",
"count": 843,
"statusCode": null,
- "timestamp": "2019-01-28T18:43:15.077Z"
+ "timestamp": "2019-01-28T18:43:15.077Z",
+ "name": null
}
]
}
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list.json
index 4398d60f22c39..c5bbefb5dd05a 100644
--- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list.json
+++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list.json
@@ -3,45 +3,42 @@
"total": 9231,
"pings": [
{
- "timestamp": "2019-01-28T17:47:08.078Z",
+ "timestamp": "2019-01-28T18:43:16.078Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1430 },
+ "duration": { "us": 3328 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:09.075Z",
+ "timestamp": "2019-01-28T18:43:15.077Z",
"http": null,
"error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
+ "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
"type": "io"
},
"monitor": {
- "duration": { "us": 1370 },
- "id": "auto-tcp-0X81440A68E839814C",
+ "duration": { "us": 3331 },
+ "id": "auto-http-0X3675F89EF0612091",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
"status": "down",
- "type": "tcp"
+ "type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:06.077Z",
+ "timestamp": "2019-01-28T18:43:15.077Z",
"http": null,
"error": null,
"monitor": {
- "duration": { "us": 1452 },
+ "duration": { "us": 3292 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
@@ -51,98 +48,83 @@
}
},
{
- "timestamp": "2019-01-28T17:47:07.075Z",
- "http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "timestamp": "2019-01-28T18:43:15.077Z",
+ "http": { "response": { "status_code": 200 } },
+ "error": null,
"monitor": {
- "duration": { "us": 1094 },
- "id": "auto-tcp-0X81440A68E839814C",
- "ip": "127.0.0.1",
+ "duration": { "us": 118727 },
+ "id": "auto-http-0X970CBD2F2102BFA8",
+ "ip": "172.217.12.132",
"name": "",
"scheme": null,
- "status": "down",
- "type": "tcp"
+ "status": "up",
+ "type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:07.074Z",
- "http": null,
- "error": {
- "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
- "type": "io"
- },
+ "timestamp": "2019-01-28T18:43:15.077Z",
+ "http": { "response": { "status_code": 200 } },
+ "error": null,
"monitor": {
- "duration": { "us": 1597 },
- "id": "auto-http-0X3675F89EF0612091",
- "ip": "127.0.0.1",
+ "duration": { "us": 132169 },
+ "id": "auto-http-0X131221E73F825974",
+ "ip": "172.217.12.132",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:18.080Z",
- "http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "timestamp": "2019-01-28T18:43:15.077Z",
+ "http": { "response": { "status_code": 200 } },
+ "error": null,
"monitor": {
- "duration": { "us": 1699 },
- "id": "auto-tcp-0X81440A68E839814C",
- "ip": "127.0.0.1",
+ "duration": { "us": 247244 },
+ "id": "auto-http-0X9CB71300ABD5A2A8",
+ "ip": "192.30.253.112",
"name": "",
"scheme": null,
- "status": "down",
- "type": "tcp"
+ "status": "up",
+ "type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:19.076Z",
+ "timestamp": "2019-01-28T18:43:14.080Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 5384 },
+ "duration": { "us": 2080 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:19.076Z",
+ "timestamp": "2019-01-28T18:43:13.075Z",
"http": null,
- "error": {
- "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 5397 },
- "id": "auto-http-0X3675F89EF0612091",
+ "duration": { "us": 1921 },
+ "id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
- "type": "http"
+ "status": "up",
+ "type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:19.077Z",
- "http": { "response": { "status_code": 200 } },
+ "timestamp": "2019-01-28T18:43:13.074Z",
+ "http": { "response": { "status_code": 301 } },
"error": null,
"monitor": {
- "duration": { "us": 127511 },
- "id": "auto-http-0X131221E73F825974",
- "ip": "172.217.7.4",
+ "duration": { "us": 299586 },
+ "id": "auto-http-0XD9AE729FC1C1E04A",
+ "ip": "151.101.249.140",
"name": "",
"scheme": null,
"status": "up",
@@ -150,13 +132,13 @@
}
},
{
- "timestamp": "2019-01-28T17:47:19.077Z",
+ "timestamp": "2019-01-28T18:43:13.074Z",
"http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 287543 },
- "id": "auto-http-0X9CB71300ABD5A2A8",
- "ip": "192.30.253.112",
+ "duration": { "us": 850870 },
+ "id": "auto-http-0XDD2D4E60FD4A61C3",
+ "ip": "151.101.250.217",
"name": "",
"scheme": null,
"status": "up",
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_count.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_count.json
index f2a68a7b1bfdf..a20456c18a0e3 100644
--- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_count.json
+++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_count.json
@@ -3,45 +3,42 @@
"total": 9231,
"pings": [
{
- "timestamp": "2019-01-28T17:47:08.078Z",
+ "timestamp": "2019-01-28T18:43:16.078Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1430 },
+ "duration": { "us": 3328 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:09.075Z",
+ "timestamp": "2019-01-28T18:43:15.077Z",
"http": null,
"error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
+ "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
"type": "io"
},
"monitor": {
- "duration": { "us": 1370 },
- "id": "auto-tcp-0X81440A68E839814C",
+ "duration": { "us": 3331 },
+ "id": "auto-http-0X3675F89EF0612091",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
"status": "down",
- "type": "tcp"
+ "type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:06.077Z",
+ "timestamp": "2019-01-28T18:43:15.077Z",
"http": null,
"error": null,
"monitor": {
- "duration": { "us": 1452 },
+ "duration": { "us": 3292 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
@@ -51,98 +48,83 @@
}
},
{
- "timestamp": "2019-01-28T17:47:07.075Z",
- "http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "timestamp": "2019-01-28T18:43:15.077Z",
+ "http": { "response": { "status_code": 200 } },
+ "error": null,
"monitor": {
- "duration": { "us": 1094 },
- "id": "auto-tcp-0X81440A68E839814C",
- "ip": "127.0.0.1",
+ "duration": { "us": 118727 },
+ "id": "auto-http-0X970CBD2F2102BFA8",
+ "ip": "172.217.12.132",
"name": "",
"scheme": null,
- "status": "down",
- "type": "tcp"
+ "status": "up",
+ "type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:07.074Z",
- "http": null,
- "error": {
- "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
- "type": "io"
- },
+ "timestamp": "2019-01-28T18:43:15.077Z",
+ "http": { "response": { "status_code": 200 } },
+ "error": null,
"monitor": {
- "duration": { "us": 1597 },
- "id": "auto-http-0X3675F89EF0612091",
- "ip": "127.0.0.1",
+ "duration": { "us": 132169 },
+ "id": "auto-http-0X131221E73F825974",
+ "ip": "172.217.12.132",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:18.080Z",
- "http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "timestamp": "2019-01-28T18:43:15.077Z",
+ "http": { "response": { "status_code": 200 } },
+ "error": null,
"monitor": {
- "duration": { "us": 1699 },
- "id": "auto-tcp-0X81440A68E839814C",
- "ip": "127.0.0.1",
+ "duration": { "us": 247244 },
+ "id": "auto-http-0X9CB71300ABD5A2A8",
+ "ip": "192.30.253.112",
"name": "",
"scheme": null,
- "status": "down",
- "type": "tcp"
+ "status": "up",
+ "type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:19.076Z",
+ "timestamp": "2019-01-28T18:43:14.080Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 5384 },
+ "duration": { "us": 2080 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:19.076Z",
+ "timestamp": "2019-01-28T18:43:13.075Z",
"http": null,
- "error": {
- "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 5397 },
- "id": "auto-http-0X3675F89EF0612091",
+ "duration": { "us": 1921 },
+ "id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
- "type": "http"
+ "status": "up",
+ "type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:19.077Z",
- "http": { "response": { "status_code": 200 } },
+ "timestamp": "2019-01-28T18:43:13.074Z",
+ "http": { "response": { "status_code": 301 } },
"error": null,
"monitor": {
- "duration": { "us": 127511 },
- "id": "auto-http-0X131221E73F825974",
- "ip": "172.217.7.4",
+ "duration": { "us": 299586 },
+ "id": "auto-http-0XD9AE729FC1C1E04A",
+ "ip": "151.101.249.140",
"name": "",
"scheme": null,
"status": "up",
@@ -150,13 +132,13 @@
}
},
{
- "timestamp": "2019-01-28T17:47:19.077Z",
+ "timestamp": "2019-01-28T18:43:13.074Z",
"http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 287543 },
- "id": "auto-http-0X9CB71300ABD5A2A8",
- "ip": "192.30.253.112",
+ "duration": { "us": 850870 },
+ "id": "auto-http-0XDD2D4E60FD4A61C3",
+ "ip": "151.101.250.217",
"name": "",
"scheme": null,
"status": "up",
@@ -164,58 +146,58 @@
}
},
{
- "timestamp": "2019-01-28T17:47:19.076Z",
- "http": { "response": { "status_code": 301 } },
+ "timestamp": "2019-01-28T18:43:12.075Z",
+ "http": null,
"error": null,
"monitor": {
- "duration": { "us": 357805 },
- "id": "auto-http-0XD9AE729FC1C1E04A",
- "ip": "151.101.209.140",
+ "duration": { "us": 1771 },
+ "id": "auto-tcp-0X81440A68E839814C",
+ "ip": "127.0.0.1",
"name": "",
"scheme": null,
"status": "up",
- "type": "http"
+ "type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:19.076Z",
- "http": { "response": { "status_code": 200 } },
+ "timestamp": "2019-01-28T18:43:11.075Z",
+ "http": null,
"error": null,
"monitor": {
- "duration": { "us": 850839 },
- "id": "auto-http-0XDD2D4E60FD4A61C3",
- "ip": "151.101.250.217",
+ "duration": { "us": 2226 },
+ "id": "auto-tcp-0X81440A68E839814C",
+ "ip": "127.0.0.1",
"name": "",
"scheme": null,
"status": "up",
- "type": "http"
+ "type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:20.077Z",
+ "timestamp": "2019-01-28T18:43:11.074Z",
"http": null,
"error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
+ "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
"type": "io"
},
"monitor": {
- "duration": { "us": 2278 },
- "id": "auto-tcp-0X81440A68E839814C",
+ "duration": { "us": 2369 },
+ "id": "auto-http-0X3675F89EF0612091",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
"status": "down",
- "type": "tcp"
+ "type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:20.077Z",
+ "timestamp": "2019-01-28T18:43:11.074Z",
"http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 76702 },
- "id": "auto-http-0X970CBD2F2102BFA8",
- "ip": "172.217.7.4",
+ "duration": { "us": 148937 },
+ "id": "auto-http-0X131221E73F825974",
+ "ip": "172.217.12.132",
"name": "",
"scheme": null,
"status": "up",
@@ -223,146 +205,114 @@
}
},
{
- "timestamp": "2019-01-28T17:47:19.077Z",
- "http": { "response": { "status_code": 301 } },
- "error": { "message": "received status code 301 expecting 200", "type": "validate" },
+ "timestamp": "2019-01-28T18:43:11.074Z",
+ "http": { "response": { "status_code": 200 } },
+ "error": null,
"monitor": {
- "duration": { "us": 1629848 },
- "id": "auto-http-0XA8096548ECEB85B7",
- "ip": "198.71.248.67",
+ "duration": { "us": 235473 },
+ "id": "auto-http-0X9CB71300ABD5A2A8",
+ "ip": "192.30.253.112",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:21.076Z",
+ "timestamp": "2019-01-28T18:43:10.075Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
- "monitor": {
- "duration": { "us": 1757 },
- "id": "auto-tcp-0X81440A68E839814C",
- "ip": "127.0.0.1",
- "name": "",
- "scheme": null,
- "status": "down",
- "type": "tcp"
- }
- },
- {
- "timestamp": "2019-01-28T17:47:22.075Z",
- "http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1040 },
+ "duration": { "us": 1076 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:23.074Z",
- "http": null,
- "error": {
- "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
- "type": "io"
- },
+ "timestamp": "2019-01-28T18:43:10.074Z",
+ "http": { "response": { "status_code": 200 } },
+ "error": null,
"monitor": {
- "duration": { "us": 4578 },
- "id": "auto-http-0X3675F89EF0612091",
- "ip": "127.0.0.1",
+ "duration": { "us": 1032917 },
+ "id": "auto-http-0X970CBD2F2102BFA8",
+ "ip": "172.217.12.132",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:23.075Z",
+ "timestamp": "2019-01-28T18:43:09.079Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 4171 },
+ "duration": { "us": 1824 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:24.077Z",
+ "timestamp": "2019-01-28T18:43:08.075Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1343 },
+ "duration": { "us": 1404 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:25.075Z",
+ "timestamp": "2019-01-28T18:43:07.078Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 647 },
+ "duration": { "us": 3353 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:26.075Z",
+ "timestamp": "2019-01-28T18:43:07.078Z",
"http": null,
"error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
+ "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
"type": "io"
},
"monitor": {
- "duration": { "us": 1227 },
- "id": "auto-tcp-0X81440A68E839814C",
+ "duration": { "us": 3509 },
+ "id": "auto-http-0X3675F89EF0612091",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
"status": "down",
- "type": "tcp"
+ "type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:23.074Z",
+ "timestamp": "2019-01-28T18:43:07.078Z",
"http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 3077816 },
+ "duration": { "us": 2836762 },
"id": "auto-http-0X131221E73F825974",
- "ip": "172.217.7.4",
+ "ip": "172.217.12.132",
"name": "",
"scheme": null,
"status": "up",
@@ -370,13 +320,13 @@
}
},
{
- "timestamp": "2019-01-28T17:47:25.074Z",
+ "timestamp": "2019-01-28T18:43:07.078Z",
"http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 1090949 },
- "id": "auto-http-0X970CBD2F2102BFA8",
- "ip": "172.217.7.4",
+ "duration": { "us": 3991372 },
+ "id": "auto-http-0X9CB71300ABD5A2A8",
+ "ip": "192.30.253.112",
"name": "",
"scheme": null,
"status": "up",
@@ -384,13 +334,13 @@
}
},
{
- "timestamp": "2019-01-28T17:47:22.074Z",
+ "timestamp": "2019-01-28T18:43:07.078Z",
"http": { "response": { "status_code": 301 } },
"error": null,
"monitor": {
- "duration": { "us": 4166351 },
+ "duration": { "us": 4058776 },
"id": "auto-http-0XD9AE729FC1C1E04A",
- "ip": "151.101.209.140",
+ "ip": "151.101.249.140",
"name": "",
"scheme": null,
"status": "up",
@@ -398,13 +348,13 @@
}
},
{
- "timestamp": "2019-01-28T17:47:23.074Z",
+ "timestamp": "2019-01-28T18:43:07.078Z",
"http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 3286549 },
- "id": "auto-http-0X9CB71300ABD5A2A8",
- "ip": "192.30.253.113",
+ "duration": { "us": 4274310 },
+ "id": "auto-http-0XDD2D4E60FD4A61C3",
+ "ip": "151.101.250.217",
"name": "",
"scheme": null,
"status": "up",
@@ -412,75 +362,55 @@
}
},
{
- "timestamp": "2019-01-28T17:47:22.073Z",
- "http": { "response": { "status_code": 200 } },
- "error": null,
+ "timestamp": "2019-01-28T18:43:07.078Z",
+ "http": { "response": { "status_code": 301 } },
+ "error": { "message": "received status code 301 expecting 200", "type": "validate" },
"monitor": {
- "duration": { "us": 4717236 },
- "id": "auto-http-0XDD2D4E60FD4A61C3",
- "ip": "151.101.250.217",
+ "duration": { "us": 4751074 },
+ "id": "auto-http-0XA8096548ECEB85B7",
+ "ip": "198.71.248.67",
"name": "",
"scheme": null,
- "status": "up",
+ "status": "down",
"type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:27.075Z",
+ "timestamp": "2019-01-28T18:43:06.075Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1449 },
+ "duration": { "us": 1861 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:27.074Z",
+ "timestamp": "2019-01-28T18:43:05.076Z",
"http": null,
- "error": {
- "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
- "type": "io"
- },
- "monitor": {
- "duration": { "us": 1769 },
- "id": "auto-http-0X3675F89EF0612091",
- "ip": "127.0.0.1",
- "name": "",
- "scheme": null,
- "status": "down",
- "type": "http"
- }
- },
- {
- "timestamp": "2019-01-28T17:47:27.074Z",
- "http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 112937 },
- "id": "auto-http-0X131221E73F825974",
- "ip": "172.217.7.4",
+ "duration": { "us": 2476 },
+ "id": "auto-tcp-0X81440A68E839814C",
+ "ip": "127.0.0.1",
"name": "",
"scheme": null,
"status": "up",
- "type": "http"
+ "type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:27.074Z",
+ "timestamp": "2019-01-28T18:43:05.076Z",
"http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 281296 },
- "id": "auto-http-0X9CB71300ABD5A2A8",
- "ip": "192.30.253.113",
+ "duration": { "us": 109030 },
+ "id": "auto-http-0X970CBD2F2102BFA8",
+ "ip": "172.217.12.132",
"name": "",
"scheme": null,
"status": "up",
@@ -488,44 +418,27 @@
}
},
{
- "timestamp": "2019-01-28T17:47:23.074Z",
- "http": { "response": { "status_code": 301 } },
- "error": { "message": "received status code 301 expecting 200", "type": "validate" },
- "monitor": {
- "duration": { "us": 4414658 },
- "id": "auto-http-0XA8096548ECEB85B7",
- "ip": "198.71.248.67",
- "name": "",
- "scheme": null,
- "status": "down",
- "type": "http"
- }
- },
- {
- "timestamp": "2019-01-28T17:47:28.075Z",
+ "timestamp": "2019-01-28T18:43:04.077Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 780 },
+ "duration": { "us": 3512 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:28.074Z",
+ "timestamp": "2019-01-28T18:43:04.077Z",
"http": { "response": { "status_code": 301 } },
"error": null,
"monitor": {
- "duration": { "us": 297465 },
+ "duration": { "us": 257046 },
"id": "auto-http-0XD9AE729FC1C1E04A",
- "ip": "151.101.209.140",
+ "ip": "151.101.249.140",
"name": "",
"scheme": null,
"status": "up",
@@ -533,11 +446,11 @@
}
},
{
- "timestamp": "2019-01-28T17:47:28.073Z",
+ "timestamp": "2019-01-28T18:43:04.077Z",
"http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 786082 },
+ "duration": { "us": 443840 },
"id": "auto-http-0XDD2D4E60FD4A61C3",
"ip": "151.101.250.217",
"name": "",
@@ -547,47 +460,44 @@
}
},
{
- "timestamp": "2019-01-28T17:47:29.078Z",
+ "timestamp": "2019-01-28T18:43:03.077Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1006 },
+ "duration": { "us": 3158 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:30.078Z",
+ "timestamp": "2019-01-28T18:43:03.077Z",
"http": null,
"error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
+ "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
"type": "io"
},
"monitor": {
- "duration": { "us": 1572 },
- "id": "auto-tcp-0X81440A68E839814C",
+ "duration": { "us": 3183 },
+ "id": "auto-http-0X3675F89EF0612091",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
"status": "down",
- "type": "tcp"
+ "type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:30.078Z",
+ "timestamp": "2019-01-28T18:43:03.077Z",
"http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 80485 },
- "id": "auto-http-0X970CBD2F2102BFA8",
- "ip": "172.217.7.4",
+ "duration": { "us": 213987 },
+ "id": "auto-http-0X131221E73F825974",
+ "ip": "172.217.12.132",
"name": "",
"scheme": null,
"status": "up",
@@ -595,33 +505,27 @@
}
},
{
- "timestamp": "2019-01-28T17:47:31.075Z",
- "http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "timestamp": "2019-01-28T18:43:03.077Z",
+ "http": { "response": { "status_code": 200 } },
+ "error": null,
"monitor": {
- "duration": { "us": 3263 },
- "id": "auto-tcp-0X81440A68E839814C",
- "ip": "127.0.0.1",
+ "duration": { "us": 263080 },
+ "id": "auto-http-0X9CB71300ABD5A2A8",
+ "ip": "192.30.253.112",
"name": "",
"scheme": null,
- "status": "down",
- "type": "tcp"
+ "status": "up",
+ "type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:31.074Z",
- "http": null,
- "error": {
- "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
- "type": "io"
- },
+ "timestamp": "2019-01-28T18:43:03.077Z",
+ "http": { "response": { "status_code": 301 } },
+ "error": { "message": "received status code 301 expecting 200", "type": "validate" },
"monitor": {
- "duration": { "us": 4109 },
- "id": "auto-http-0X3675F89EF0612091",
- "ip": "127.0.0.1",
+ "duration": { "us": 1396605 },
+ "id": "auto-http-0XA8096548ECEB85B7",
+ "ip": "198.71.248.67",
"name": "",
"scheme": null,
"status": "down",
@@ -629,41 +533,41 @@
}
},
{
- "timestamp": "2019-01-28T17:47:31.074Z",
- "http": { "response": { "status_code": 200 } },
+ "timestamp": "2019-01-28T18:43:02.080Z",
+ "http": null,
"error": null,
"monitor": {
- "duration": { "us": 129148 },
- "id": "auto-http-0X131221E73F825974",
- "ip": "172.217.7.4",
+ "duration": { "us": 1889 },
+ "id": "auto-tcp-0X81440A68E839814C",
+ "ip": "127.0.0.1",
"name": "",
"scheme": null,
"status": "up",
- "type": "http"
+ "type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:31.074Z",
- "http": { "response": { "status_code": 200 } },
+ "timestamp": "2019-01-28T18:43:01.077Z",
+ "http": null,
"error": null,
"monitor": {
- "duration": { "us": 196839 },
- "id": "auto-http-0X9CB71300ABD5A2A8",
- "ip": "192.30.253.113",
+ "duration": { "us": 3191 },
+ "id": "auto-tcp-0X81440A68E839814C",
+ "ip": "127.0.0.1",
"name": "",
"scheme": null,
"status": "up",
- "type": "http"
+ "type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:31.074Z",
+ "timestamp": "2019-01-28T18:43:01.077Z",
"http": { "response": { "status_code": 301 } },
"error": null,
"monitor": {
- "duration": { "us": 362680 },
+ "duration": { "us": 248880 },
"id": "auto-http-0XD9AE729FC1C1E04A",
- "ip": "151.101.209.140",
+ "ip": "151.101.249.140",
"name": "",
"scheme": null,
"status": "up",
@@ -671,11 +575,11 @@
}
},
{
- "timestamp": "2019-01-28T17:47:31.073Z",
+ "timestamp": "2019-01-28T18:43:01.077Z",
"http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 987186 },
+ "duration": { "us": 541379 },
"id": "auto-http-0XDD2D4E60FD4A61C3",
"ip": "151.101.250.217",
"name": "",
@@ -685,78 +589,72 @@
}
},
{
- "timestamp": "2019-01-28T17:47:32.076Z",
+ "timestamp": "2019-01-28T18:43:00.078Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1731 },
+ "duration": { "us": 2449 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:31.073Z",
- "http": { "response": { "status_code": 301 } },
- "error": { "message": "received status code 301 expecting 200", "type": "validate" },
+ "timestamp": "2019-01-28T18:43:00.078Z",
+ "http": { "response": { "status_code": 200 } },
+ "error": null,
"monitor": {
- "duration": { "us": 1512820 },
- "id": "auto-http-0XA8096548ECEB85B7",
- "ip": "198.71.248.67",
+ "duration": { "us": 120545 },
+ "id": "auto-http-0X970CBD2F2102BFA8",
+ "ip": "172.217.12.132",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:33.075Z",
+ "timestamp": "2019-01-28T18:42:59.075Z",
"http": null,
"error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
+ "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
"type": "io"
},
"monitor": {
- "duration": { "us": 1489 },
- "id": "auto-tcp-0X81440A68E839814C",
+ "duration": { "us": 4736 },
+ "id": "auto-http-0X3675F89EF0612091",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
"status": "down",
- "type": "tcp"
+ "type": "http"
}
},
{
- "timestamp": "2019-01-28T17:47:34.075Z",
+ "timestamp": "2019-01-28T18:42:59.075Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 2608 },
+ "duration": { "us": 4617 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:34.075Z",
- "http": { "response": { "status_code": 301 } },
+ "timestamp": "2019-01-28T18:42:59.075Z",
+ "http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 317978 },
- "id": "auto-http-0XD9AE729FC1C1E04A",
- "ip": "151.101.209.140",
+ "duration": { "us": 137745 },
+ "id": "auto-http-0X131221E73F825974",
+ "ip": "172.217.12.132",
"name": "",
"scheme": null,
"status": "up",
@@ -764,13 +662,55 @@
}
},
{
- "timestamp": "2019-01-28T17:47:34.075Z",
+ "timestamp": "2019-01-28T18:42:59.075Z",
"http": { "response": { "status_code": 200 } },
"error": null,
"monitor": {
- "duration": { "us": 752672 },
- "id": "auto-http-0XDD2D4E60FD4A61C3",
- "ip": "151.101.250.217",
+ "duration": { "us": 204668 },
+ "id": "auto-http-0X9CB71300ABD5A2A8",
+ "ip": "192.30.253.112",
+ "name": "",
+ "scheme": null,
+ "status": "up",
+ "type": "http"
+ }
+ },
+ {
+ "timestamp": "2019-01-28T18:42:59.075Z",
+ "http": { "response": { "status_code": 301 } },
+ "error": { "message": "received status code 301 expecting 200", "type": "validate" },
+ "monitor": {
+ "duration": { "us": 1911427 },
+ "id": "auto-http-0XA8096548ECEB85B7",
+ "ip": "198.71.248.67",
+ "name": "",
+ "scheme": null,
+ "status": "down",
+ "type": "http"
+ }
+ },
+ {
+ "timestamp": "2019-01-28T18:42:58.075Z",
+ "http": null,
+ "error": null,
+ "monitor": {
+ "duration": { "us": 1945 },
+ "id": "auto-tcp-0X81440A68E839814C",
+ "ip": "127.0.0.1",
+ "name": "",
+ "scheme": null,
+ "status": "up",
+ "type": "tcp"
+ }
+ },
+ {
+ "timestamp": "2019-01-28T18:42:58.074Z",
+ "http": { "response": { "status_code": 301 } },
+ "error": null,
+ "monitor": {
+ "duration": { "us": 269254 },
+ "id": "auto-http-0XD9AE729FC1C1E04A",
+ "ip": "151.101.249.140",
"name": "",
"scheme": null,
"status": "up",
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_monitor_id.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_monitor_id.json
index ad6f23b5d1182..93a713bb6160f 100644
--- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_monitor_id.json
+++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_monitor_id.json
@@ -3,45 +3,39 @@
"total": 3371,
"pings": [
{
- "timestamp": "2019-01-28T17:47:08.078Z",
+ "timestamp": "2019-01-28T18:43:16.078Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1430 },
+ "duration": { "us": 3328 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:09.075Z",
+ "timestamp": "2019-01-28T18:43:15.077Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1370 },
+ "duration": { "us": 3292 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:06.077Z",
+ "timestamp": "2019-01-28T18:43:14.080Z",
"http": null,
"error": null,
"monitor": {
- "duration": { "us": 1452 },
+ "duration": { "us": 2080 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
@@ -51,206 +45,170 @@
}
},
{
- "timestamp": "2019-01-28T17:47:07.075Z",
+ "timestamp": "2019-01-28T18:43:13.075Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1094 },
+ "duration": { "us": 1921 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:18.080Z",
+ "timestamp": "2019-01-28T18:43:12.075Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1699 },
+ "duration": { "us": 1771 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:19.076Z",
+ "timestamp": "2019-01-28T18:43:11.075Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 5384 },
+ "duration": { "us": 2226 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:20.077Z",
+ "timestamp": "2019-01-28T18:43:10.075Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 2278 },
+ "duration": { "us": 1076 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:21.076Z",
+ "timestamp": "2019-01-28T18:43:09.079Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1757 },
+ "duration": { "us": 1824 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:22.075Z",
+ "timestamp": "2019-01-28T18:43:08.075Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1040 },
+ "duration": { "us": 1404 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:23.075Z",
+ "timestamp": "2019-01-28T18:43:07.078Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 4171 },
+ "duration": { "us": 3353 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:24.077Z",
+ "timestamp": "2019-01-28T18:43:06.075Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1343 },
+ "duration": { "us": 1861 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:25.075Z",
+ "timestamp": "2019-01-28T18:43:05.076Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 647 },
+ "duration": { "us": 2476 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:26.075Z",
+ "timestamp": "2019-01-28T18:43:04.077Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1227 },
+ "duration": { "us": 3512 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:27.075Z",
+ "timestamp": "2019-01-28T18:43:03.077Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 1449 },
+ "duration": { "us": 3158 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
},
{
- "timestamp": "2019-01-28T17:47:28.075Z",
+ "timestamp": "2019-01-28T18:43:02.080Z",
"http": null,
- "error": {
- "message": "dial tcp 127.0.0.1:9200: connect: connection refused",
- "type": "io"
- },
+ "error": null,
"monitor": {
- "duration": { "us": 780 },
+ "duration": { "us": 1889 },
"id": "auto-tcp-0X81440A68E839814C",
"ip": "127.0.0.1",
"name": "",
"scheme": null,
- "status": "down",
+ "status": "up",
"type": "tcp"
}
}
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_filtered_by_up.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_filtered_by_up.json
index c2065ff4659c9..904cf96425841 100644
--- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_filtered_by_up.json
+++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_filtered_by_up.json
@@ -4,10 +4,10 @@
"down": 0,
"total": 8,
"histogram": [
- { "upCount": 8, "downCount": 0, "x": 1548697920000, "x0": 1548697620000, "y": 1 },
+ { "upCount": 7, "downCount": 0, "x": 1548697920000, "x0": 1548697620000, "y": 1 },
{ "upCount": 7, "downCount": 0, "x": 1548698220000, "x0": 1548697920000, "y": 1 },
- { "upCount": 8, "downCount": 0, "x": 1548698520000, "x0": 1548698220000, "y": 1 },
- { "upCount": 8, "downCount": 0, "x": 1548698820000, "x0": 1548698520000, "y": 1 },
+ { "upCount": 7, "downCount": 0, "x": 1548698520000, "x0": 1548698220000, "y": 1 },
+ { "upCount": 7, "downCount": 0, "x": 1548698820000, "x0": 1548698520000, "y": 1 },
{ "upCount": 8, "downCount": 0, "x": 1548699120000, "x0": 1548698820000, "y": 1 },
{ "upCount": 8, "downCount": 0, "x": 1548699420000, "x0": 1548699120000, "y": 1 },
{ "upCount": 8, "downCount": 0, "x": 1548699720000, "x0": 1548699420000, "y": 1 },
diff --git a/x-pack/test/functional/apps/uptime/monitor.ts b/x-pack/test/functional/apps/uptime/monitor.ts
index 7e1cd40d41796..e293dbb04027b 100644
--- a/x-pack/test/functional/apps/uptime/monitor.ts
+++ b/x-pack/test/functional/apps/uptime/monitor.ts
@@ -20,8 +20,9 @@ export default ({ getPageObjects, getService }: KibanaFunctionalTestDefaultProvi
it('loads and displays uptime data based on date range', async () => {
await pageObjects.uptime.loadDataAndGoToMonitorPage(
'2019-01-28 12:40:08.078',
+ '2019-01-29 12:40:08.078',
'auto-http-0X131221E73F825974',
- 'https://www.google.com/'
+ 'auto-http-0X131221E73F825974'
);
});
});
diff --git a/x-pack/test/functional/apps/uptime/overview.ts b/x-pack/test/functional/apps/uptime/overview.ts
index 5379dd9fd68da..b4101db709b31 100644
--- a/x-pack/test/functional/apps/uptime/overview.ts
+++ b/x-pack/test/functional/apps/uptime/overview.ts
@@ -14,6 +14,7 @@ export default ({ getPageObjects }: KibanaFunctionalTestDefaultProviders) => {
it('loads and displays uptime data based on date range', async () => {
await pageObjects.uptime.goToUptimeOverviewAndLoadData(
'2019-01-28 12:40:08.078',
+ '2019-01-29 12:40:08.078',
'monitor-page-link-auto-http-0X131221E73F825974'
);
});
diff --git a/x-pack/test/functional/page_objects/uptime_page.ts b/x-pack/test/functional/page_objects/uptime_page.ts
index d0ad3259247fd..85133b4dd1a5f 100644
--- a/x-pack/test/functional/page_objects/uptime_page.ts
+++ b/x-pack/test/functional/page_objects/uptime_page.ts
@@ -16,20 +16,22 @@ export const UptimePageProvider = ({
return new class UptimePage {
public async goToUptimeOverviewAndLoadData(
datePickerStartValue: string,
+ datePickerEndValue: string,
monitorIdToCheck: string
) {
await pageObjects.common.navigateToApp('uptime');
- await pageObjects.timePicker.setAbsoluteStart(datePickerStartValue);
+ await pageObjects.timePicker.setAbsoluteRange(datePickerStartValue, datePickerEndValue);
await uptimeService.monitorIdExists(monitorIdToCheck);
}
public async loadDataAndGoToMonitorPage(
datePickerStartValue: string,
+ datePickerEndValue: string,
monitorId: string,
monitorName: string
) {
await pageObjects.common.navigateToApp('uptime');
- await pageObjects.timePicker.setAbsoluteStart(datePickerStartValue);
+ await pageObjects.timePicker.setAbsoluteRange(datePickerStartValue, datePickerEndValue);
await uptimeService.navigateToMonitorWithId(monitorId);
if ((await uptimeService.getMonitorNameDisplayedOnPageTitle()) !== monitorName) {
throw new Error('Expected monitor name not found');