mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Uptime] Port unit tests to master (#29876)
* Uptime unit tests6.x (#29280) * Add API functional tests for uptime graphQL. * Remove obsolete code. * Add CI group for UI functional tests. * Delete obsolete code, rename heartbeat es archive. * Refactor adapter methods. * Refactor adapter methods. * Attempt to fix ci-group tag error. * Skip functional app tests until later PR. * Remove unused code. * Add unit tests for ping list and snapshot components. * Add additional unit tests. * Remove unused variable. * Update tests for EmptyState component. * Update ErrorList component tests. * Update monitor list unit test. * Add tests for EmptyStatusBar component. * Write test for FilterBar component. * Update PingList test to work with 7.x data. * Delete obsolete snapshot. * Add test for Snapshot component. * Update types. * Add snapshot histogram test. * Write tests and improve histogram data formatting function. * Fix bug and add test to data format function. * Remove unused localization value. * Resolve localization conflict. * Clean up guaranteed truthy property reference. * Remove expression from localization default message.
This commit is contained in:
parent
674a6aa2ef
commit
e9d0f1b58d
64 changed files with 6901 additions and 1071 deletions
|
@ -301,7 +301,11 @@
|
|||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": { "kind": "OBJECT", "name": "ErrorListItem", "ofType": null }
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "OBJECT", "name": "ErrorListItem", "ofType": null }
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
|
@ -1553,7 +1557,11 @@
|
|||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": { "kind": "OBJECT", "name": "LatestMonitor", "ofType": null }
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "OBJECT", "name": "LatestMonitor", "ofType": null }
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
|
@ -1713,7 +1721,11 @@
|
|||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": { "kind": "OBJECT", "name": "HistogramSeries", "ofType": null }
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "OBJECT", "name": "HistogramSeries", "ofType": null }
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
|
@ -1744,7 +1756,11 @@
|
|||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": { "kind": "OBJECT", "name": "HistogramDataPoint", "ofType": null }
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "OBJECT", "name": "HistogramDataPoint", "ofType": null }
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
|
|
|
@ -30,7 +30,7 @@ export interface Query {
|
|||
|
||||
getFilterBar?: FilterBar | null;
|
||||
|
||||
getErrorsList?: (ErrorListItem | null)[] | null;
|
||||
getErrorsList?: ErrorListItem[] | null;
|
||||
|
||||
getMonitorPageTitle?: MonitorPageTitle | null;
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ export interface DocCount {
|
|||
}
|
||||
|
||||
export interface LatestMonitorsResult {
|
||||
monitors?: (LatestMonitor | null)[] | null;
|
||||
monitors?: LatestMonitor[] | null;
|
||||
}
|
||||
|
||||
export interface LatestMonitor {
|
||||
|
@ -337,13 +337,13 @@ export interface Snapshot {
|
|||
|
||||
total?: number | null;
|
||||
|
||||
histogram?: (HistogramSeries | null)[] | null;
|
||||
histogram?: HistogramSeries[] | null;
|
||||
}
|
||||
|
||||
export interface HistogramSeries {
|
||||
monitorId?: string | null;
|
||||
|
||||
data?: (HistogramDataPoint | null)[] | null;
|
||||
data?: HistogramDataPoint[] | null;
|
||||
}
|
||||
|
||||
export interface HistogramDataPoint {
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`EmptyStatusBar component renders a default message when no message provided 1`] = `
|
||||
<EuiPanel
|
||||
grow={true}
|
||||
hasShadow={false}
|
||||
paddingSize="m"
|
||||
>
|
||||
<EuiFlexGroup
|
||||
alignItems="stretch"
|
||||
component="div"
|
||||
direction="row"
|
||||
gutterSize="l"
|
||||
justifyContent="flexStart"
|
||||
responsive={true}
|
||||
wrap={false}
|
||||
>
|
||||
<EuiFlexItem
|
||||
component="div"
|
||||
grow={false}
|
||||
>
|
||||
No data found for monitor id mon_id
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
`;
|
||||
|
||||
exports[`EmptyStatusBar component renders a message when provided 1`] = `
|
||||
<EuiPanel
|
||||
grow={true}
|
||||
hasShadow={false}
|
||||
paddingSize="m"
|
||||
>
|
||||
<EuiFlexGroup
|
||||
alignItems="stretch"
|
||||
component="div"
|
||||
direction="row"
|
||||
gutterSize="l"
|
||||
justifyContent="flexStart"
|
||||
responsive={true}
|
||||
wrap={false}
|
||||
>
|
||||
<EuiFlexItem
|
||||
component="div"
|
||||
grow={false}
|
||||
>
|
||||
foobarbaz
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
`;
|
|
@ -0,0 +1,115 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ErrorList component renders the error list without errors 1`] = `
|
||||
<Fragment>
|
||||
<EuiTitle
|
||||
size="xs"
|
||||
textTransform="none"
|
||||
>
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
defaultMessage="Error list"
|
||||
id="xpack.uptime.errorList.title"
|
||||
values={Object {}}
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
<EuiPanel
|
||||
grow={true}
|
||||
hasShadow={false}
|
||||
paddingSize="m"
|
||||
>
|
||||
<EuiInMemoryTable
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"field": "type",
|
||||
"name": "Error type",
|
||||
"sortable": true,
|
||||
},
|
||||
Object {
|
||||
"field": "monitorId",
|
||||
"name": "Monitor ID",
|
||||
"render": [Function],
|
||||
"sortable": true,
|
||||
"width": "25%",
|
||||
},
|
||||
Object {
|
||||
"field": "count",
|
||||
"name": "Count",
|
||||
"sortable": true,
|
||||
},
|
||||
Object {
|
||||
"field": "timestamp",
|
||||
"name": "Latest error",
|
||||
"render": [Function],
|
||||
"sortable": true,
|
||||
},
|
||||
Object {
|
||||
"field": "statusCode",
|
||||
"name": "Status code",
|
||||
"sortable": true,
|
||||
},
|
||||
Object {
|
||||
"field": "latestMessage",
|
||||
"name": "Latest message",
|
||||
"sortable": true,
|
||||
"width": "40%",
|
||||
},
|
||||
]
|
||||
}
|
||||
executeQueryOptions={Object {}}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"count": 843,
|
||||
"latestMessage": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
|
||||
"monitorId": "auto-http-0X3675F89EF0612091",
|
||||
"statusCode": null,
|
||||
"timestamp": "2019-01-28T18:43:15.077Z",
|
||||
"type": "io",
|
||||
},
|
||||
Object {
|
||||
"count": 748,
|
||||
"latestMessage": "dial tcp 127.0.0.1:9200: connect: connection refused",
|
||||
"monitorId": "auto-tcp-0X81440A68E839814C",
|
||||
"statusCode": null,
|
||||
"timestamp": "2019-01-28T17:59:34.075Z",
|
||||
"type": "io",
|
||||
},
|
||||
Object {
|
||||
"count": 1,
|
||||
"latestMessage": "lookup www.reddit.com: no such host",
|
||||
"monitorId": "auto-http-0XD9AE729FC1C1E04A",
|
||||
"statusCode": null,
|
||||
"timestamp": "2019-01-28T18:03:10.077Z",
|
||||
"type": "io",
|
||||
},
|
||||
Object {
|
||||
"count": 645,
|
||||
"latestMessage": "received status code 301 expecting 200",
|
||||
"monitorId": "auto-http-0XA8096548ECEB85B7",
|
||||
"statusCode": "301",
|
||||
"timestamp": "2019-01-28T18:43:07.078Z",
|
||||
"type": "validate",
|
||||
},
|
||||
]
|
||||
}
|
||||
loading={false}
|
||||
pagination={
|
||||
Object {
|
||||
"initialPageSize": 10,
|
||||
"pageSizeOptions": Array [
|
||||
5,
|
||||
10,
|
||||
20,
|
||||
50,
|
||||
],
|
||||
}
|
||||
}
|
||||
responsive={true}
|
||||
sorting={true}
|
||||
/>
|
||||
</EuiPanel>
|
||||
</Fragment>
|
||||
`;
|
|
@ -0,0 +1,205 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`FilterBar component renders the component without errors 1`] = `
|
||||
<EuiFlexGroup
|
||||
alignItems="stretch"
|
||||
component="div"
|
||||
direction="row"
|
||||
gutterSize="l"
|
||||
justifyContent="flexStart"
|
||||
responsive={true}
|
||||
wrap={false}
|
||||
>
|
||||
<EuiFlexItem
|
||||
component="div"
|
||||
grow={true}
|
||||
>
|
||||
<EuiSearchBar
|
||||
filters={
|
||||
Array [
|
||||
Object {
|
||||
"field": "monitor.status",
|
||||
"items": Array [
|
||||
Object {
|
||||
"name": "Up",
|
||||
"value": "up",
|
||||
},
|
||||
Object {
|
||||
"name": "Down",
|
||||
"value": "down",
|
||||
},
|
||||
],
|
||||
"type": "field_value_toggle_group",
|
||||
},
|
||||
Object {
|
||||
"field": "monitor.id",
|
||||
"multiSelect": false,
|
||||
"name": "ID",
|
||||
"options": Array [
|
||||
Object {
|
||||
"value": "auto-tcp-0X81440A68E839814C",
|
||||
"view": "auto-tcp-0X81440A68E839814C",
|
||||
},
|
||||
Object {
|
||||
"value": "auto-http-0X3675F89EF0612091",
|
||||
"view": "auto-http-0X3675F89EF0612091",
|
||||
},
|
||||
Object {
|
||||
"value": "auto-http-0X970CBD2F2102BFA8",
|
||||
"view": "auto-http-0X970CBD2F2102BFA8",
|
||||
},
|
||||
Object {
|
||||
"value": "auto-http-0X131221E73F825974",
|
||||
"view": "auto-http-0X131221E73F825974",
|
||||
},
|
||||
Object {
|
||||
"value": "auto-http-0X9CB71300ABD5A2A8",
|
||||
"view": "auto-http-0X9CB71300ABD5A2A8",
|
||||
},
|
||||
Object {
|
||||
"value": "auto-http-0XD9AE729FC1C1E04A",
|
||||
"view": "auto-http-0XD9AE729FC1C1E04A",
|
||||
},
|
||||
Object {
|
||||
"value": "auto-http-0XDD2D4E60FD4A61C3",
|
||||
"view": "auto-http-0XDD2D4E60FD4A61C3",
|
||||
},
|
||||
Object {
|
||||
"value": "auto-http-0XA8096548ECEB85B7",
|
||||
"view": "auto-http-0XA8096548ECEB85B7",
|
||||
},
|
||||
Object {
|
||||
"value": "auto-http-0XC9CDA429418EDC2B",
|
||||
"view": "auto-http-0XC9CDA429418EDC2B",
|
||||
},
|
||||
Object {
|
||||
"value": "auto-http-0XE3B163481423197D",
|
||||
"view": "auto-http-0XE3B163481423197D",
|
||||
},
|
||||
],
|
||||
"searchThreshold": 2,
|
||||
"type": "field_value_selection",
|
||||
},
|
||||
Object {
|
||||
"field": "monitor.name",
|
||||
"multiSelect": false,
|
||||
"name": "Name",
|
||||
"options": Array [],
|
||||
"searchThreshold": 2,
|
||||
"type": "field_value_selection",
|
||||
},
|
||||
Object {
|
||||
"field": "url.full",
|
||||
"multiSelect": false,
|
||||
"name": "URL",
|
||||
"options": Array [
|
||||
Object {
|
||||
"value": "tcp://localhost:9200",
|
||||
"view": "tcp://localhost:9200",
|
||||
},
|
||||
Object {
|
||||
"value": "http://localhost:12349/",
|
||||
"view": "http://localhost:12349/",
|
||||
},
|
||||
Object {
|
||||
"value": "http://www.google.com/",
|
||||
"view": "http://www.google.com/",
|
||||
},
|
||||
Object {
|
||||
"value": "https://www.google.com/",
|
||||
"view": "https://www.google.com/",
|
||||
},
|
||||
Object {
|
||||
"value": "https://www.github.com/",
|
||||
"view": "https://www.github.com/",
|
||||
},
|
||||
Object {
|
||||
"value": "http://www.reddit.com/",
|
||||
"view": "http://www.reddit.com/",
|
||||
},
|
||||
Object {
|
||||
"value": "https://www.elastic.co",
|
||||
"view": "https://www.elastic.co",
|
||||
},
|
||||
Object {
|
||||
"value": "http://www.example.com/",
|
||||
"view": "http://www.example.com/",
|
||||
},
|
||||
Object {
|
||||
"value": "https://www.wikipedia.org/",
|
||||
"view": "https://www.wikipedia.org/",
|
||||
},
|
||||
Object {
|
||||
"value": "https://news.google.com/",
|
||||
"view": "https://news.google.com/",
|
||||
},
|
||||
],
|
||||
"searchThreshold": 2,
|
||||
"type": "field_value_selection",
|
||||
},
|
||||
Object {
|
||||
"field": "url.port",
|
||||
"multiSelect": false,
|
||||
"name": "Port",
|
||||
"options": Array [
|
||||
Object {
|
||||
"value": 9200,
|
||||
"view": 9200,
|
||||
},
|
||||
Object {
|
||||
"value": 12349,
|
||||
"view": 12349,
|
||||
},
|
||||
],
|
||||
"searchThreshold": 2,
|
||||
"type": "field_value_selection",
|
||||
},
|
||||
Object {
|
||||
"field": "monitor.type",
|
||||
"multiSelect": false,
|
||||
"name": "Type",
|
||||
"options": Array [
|
||||
Object {
|
||||
"value": "tcp",
|
||||
"view": "tcp",
|
||||
},
|
||||
Object {
|
||||
"value": "http",
|
||||
"view": "http",
|
||||
},
|
||||
],
|
||||
"searchThreshold": 2,
|
||||
"type": "field_value_selection",
|
||||
},
|
||||
]
|
||||
}
|
||||
onChange={[Function]}
|
||||
schema={
|
||||
Object {
|
||||
"fields": Object {
|
||||
"monitor.host": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"monitor.id": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"monitor.ip": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"monitor.scheme": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"monitor.status": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"url.port": Object {
|
||||
"type": "number",
|
||||
},
|
||||
},
|
||||
"strict": true,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
`;
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,375 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PingList component renders sorted list without errors 1`] = `
|
||||
<Fragment>
|
||||
<EuiFlexGroup
|
||||
alignItems="stretch"
|
||||
component="div"
|
||||
direction="row"
|
||||
gutterSize="l"
|
||||
justifyContent="flexStart"
|
||||
responsive={true}
|
||||
wrap={false}
|
||||
>
|
||||
<EuiFlexItem
|
||||
component="div"
|
||||
grow={false}
|
||||
>
|
||||
<EuiTitle
|
||||
size="xs"
|
||||
textTransform="none"
|
||||
>
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
defaultMessage="Check History"
|
||||
id="xpack.uptime.pingList.checkHistoryTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
</h4>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem
|
||||
component="div"
|
||||
grow={false}
|
||||
>
|
||||
<EuiBadge
|
||||
color="primary"
|
||||
iconSide="left"
|
||||
>
|
||||
9231
|
||||
</EuiBadge>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiPanel
|
||||
grow={true}
|
||||
hasShadow={false}
|
||||
paddingSize="l"
|
||||
>
|
||||
<EuiFlexGroup
|
||||
alignItems="stretch"
|
||||
component="div"
|
||||
direction="row"
|
||||
gutterSize="l"
|
||||
justifyContent="flexStart"
|
||||
responsive={true}
|
||||
wrap={false}
|
||||
>
|
||||
<EuiFlexItem
|
||||
component="div"
|
||||
grow={true}
|
||||
>
|
||||
<EuiFormRow
|
||||
describedByIds={Array []}
|
||||
fullWidth={false}
|
||||
hasEmptyLabelSpace={false}
|
||||
label="Status"
|
||||
>
|
||||
<EuiComboBox
|
||||
compressed={false}
|
||||
fullWidth={false}
|
||||
isClearable={false}
|
||||
onChange={[MockFunction]}
|
||||
options={
|
||||
Array [
|
||||
Object {
|
||||
"label": "All",
|
||||
"value": "",
|
||||
},
|
||||
]
|
||||
}
|
||||
selectedOptions={
|
||||
Array [
|
||||
Object {
|
||||
"label": "All",
|
||||
"value": "",
|
||||
},
|
||||
]
|
||||
}
|
||||
singleSelection={
|
||||
Object {
|
||||
"asPlainText": true,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem
|
||||
component="div"
|
||||
grow={true}
|
||||
>
|
||||
<EuiFormRow
|
||||
describedByIds={Array []}
|
||||
fullWidth={false}
|
||||
hasEmptyLabelSpace={false}
|
||||
label="Max Search Size"
|
||||
>
|
||||
<EuiFieldNumber
|
||||
compressed={false}
|
||||
defaultValue="200"
|
||||
fullWidth={false}
|
||||
isLoading={false}
|
||||
max={10000}
|
||||
min={0}
|
||||
onBlur={[MockFunction]}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiInMemoryTable
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"field": "monitor.status",
|
||||
"name": "Status",
|
||||
"render": [Function],
|
||||
"sortable": true,
|
||||
},
|
||||
Object {
|
||||
"field": "timestamp",
|
||||
"name": "Timestamp",
|
||||
"render": [Function],
|
||||
"sortable": true,
|
||||
},
|
||||
Object {
|
||||
"field": "monitor.ip",
|
||||
"name": "IP",
|
||||
},
|
||||
Object {
|
||||
"dataType": "string",
|
||||
"field": "monitor.id",
|
||||
"name": "Id",
|
||||
"width": "20%",
|
||||
},
|
||||
Object {
|
||||
"field": "monitor.duration.us",
|
||||
"name": "Duration ms",
|
||||
"render": [Function],
|
||||
"sortable": true,
|
||||
},
|
||||
Object {
|
||||
"field": "error.type",
|
||||
"name": "Error type",
|
||||
},
|
||||
Object {
|
||||
"field": "error.message",
|
||||
"name": "Error message",
|
||||
"render": [Function],
|
||||
},
|
||||
Object {
|
||||
"field": "http.response.status_code",
|
||||
"name": "Response code",
|
||||
},
|
||||
]
|
||||
}
|
||||
executeQueryOptions={Object {}}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"error": Object {
|
||||
"message": "dial tcp 127.0.0.1:9200: connect: connection refused",
|
||||
"type": "io",
|
||||
},
|
||||
"http": null,
|
||||
"monitor": Object {
|
||||
"duration": Object {
|
||||
"us": 1430,
|
||||
},
|
||||
"id": "auto-tcp-0X81440A68E839814C",
|
||||
"ip": "127.0.0.1",
|
||||
"name": "",
|
||||
"scheme": null,
|
||||
"status": "down",
|
||||
"type": "tcp",
|
||||
},
|
||||
"timestamp": "2019-01-28T17:47:08.078Z",
|
||||
},
|
||||
Object {
|
||||
"error": Object {
|
||||
"message": "dial tcp 127.0.0.1:9200: connect: connection refused",
|
||||
"type": "io",
|
||||
},
|
||||
"http": null,
|
||||
"monitor": Object {
|
||||
"duration": Object {
|
||||
"us": 1370,
|
||||
},
|
||||
"id": "auto-tcp-0X81440A68E839814C",
|
||||
"ip": "127.0.0.1",
|
||||
"name": "",
|
||||
"scheme": null,
|
||||
"status": "down",
|
||||
"type": "tcp",
|
||||
},
|
||||
"timestamp": "2019-01-28T17:47:09.075Z",
|
||||
},
|
||||
Object {
|
||||
"error": null,
|
||||
"http": null,
|
||||
"monitor": Object {
|
||||
"duration": Object {
|
||||
"us": 1452,
|
||||
},
|
||||
"id": "auto-tcp-0X81440A68E839814C",
|
||||
"ip": "127.0.0.1",
|
||||
"name": "",
|
||||
"scheme": null,
|
||||
"status": "up",
|
||||
"type": "tcp",
|
||||
},
|
||||
"timestamp": "2019-01-28T17:47:06.077Z",
|
||||
},
|
||||
Object {
|
||||
"error": Object {
|
||||
"message": "dial tcp 127.0.0.1:9200: connect: connection refused",
|
||||
"type": "io",
|
||||
},
|
||||
"http": null,
|
||||
"monitor": Object {
|
||||
"duration": Object {
|
||||
"us": 1094,
|
||||
},
|
||||
"id": "auto-tcp-0X81440A68E839814C",
|
||||
"ip": "127.0.0.1",
|
||||
"name": "",
|
||||
"scheme": null,
|
||||
"status": "down",
|
||||
"type": "tcp",
|
||||
},
|
||||
"timestamp": "2019-01-28T17:47:07.075Z",
|
||||
},
|
||||
Object {
|
||||
"error": Object {
|
||||
"message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
|
||||
"type": "io",
|
||||
},
|
||||
"http": null,
|
||||
"monitor": Object {
|
||||
"duration": Object {
|
||||
"us": 1597,
|
||||
},
|
||||
"id": "auto-http-0X3675F89EF0612091",
|
||||
"ip": "127.0.0.1",
|
||||
"name": "",
|
||||
"scheme": null,
|
||||
"status": "down",
|
||||
"type": "http",
|
||||
},
|
||||
"timestamp": "2019-01-28T17:47:07.074Z",
|
||||
},
|
||||
Object {
|
||||
"error": Object {
|
||||
"message": "dial tcp 127.0.0.1:9200: connect: connection refused",
|
||||
"type": "io",
|
||||
},
|
||||
"http": null,
|
||||
"monitor": Object {
|
||||
"duration": Object {
|
||||
"us": 1699,
|
||||
},
|
||||
"id": "auto-tcp-0X81440A68E839814C",
|
||||
"ip": "127.0.0.1",
|
||||
"name": "",
|
||||
"scheme": null,
|
||||
"status": "down",
|
||||
"type": "tcp",
|
||||
},
|
||||
"timestamp": "2019-01-28T17:47:18.080Z",
|
||||
},
|
||||
Object {
|
||||
"error": Object {
|
||||
"message": "dial tcp 127.0.0.1:9200: connect: connection refused",
|
||||
"type": "io",
|
||||
},
|
||||
"http": null,
|
||||
"monitor": Object {
|
||||
"duration": Object {
|
||||
"us": 5384,
|
||||
},
|
||||
"id": "auto-tcp-0X81440A68E839814C",
|
||||
"ip": "127.0.0.1",
|
||||
"name": "",
|
||||
"scheme": null,
|
||||
"status": "down",
|
||||
"type": "tcp",
|
||||
},
|
||||
"timestamp": "2019-01-28T17:47:19.076Z",
|
||||
},
|
||||
Object {
|
||||
"error": Object {
|
||||
"message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused",
|
||||
"type": "io",
|
||||
},
|
||||
"http": null,
|
||||
"monitor": Object {
|
||||
"duration": Object {
|
||||
"us": 5397,
|
||||
},
|
||||
"id": "auto-http-0X3675F89EF0612091",
|
||||
"ip": "127.0.0.1",
|
||||
"name": "",
|
||||
"scheme": null,
|
||||
"status": "down",
|
||||
"type": "http",
|
||||
},
|
||||
"timestamp": "2019-01-28T17:47:19.076Z",
|
||||
},
|
||||
Object {
|
||||
"error": null,
|
||||
"http": Object {
|
||||
"response": Object {
|
||||
"status_code": 200,
|
||||
},
|
||||
},
|
||||
"monitor": Object {
|
||||
"duration": Object {
|
||||
"us": 127511,
|
||||
},
|
||||
"id": "auto-http-0X131221E73F825974",
|
||||
"ip": "172.217.7.4",
|
||||
"name": "",
|
||||
"scheme": null,
|
||||
"status": "up",
|
||||
"type": "http",
|
||||
},
|
||||
"timestamp": "2019-01-28T17:47:19.077Z",
|
||||
},
|
||||
Object {
|
||||
"error": null,
|
||||
"http": Object {
|
||||
"response": Object {
|
||||
"status_code": 200,
|
||||
},
|
||||
},
|
||||
"monitor": Object {
|
||||
"duration": Object {
|
||||
"us": 287543,
|
||||
},
|
||||
"id": "auto-http-0X9CB71300ABD5A2A8",
|
||||
"ip": "192.30.253.112",
|
||||
"name": "",
|
||||
"scheme": null,
|
||||
"status": "up",
|
||||
"type": "http",
|
||||
},
|
||||
"timestamp": "2019-01-28T17:47:19.077Z",
|
||||
},
|
||||
]
|
||||
}
|
||||
loading={false}
|
||||
pagination={
|
||||
Object {
|
||||
"initialPageSize": 10,
|
||||
"pageSizeOptions": Array [
|
||||
5,
|
||||
10,
|
||||
20,
|
||||
100,
|
||||
],
|
||||
}
|
||||
}
|
||||
responsive={true}
|
||||
sorting={true}
|
||||
/>
|
||||
</EuiPanel>
|
||||
</Fragment>
|
||||
`;
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,147 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SnapshotHistogram component renders the component without errors 1`] = `
|
||||
<FlexibleEuiSeriesChart
|
||||
height={107}
|
||||
stackBy="y"
|
||||
width={600}
|
||||
xType="time"
|
||||
>
|
||||
<EuiHistogramSeries
|
||||
color="#FEFEFE"
|
||||
data={
|
||||
Array [
|
||||
Object {
|
||||
"x": 1548698820000,
|
||||
"x0": 1548698520000,
|
||||
"y": 7,
|
||||
},
|
||||
Object {
|
||||
"x": 1548699120000,
|
||||
"x0": 1548698820000,
|
||||
"y": 8,
|
||||
},
|
||||
Object {
|
||||
"x": 1548699420000,
|
||||
"x0": 1548699120000,
|
||||
"y": 8,
|
||||
},
|
||||
Object {
|
||||
"x": 1548699720000,
|
||||
"x0": 1548699420000,
|
||||
"y": 8,
|
||||
},
|
||||
Object {
|
||||
"x": 1548700020000,
|
||||
"x0": 1548699720000,
|
||||
"y": 8,
|
||||
},
|
||||
Object {
|
||||
"x": 1548700320000,
|
||||
"x0": 1548700020000,
|
||||
"y": 8,
|
||||
},
|
||||
Object {
|
||||
"x": 1548700620000,
|
||||
"x0": 1548700320000,
|
||||
"y": 8,
|
||||
},
|
||||
Object {
|
||||
"x": 1548700920000,
|
||||
"x0": 1548700620000,
|
||||
"y": 8,
|
||||
},
|
||||
Object {
|
||||
"x": 1548701220000,
|
||||
"x0": 1548700920000,
|
||||
"y": 8,
|
||||
},
|
||||
Object {
|
||||
"x": 1548697920000,
|
||||
"x0": 1548697620000,
|
||||
"y": 7,
|
||||
},
|
||||
Object {
|
||||
"x": 1548698220000,
|
||||
"x0": 1548697920000,
|
||||
"y": 7,
|
||||
},
|
||||
Object {
|
||||
"x": 1548698520000,
|
||||
"x0": 1548698220000,
|
||||
"y": 7,
|
||||
},
|
||||
]
|
||||
}
|
||||
name="Up"
|
||||
/>
|
||||
<EuiHistogramSeries
|
||||
color="#FF00FF"
|
||||
data={
|
||||
Array [
|
||||
Object {
|
||||
"x": 1548697920000,
|
||||
"x0": 1548697620000,
|
||||
"y": 3,
|
||||
},
|
||||
Object {
|
||||
"x": 1548698220000,
|
||||
"x0": 1548697920000,
|
||||
"y": 3,
|
||||
},
|
||||
Object {
|
||||
"x": 1548698520000,
|
||||
"x0": 1548698220000,
|
||||
"y": 3,
|
||||
},
|
||||
Object {
|
||||
"x": 1548698820000,
|
||||
"x0": 1548698520000,
|
||||
"y": 3,
|
||||
},
|
||||
Object {
|
||||
"x": 1548699120000,
|
||||
"x0": 1548698820000,
|
||||
"y": 2,
|
||||
},
|
||||
Object {
|
||||
"x": 1548699420000,
|
||||
"x0": 1548699120000,
|
||||
"y": 2,
|
||||
},
|
||||
Object {
|
||||
"x": 1548699720000,
|
||||
"x0": 1548699420000,
|
||||
"y": 2,
|
||||
},
|
||||
Object {
|
||||
"x": 1548700020000,
|
||||
"x0": 1548699720000,
|
||||
"y": 2,
|
||||
},
|
||||
Object {
|
||||
"x": 1548700320000,
|
||||
"x0": 1548700020000,
|
||||
"y": 2,
|
||||
},
|
||||
Object {
|
||||
"x": 1548700620000,
|
||||
"x0": 1548700320000,
|
||||
"y": 2,
|
||||
},
|
||||
Object {
|
||||
"x": 1548700920000,
|
||||
"x0": 1548700620000,
|
||||
"y": 2,
|
||||
},
|
||||
Object {
|
||||
"x": 1548701220000,
|
||||
"x0": 1548700920000,
|
||||
"y": 2,
|
||||
},
|
||||
]
|
||||
}
|
||||
name="Down"
|
||||
/>
|
||||
</FlexibleEuiSeriesChart>
|
||||
`;
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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 { EmptyStatusBar } from '../empty_status_bar';
|
||||
|
||||
describe('EmptyStatusBar component', () => {
|
||||
it('renders a message when provided', () => {
|
||||
const component = shallowWithIntl(<EmptyStatusBar message="foobarbaz" monitorId="mon_id" />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders a default message when no message provided', () => {
|
||||
const component = shallowWithIntl(<EmptyStatusBar monitorId="mon_id" />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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 { ErrorListItem } from 'x-pack/plugins/uptime/common/graphql/types';
|
||||
import { ErrorList } from '../error_list';
|
||||
|
||||
describe('ErrorList component', () => {
|
||||
let getErrorListResponse: { errorList: ErrorListItem[] };
|
||||
beforeEach(() => {
|
||||
getErrorListResponse = {
|
||||
errorList: [
|
||||
{
|
||||
latestMessage:
|
||||
'Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused',
|
||||
monitorId: 'auto-http-0X3675F89EF0612091',
|
||||
type: 'io',
|
||||
count: 843,
|
||||
statusCode: null,
|
||||
timestamp: '2019-01-28T18:43:15.077Z',
|
||||
},
|
||||
{
|
||||
latestMessage: 'dial tcp 127.0.0.1:9200: connect: connection refused',
|
||||
monitorId: 'auto-tcp-0X81440A68E839814C',
|
||||
type: 'io',
|
||||
count: 748,
|
||||
statusCode: null,
|
||||
timestamp: '2019-01-28T17:59:34.075Z',
|
||||
},
|
||||
{
|
||||
latestMessage: 'lookup www.reddit.com: no such host',
|
||||
monitorId: 'auto-http-0XD9AE729FC1C1E04A',
|
||||
type: 'io',
|
||||
count: 1,
|
||||
statusCode: null,
|
||||
timestamp: '2019-01-28T18:03:10.077Z',
|
||||
},
|
||||
{
|
||||
latestMessage: 'received status code 301 expecting 200',
|
||||
monitorId: 'auto-http-0XA8096548ECEB85B7',
|
||||
type: 'validate',
|
||||
count: 645,
|
||||
statusCode: '301',
|
||||
timestamp: '2019-01-28T18:43:07.078Z',
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
it('renders the error list without errors', () => {
|
||||
const { errorList } = getErrorListResponse;
|
||||
const component = shallowWithIntl(<ErrorList loading={false} errorList={errorList} />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 { FilterBar } from '../filter_bar';
|
||||
|
||||
describe('FilterBar component', () => {
|
||||
const data = {
|
||||
filterBar: {
|
||||
ports: [9200, 12349],
|
||||
ids: [
|
||||
{ key: 'auto-tcp-0X81440A68E839814C', url: 'tcp://localhost:9200' },
|
||||
{ key: 'auto-http-0X3675F89EF0612091', url: 'http://localhost:12349/' },
|
||||
{ key: 'auto-http-0X970CBD2F2102BFA8', url: 'http://www.google.com/' },
|
||||
{ key: 'auto-http-0X131221E73F825974', url: 'https://www.google.com/' },
|
||||
{ key: 'auto-http-0X9CB71300ABD5A2A8', url: 'https://www.github.com/' },
|
||||
{ key: 'auto-http-0XD9AE729FC1C1E04A', url: 'http://www.reddit.com/' },
|
||||
{ key: 'auto-http-0XDD2D4E60FD4A61C3', url: 'https://www.elastic.co' },
|
||||
{ key: 'auto-http-0XA8096548ECEB85B7', url: 'http://www.example.com/' },
|
||||
{ key: 'auto-http-0XC9CDA429418EDC2B', url: 'https://www.wikipedia.org/' },
|
||||
{ key: 'auto-http-0XE3B163481423197D', url: 'https://news.google.com/' },
|
||||
],
|
||||
names: [],
|
||||
schemes: ['tcp', 'http'],
|
||||
},
|
||||
};
|
||||
|
||||
it('renders the component without errors', () => {
|
||||
const component = shallowWithIntl(
|
||||
<FilterBar filterBar={data.filterBar} updateQuery={jest.fn()} />
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,454 @@
|
|||
/*
|
||||
* 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 { LatestMonitorsResult } from '../../../../common/graphql/types';
|
||||
import { MonitorList } from '../monitor_list';
|
||||
|
||||
describe('MonitorList component', () => {
|
||||
let monitorResult: LatestMonitorsResult;
|
||||
|
||||
beforeEach(() => {
|
||||
monitorResult = {
|
||||
monitors: [
|
||||
{
|
||||
id: { key: 'auto-http-0X131221E73F825974', url: 'https://www.google.com/' },
|
||||
ping: {
|
||||
timestamp: '2019-01-28T18:43:15.077Z',
|
||||
monitor: {
|
||||
duration: { us: 132169 },
|
||||
id: 'auto-http-0X131221E73F825974',
|
||||
ip: '172.217.12.132',
|
||||
name: '',
|
||||
status: 'up',
|
||||
},
|
||||
url: { full: 'https://www.google.com/' },
|
||||
},
|
||||
upSeries: [
|
||||
{ x: 1548697620000, y: 74 },
|
||||
{ x: 1548697920000, y: 75 },
|
||||
{ x: 1548698220000, y: 75 },
|
||||
{ x: 1548698520000, y: 73 },
|
||||
{ x: 1548698820000, y: 75 },
|
||||
{ x: 1548699120000, y: 74 },
|
||||
{ x: 1548699420000, y: 75 },
|
||||
{ x: 1548699720000, y: 75 },
|
||||
{ x: 1548700020000, y: 75 },
|
||||
{ x: 1548700320000, y: 75 },
|
||||
{ x: 1548700620000, y: 75 },
|
||||
{ x: 1548700920000, y: 19 },
|
||||
],
|
||||
downSeries: [
|
||||
{ x: 1548697620000, y: null },
|
||||
{ x: 1548697920000, y: null },
|
||||
{ x: 1548698220000, y: null },
|
||||
{ x: 1548698520000, y: null },
|
||||
{ x: 1548698820000, y: null },
|
||||
{ x: 1548699120000, y: null },
|
||||
{ x: 1548699420000, y: null },
|
||||
{ x: 1548699720000, y: null },
|
||||
{ x: 1548700020000, y: null },
|
||||
{ x: 1548700320000, y: null },
|
||||
{ x: 1548700620000, y: null },
|
||||
{ x: 1548700920000, y: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: { key: 'auto-http-0X3675F89EF0612091', url: 'http://localhost:12349/' },
|
||||
ping: {
|
||||
timestamp: '2019-01-28T18:43:15.077Z',
|
||||
monitor: {
|
||||
duration: { us: 3331 },
|
||||
id: 'auto-http-0X3675F89EF0612091',
|
||||
ip: '127.0.0.1',
|
||||
name: '',
|
||||
status: 'down',
|
||||
},
|
||||
url: { full: 'http://localhost:12349/' },
|
||||
},
|
||||
upSeries: [
|
||||
{ x: 1548697620000, y: null },
|
||||
{ x: 1548697920000, y: null },
|
||||
{ x: 1548698220000, y: null },
|
||||
{ x: 1548698520000, y: null },
|
||||
{ x: 1548698820000, y: null },
|
||||
{ x: 1548699120000, y: null },
|
||||
{ x: 1548699420000, y: null },
|
||||
{ x: 1548699720000, y: null },
|
||||
{ x: 1548700020000, y: null },
|
||||
{ x: 1548700320000, y: null },
|
||||
{ x: 1548700620000, y: null },
|
||||
{ x: 1548700920000, y: null },
|
||||
],
|
||||
downSeries: [
|
||||
{ x: 1548697620000, y: 74 },
|
||||
{ x: 1548697920000, y: 75 },
|
||||
{ x: 1548698220000, y: 75 },
|
||||
{ x: 1548698520000, y: 75 },
|
||||
{ x: 1548698820000, y: 75 },
|
||||
{ x: 1548699120000, y: 75 },
|
||||
{ x: 1548699420000, y: 75 },
|
||||
{ x: 1548699720000, y: 75 },
|
||||
{ x: 1548700020000, y: 75 },
|
||||
{ x: 1548700320000, y: 75 },
|
||||
{ x: 1548700620000, y: 75 },
|
||||
{ x: 1548700920000, y: 19 },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: { key: 'auto-http-0X970CBD2F2102BFA8', url: 'http://www.google.com/' },
|
||||
ping: {
|
||||
timestamp: '2019-01-28T18:43:15.077Z',
|
||||
monitor: {
|
||||
duration: { us: 118727 },
|
||||
id: 'auto-http-0X970CBD2F2102BFA8',
|
||||
ip: '172.217.12.132',
|
||||
name: '',
|
||||
status: 'up',
|
||||
},
|
||||
url: { full: 'http://www.google.com/' },
|
||||
},
|
||||
upSeries: [
|
||||
{ x: 1548697620000, y: 58 },
|
||||
{ x: 1548697920000, y: 60 },
|
||||
{ x: 1548698220000, y: 60 },
|
||||
{ x: 1548698520000, y: 60 },
|
||||
{ x: 1548698820000, y: 60 },
|
||||
{ x: 1548699120000, y: 60 },
|
||||
{ x: 1548699420000, y: 60 },
|
||||
{ x: 1548699720000, y: 60 },
|
||||
{ x: 1548700020000, y: 60 },
|
||||
{ x: 1548700320000, y: 60 },
|
||||
{ x: 1548700620000, y: 60 },
|
||||
{ x: 1548700920000, y: 16 },
|
||||
],
|
||||
downSeries: [
|
||||
{ x: 1548697620000, y: null },
|
||||
{ x: 1548697920000, y: null },
|
||||
{ x: 1548698220000, y: null },
|
||||
{ x: 1548698520000, y: null },
|
||||
{ x: 1548698820000, y: null },
|
||||
{ x: 1548699120000, y: null },
|
||||
{ x: 1548699420000, y: null },
|
||||
{ x: 1548699720000, y: null },
|
||||
{ x: 1548700020000, y: null },
|
||||
{ x: 1548700320000, y: null },
|
||||
{ x: 1548700620000, y: null },
|
||||
{ x: 1548700920000, y: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: { key: 'auto-http-0X9CB71300ABD5A2A8', url: 'https://www.github.com/' },
|
||||
ping: {
|
||||
timestamp: '2019-01-28T18:43:15.077Z',
|
||||
monitor: {
|
||||
duration: { us: 247244 },
|
||||
id: 'auto-http-0X9CB71300ABD5A2A8',
|
||||
ip: '192.30.253.112',
|
||||
name: '',
|
||||
status: 'up',
|
||||
},
|
||||
url: { full: 'https://www.github.com/' },
|
||||
},
|
||||
upSeries: [
|
||||
{ x: 1548697620000, y: 69 },
|
||||
{ x: 1548697920000, y: 70 },
|
||||
{ x: 1548698220000, y: 68 },
|
||||
{ x: 1548698520000, y: 69 },
|
||||
{ x: 1548698820000, y: 69 },
|
||||
{ x: 1548699120000, y: 69 },
|
||||
{ x: 1548699420000, y: 70 },
|
||||
{ x: 1548699720000, y: 70 },
|
||||
{ x: 1548700020000, y: 70 },
|
||||
{ x: 1548700320000, y: 69 },
|
||||
{ x: 1548700620000, y: 70 },
|
||||
{ x: 1548700920000, y: 18 },
|
||||
],
|
||||
downSeries: [
|
||||
{ x: 1548697620000, y: null },
|
||||
{ x: 1548697920000, y: null },
|
||||
{ x: 1548698220000, y: null },
|
||||
{ x: 1548698520000, y: null },
|
||||
{ x: 1548698820000, y: null },
|
||||
{ x: 1548699120000, y: null },
|
||||
{ x: 1548699420000, y: null },
|
||||
{ x: 1548699720000, y: null },
|
||||
{ x: 1548700020000, y: null },
|
||||
{ x: 1548700320000, y: null },
|
||||
{ x: 1548700620000, y: null },
|
||||
{ x: 1548700920000, y: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: { key: 'auto-http-0XA8096548ECEB85B7', url: 'http://www.example.com/' },
|
||||
ping: {
|
||||
timestamp: '2019-01-28T18:43:07.078Z',
|
||||
monitor: {
|
||||
duration: { us: 4751074 },
|
||||
id: 'auto-http-0XA8096548ECEB85B7',
|
||||
ip: '198.71.248.67',
|
||||
name: '',
|
||||
status: 'down',
|
||||
},
|
||||
url: { full: 'http://www.example.com/' },
|
||||
},
|
||||
upSeries: [
|
||||
{ x: 1548697620000, y: null },
|
||||
{ x: 1548697920000, y: null },
|
||||
{ x: 1548698220000, y: null },
|
||||
{ x: 1548698520000, y: null },
|
||||
{ x: 1548698820000, y: null },
|
||||
{ x: 1548699120000, y: null },
|
||||
{ x: 1548699420000, y: null },
|
||||
{ x: 1548699720000, y: null },
|
||||
{ x: 1548700020000, y: null },
|
||||
{ x: 1548700320000, y: null },
|
||||
{ x: 1548700620000, y: null },
|
||||
{ x: 1548700920000, y: null },
|
||||
],
|
||||
downSeries: [
|
||||
{ x: 1548697620000, y: 57 },
|
||||
{ x: 1548697920000, y: 60 },
|
||||
{ x: 1548698220000, y: 61 },
|
||||
{ x: 1548698520000, y: 56 },
|
||||
{ x: 1548698820000, y: 45 },
|
||||
{ x: 1548699120000, y: 49 },
|
||||
{ x: 1548699420000, y: 60 },
|
||||
{ x: 1548699720000, y: 60 },
|
||||
{ x: 1548700020000, y: 64 },
|
||||
{ x: 1548700320000, y: 59 },
|
||||
{ x: 1548700620000, y: 60 },
|
||||
{ x: 1548700920000, y: 14 },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: { key: 'auto-http-0XC9CDA429418EDC2B', url: 'https://www.wikipedia.org/' },
|
||||
ping: {
|
||||
timestamp: '2019-01-28T18:42:55.074Z',
|
||||
monitor: {
|
||||
duration: { us: 1164812 },
|
||||
id: 'auto-http-0XC9CDA429418EDC2B',
|
||||
ip: '208.80.154.224',
|
||||
name: '',
|
||||
status: 'up',
|
||||
},
|
||||
url: { full: 'https://www.wikipedia.org/' },
|
||||
},
|
||||
upSeries: [
|
||||
{ x: 1548697620000, y: 5 },
|
||||
{ x: 1548697920000, y: 5 },
|
||||
{ x: 1548698220000, y: 5 },
|
||||
{ x: 1548698520000, y: 5 },
|
||||
{ x: 1548698820000, y: 5 },
|
||||
{ x: 1548699120000, y: 5 },
|
||||
{ x: 1548699420000, y: 5 },
|
||||
{ x: 1548699720000, y: 5 },
|
||||
{ x: 1548700020000, y: 5 },
|
||||
{ x: 1548700320000, y: 5 },
|
||||
{ x: 1548700620000, y: 5 },
|
||||
{ x: 1548700920000, y: 1 },
|
||||
],
|
||||
downSeries: [
|
||||
{ x: 1548697620000, y: null },
|
||||
{ x: 1548697920000, y: null },
|
||||
{ x: 1548698220000, y: null },
|
||||
{ x: 1548698520000, y: null },
|
||||
{ x: 1548698820000, y: null },
|
||||
{ x: 1548699120000, y: null },
|
||||
{ x: 1548699420000, y: null },
|
||||
{ x: 1548699720000, y: null },
|
||||
{ x: 1548700020000, y: null },
|
||||
{ x: 1548700320000, y: null },
|
||||
{ x: 1548700620000, y: null },
|
||||
{ x: 1548700920000, y: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: { key: 'auto-http-0XD9AE729FC1C1E04A', url: 'http://www.reddit.com/' },
|
||||
ping: {
|
||||
timestamp: '2019-01-28T18:43:13.074Z',
|
||||
monitor: {
|
||||
duration: { us: 299586 },
|
||||
id: 'auto-http-0XD9AE729FC1C1E04A',
|
||||
ip: '151.101.249.140',
|
||||
name: '',
|
||||
status: 'up',
|
||||
},
|
||||
url: { full: 'http://www.reddit.com/' },
|
||||
},
|
||||
upSeries: [
|
||||
{ x: 1548697620000, y: 79 },
|
||||
{ x: 1548697920000, y: 80 },
|
||||
{ x: 1548698220000, y: 86 },
|
||||
{ x: 1548698520000, y: 87 },
|
||||
{ x: 1548698820000, y: 81 },
|
||||
{ x: 1548699120000, y: 100 },
|
||||
{ x: 1548699420000, y: 100 },
|
||||
{ x: 1548699720000, y: 99 },
|
||||
{ x: 1548700020000, y: 96 },
|
||||
{ x: 1548700320000, y: 81 },
|
||||
{ x: 1548700620000, y: 80 },
|
||||
{ x: 1548700920000, y: 20 },
|
||||
],
|
||||
downSeries: [
|
||||
{ x: 1548697620000, y: null },
|
||||
{ x: 1548697920000, y: null },
|
||||
{ x: 1548698220000, y: null },
|
||||
{ x: 1548698520000, y: 1 },
|
||||
{ x: 1548698820000, y: null },
|
||||
{ x: 1548699120000, y: null },
|
||||
{ x: 1548699420000, y: null },
|
||||
{ x: 1548699720000, y: null },
|
||||
{ x: 1548700020000, y: null },
|
||||
{ x: 1548700320000, y: null },
|
||||
{ x: 1548700620000, y: null },
|
||||
{ x: 1548700920000, y: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: { key: 'auto-http-0XDD2D4E60FD4A61C3', url: 'https://www.elastic.co' },
|
||||
ping: {
|
||||
timestamp: '2019-01-28T18:43:13.074Z',
|
||||
monitor: {
|
||||
duration: { us: 850870 },
|
||||
id: 'auto-http-0XDD2D4E60FD4A61C3',
|
||||
ip: '151.101.250.217',
|
||||
name: '',
|
||||
status: 'up',
|
||||
},
|
||||
url: { full: 'https://www.elastic.co' },
|
||||
},
|
||||
upSeries: [
|
||||
{ x: 1548697620000, y: 79 },
|
||||
{ x: 1548697920000, y: 80 },
|
||||
{ x: 1548698220000, y: 86 },
|
||||
{ x: 1548698520000, y: 88 },
|
||||
{ x: 1548698820000, y: 81 },
|
||||
{ x: 1548699120000, y: 95 },
|
||||
{ x: 1548699420000, y: 94 },
|
||||
{ x: 1548699720000, y: 98 },
|
||||
{ x: 1548700020000, y: 93 },
|
||||
{ x: 1548700320000, y: 81 },
|
||||
{ x: 1548700620000, y: 80 },
|
||||
{ x: 1548700920000, y: 20 },
|
||||
],
|
||||
downSeries: [
|
||||
{ x: 1548697620000, y: null },
|
||||
{ x: 1548697920000, y: null },
|
||||
{ x: 1548698220000, y: null },
|
||||
{ x: 1548698520000, y: null },
|
||||
{ x: 1548698820000, y: null },
|
||||
{ x: 1548699120000, y: null },
|
||||
{ x: 1548699420000, y: null },
|
||||
{ x: 1548699720000, y: null },
|
||||
{ x: 1548700020000, y: null },
|
||||
{ x: 1548700320000, y: null },
|
||||
{ x: 1548700620000, y: null },
|
||||
{ x: 1548700920000, y: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: { key: 'auto-http-0XE3B163481423197D', url: 'https://news.google.com/' },
|
||||
ping: {
|
||||
timestamp: '2019-01-28T18:42:55.074Z',
|
||||
monitor: {
|
||||
duration: { us: 2059606 },
|
||||
id: 'auto-http-0XE3B163481423197D',
|
||||
ip: '216.58.219.206',
|
||||
name: '',
|
||||
status: 'up',
|
||||
},
|
||||
url: { full: 'https://news.google.com/' },
|
||||
},
|
||||
upSeries: [
|
||||
{ x: 1548697620000, y: 5 },
|
||||
{ x: 1548697920000, y: 5 },
|
||||
{ x: 1548698220000, y: 5 },
|
||||
{ x: 1548698520000, y: 5 },
|
||||
{ x: 1548698820000, y: 5 },
|
||||
{ x: 1548699120000, y: 5 },
|
||||
{ x: 1548699420000, y: 5 },
|
||||
{ x: 1548699720000, y: 5 },
|
||||
{ x: 1548700020000, y: 5 },
|
||||
{ x: 1548700320000, y: 5 },
|
||||
{ x: 1548700620000, y: 5 },
|
||||
{ x: 1548700920000, y: 1 },
|
||||
],
|
||||
downSeries: [
|
||||
{ x: 1548697620000, y: null },
|
||||
{ x: 1548697920000, y: null },
|
||||
{ x: 1548698220000, y: null },
|
||||
{ x: 1548698520000, y: null },
|
||||
{ x: 1548698820000, y: null },
|
||||
{ x: 1548699120000, y: null },
|
||||
{ x: 1548699420000, y: null },
|
||||
{ x: 1548699720000, y: null },
|
||||
{ x: 1548700020000, y: null },
|
||||
{ x: 1548700320000, y: null },
|
||||
{ x: 1548700620000, y: null },
|
||||
{ x: 1548700920000, y: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: { key: 'auto-tcp-0X81440A68E839814C', url: 'tcp://localhost:9200' },
|
||||
ping: {
|
||||
timestamp: '2019-01-28T18:43:16.078Z',
|
||||
monitor: {
|
||||
duration: { us: 3328 },
|
||||
id: 'auto-tcp-0X81440A68E839814C',
|
||||
ip: '127.0.0.1',
|
||||
name: '',
|
||||
status: 'up',
|
||||
},
|
||||
url: { full: 'tcp://localhost:9200' },
|
||||
},
|
||||
upSeries: [
|
||||
{ x: 1548697620000, y: 1 },
|
||||
{ x: 1548697920000, y: null },
|
||||
{ x: 1548698220000, y: 145 },
|
||||
{ x: 1548698520000, y: 300 },
|
||||
{ x: 1548698820000, y: 300 },
|
||||
{ x: 1548699120000, y: 300 },
|
||||
{ x: 1548699420000, y: 300 },
|
||||
{ x: 1548699720000, y: 300 },
|
||||
{ x: 1548700020000, y: 300 },
|
||||
{ x: 1548700320000, y: 300 },
|
||||
{ x: 1548700620000, y: 300 },
|
||||
{ x: 1548700920000, y: 77 },
|
||||
],
|
||||
downSeries: [
|
||||
{ x: 1548697620000, y: 293 },
|
||||
{ x: 1548697920000, y: 300 },
|
||||
{ x: 1548698220000, y: 155 },
|
||||
{ x: 1548698520000, y: null },
|
||||
{ x: 1548698820000, y: null },
|
||||
{ x: 1548699120000, y: null },
|
||||
{ x: 1548699420000, y: null },
|
||||
{ x: 1548699720000, y: null },
|
||||
{ x: 1548700020000, y: null },
|
||||
{ x: 1548700320000, y: null },
|
||||
{ x: 1548700620000, y: null },
|
||||
{ x: 1548700920000, y: null },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
it('renders a monitor list without errors', () => {
|
||||
const { monitors } = monitorResult;
|
||||
const component = shallowWithIntl(
|
||||
<MonitorList
|
||||
primaryColor="green"
|
||||
dangerColor="red"
|
||||
loading={false}
|
||||
monitors={monitors || []}
|
||||
/>
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* 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 { PingResults } from '../../../../common/graphql/types';
|
||||
import { PingList } from '../ping_list';
|
||||
|
||||
describe('PingList component', () => {
|
||||
let pingList: { allPings: PingResults };
|
||||
|
||||
beforeEach(() => {
|
||||
pingList = {
|
||||
allPings: {
|
||||
total: 9231,
|
||||
pings: [
|
||||
{
|
||||
timestamp: '2019-01-28T17:47:08.078Z',
|
||||
http: null,
|
||||
error: {
|
||||
message: 'dial tcp 127.0.0.1:9200: connect: connection refused',
|
||||
type: 'io',
|
||||
},
|
||||
monitor: {
|
||||
duration: { us: 1430 },
|
||||
id: 'auto-tcp-0X81440A68E839814C',
|
||||
ip: '127.0.0.1',
|
||||
name: '',
|
||||
scheme: null,
|
||||
status: 'down',
|
||||
type: 'tcp',
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamp: '2019-01-28T17:47:09.075Z',
|
||||
http: null,
|
||||
error: {
|
||||
message: 'dial tcp 127.0.0.1:9200: connect: connection refused',
|
||||
type: 'io',
|
||||
},
|
||||
monitor: {
|
||||
duration: { us: 1370 },
|
||||
id: 'auto-tcp-0X81440A68E839814C',
|
||||
ip: '127.0.0.1',
|
||||
name: '',
|
||||
scheme: null,
|
||||
status: 'down',
|
||||
type: 'tcp',
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamp: '2019-01-28T17:47:06.077Z',
|
||||
http: null,
|
||||
error: null,
|
||||
monitor: {
|
||||
duration: { us: 1452 },
|
||||
id: 'auto-tcp-0X81440A68E839814C',
|
||||
ip: '127.0.0.1',
|
||||
name: '',
|
||||
scheme: null,
|
||||
status: 'up',
|
||||
type: 'tcp',
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamp: '2019-01-28T17:47:07.075Z',
|
||||
http: null,
|
||||
error: {
|
||||
message: 'dial tcp 127.0.0.1:9200: connect: connection refused',
|
||||
type: 'io',
|
||||
},
|
||||
monitor: {
|
||||
duration: { us: 1094 },
|
||||
id: 'auto-tcp-0X81440A68E839814C',
|
||||
ip: '127.0.0.1',
|
||||
name: '',
|
||||
scheme: null,
|
||||
status: 'down',
|
||||
type: 'tcp',
|
||||
},
|
||||
},
|
||||
{
|
||||
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',
|
||||
},
|
||||
monitor: {
|
||||
duration: { us: 1597 },
|
||||
id: 'auto-http-0X3675F89EF0612091',
|
||||
ip: '127.0.0.1',
|
||||
name: '',
|
||||
scheme: null,
|
||||
status: 'down',
|
||||
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',
|
||||
},
|
||||
monitor: {
|
||||
duration: { us: 1699 },
|
||||
id: 'auto-tcp-0X81440A68E839814C',
|
||||
ip: '127.0.0.1',
|
||||
name: '',
|
||||
scheme: null,
|
||||
status: 'down',
|
||||
type: 'tcp',
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamp: '2019-01-28T17:47:19.076Z',
|
||||
http: null,
|
||||
error: {
|
||||
message: 'dial tcp 127.0.0.1:9200: connect: connection refused',
|
||||
type: 'io',
|
||||
},
|
||||
monitor: {
|
||||
duration: { us: 5384 },
|
||||
id: 'auto-tcp-0X81440A68E839814C',
|
||||
ip: '127.0.0.1',
|
||||
name: '',
|
||||
scheme: null,
|
||||
status: 'down',
|
||||
type: 'tcp',
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamp: '2019-01-28T17:47:19.076Z',
|
||||
http: null,
|
||||
error: {
|
||||
message:
|
||||
'Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused',
|
||||
type: 'io',
|
||||
},
|
||||
monitor: {
|
||||
duration: { us: 5397 },
|
||||
id: 'auto-http-0X3675F89EF0612091',
|
||||
ip: '127.0.0.1',
|
||||
name: '',
|
||||
scheme: null,
|
||||
status: 'down',
|
||||
type: 'http',
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamp: '2019-01-28T17:47:19.077Z',
|
||||
http: { response: { status_code: 200 } },
|
||||
error: null,
|
||||
monitor: {
|
||||
duration: { us: 127511 },
|
||||
id: 'auto-http-0X131221E73F825974',
|
||||
ip: '172.217.7.4',
|
||||
name: '',
|
||||
scheme: null,
|
||||
status: 'up',
|
||||
type: 'http',
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamp: '2019-01-28T17:47:19.077Z',
|
||||
http: { response: { status_code: 200 } },
|
||||
error: null,
|
||||
monitor: {
|
||||
duration: { us: 287543 },
|
||||
id: 'auto-http-0X9CB71300ABD5A2A8',
|
||||
ip: '192.30.253.112',
|
||||
name: '',
|
||||
scheme: null,
|
||||
status: 'up',
|
||||
type: 'http',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
it('renders sorted list without errors', () => {
|
||||
const { allPings } = pingList;
|
||||
const component = shallowWithIntl(
|
||||
<PingList
|
||||
loading={false}
|
||||
maxSearchSize={200}
|
||||
pingResults={allPings}
|
||||
searchSizeOnBlur={jest.fn()}
|
||||
selectedOption={{ label: 'All', value: '' }}
|
||||
selectedOptionChanged={jest.fn()}
|
||||
statusOptions={[{ label: 'All', value: '' }]}
|
||||
/>
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* 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 { Snapshot } from '../snapshot';
|
||||
|
||||
describe('Snapshot component', () => {
|
||||
const data = {
|
||||
snapshot: {
|
||||
up: 8,
|
||||
down: 2,
|
||||
total: 10,
|
||||
histogram: [
|
||||
{
|
||||
monitorId: 'auto-tcp-0X81440A68E839814C',
|
||||
data: [
|
||||
{ upCount: 1, downCount: 293, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: null, downCount: 300, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 145, downCount: 155, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 77, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0XD9AE729FC1C1E04A',
|
||||
data: [
|
||||
{ upCount: 79, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 80, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 86, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 87, downCount: 1, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 81, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 100, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 100, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 99, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 96, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 81, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 80, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 20, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0XDD2D4E60FD4A61C3',
|
||||
data: [
|
||||
{ upCount: 79, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 80, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 86, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 88, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 81, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 95, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 94, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 98, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 93, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 81, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 80, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 20, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0X131221E73F825974',
|
||||
data: [
|
||||
{ upCount: 74, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 73, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 74, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 19, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0X3675F89EF0612091',
|
||||
data: [
|
||||
{ upCount: null, downCount: 74, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: null, downCount: 19, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0X9CB71300ABD5A2A8',
|
||||
data: [
|
||||
{ upCount: 69, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 70, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 68, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 69, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 69, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 69, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 70, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 70, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 70, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 69, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 70, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 18, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0X970CBD2F2102BFA8',
|
||||
data: [
|
||||
{ upCount: 58, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 16, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0XA8096548ECEB85B7',
|
||||
data: [
|
||||
{ upCount: null, downCount: 57, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: null, downCount: 60, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: null, downCount: 61, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: null, downCount: 56, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: null, downCount: 45, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: null, downCount: 49, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: null, downCount: 60, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: null, downCount: 60, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: null, downCount: 64, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: null, downCount: 59, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: null, downCount: 60, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: null, downCount: 14, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0XC9CDA429418EDC2B',
|
||||
data: [
|
||||
{ upCount: 5, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 1, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0XE3B163481423197D',
|
||||
data: [
|
||||
{ upCount: 5, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 1, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
it('renders without errors', () => {
|
||||
const { snapshot } = data;
|
||||
const wrapper = shallowWithIntl(
|
||||
<Snapshot dangerColor="#F050F0" primaryColor="#000000" snapshot={snapshot} />
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* 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 { SnapshotHistogram } from '../snapshot_histogram';
|
||||
|
||||
describe('SnapshotHistogram component', () => {
|
||||
const props = {
|
||||
primaryColor: '#FEFEFE',
|
||||
dangerColor: '#FF00FF',
|
||||
histogram: [
|
||||
{
|
||||
monitorId: 'auto-tcp-0X81440A68E839814C',
|
||||
data: [
|
||||
{ upCount: 1, downCount: 293, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: null, downCount: 300, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 145, downCount: 155, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 300, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 77, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0XD9AE729FC1C1E04A',
|
||||
data: [
|
||||
{ upCount: 79, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 80, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 86, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 87, downCount: 1, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 81, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 100, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 100, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 99, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 96, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 81, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 80, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 20, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0XDD2D4E60FD4A61C3',
|
||||
data: [
|
||||
{ upCount: 79, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 80, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 86, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 88, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 81, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 95, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 94, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 98, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 93, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 81, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 80, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 20, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0X131221E73F825974',
|
||||
data: [
|
||||
{ upCount: 74, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 73, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 74, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 75, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 19, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0X3675F89EF0612091',
|
||||
data: [
|
||||
{ upCount: null, downCount: 74, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: null, downCount: 75, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: null, downCount: 19, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0X9CB71300ABD5A2A8',
|
||||
data: [
|
||||
{ upCount: 69, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 70, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 68, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 69, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 69, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 69, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 70, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 70, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 70, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 69, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 70, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 18, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0X970CBD2F2102BFA8',
|
||||
data: [
|
||||
{ upCount: 58, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 60, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 16, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0XA8096548ECEB85B7',
|
||||
data: [
|
||||
{ upCount: null, downCount: 57, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: null, downCount: 60, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: null, downCount: 61, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: null, downCount: 56, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: null, downCount: 45, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: null, downCount: 49, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: null, downCount: 60, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: null, downCount: 60, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: null, downCount: 64, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: null, downCount: 59, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: null, downCount: 60, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: null, downCount: 14, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0XC9CDA429418EDC2B',
|
||||
data: [
|
||||
{ upCount: 5, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 1, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'auto-http-0XE3B163481423197D',
|
||||
data: [
|
||||
{ upCount: 5, downCount: null, x: 1548697920000, x0: 1548697620000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548698220000, x0: 1548697920000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548698520000, x0: 1548698220000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548698820000, x0: 1548698520000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548699120000, x0: 1548698820000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548699420000, x0: 1548699120000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548699720000, x0: 1548699420000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700020000, x0: 1548699720000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700320000, x0: 1548700020000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700620000, x0: 1548700320000, y: 1 },
|
||||
{ upCount: 5, downCount: null, x: 1548700920000, x0: 1548700620000, y: 1 },
|
||||
{ upCount: 1, downCount: null, x: 1548701220000, x0: 1548700920000, y: 1 },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
it('renders the component without errors', () => {
|
||||
const component = shallowWithIntl(<SnapshotHistogram {...props} />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,686 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`EmptyState component doesn't render child components when count is falsey 1`] = `
|
||||
<Component
|
||||
intl={
|
||||
Object {
|
||||
"defaultFormats": Object {},
|
||||
"defaultLocale": "en",
|
||||
"formatDate": [Function],
|
||||
"formatHTMLMessage": [Function],
|
||||
"formatMessage": [Function],
|
||||
"formatNumber": [Function],
|
||||
"formatPlural": [Function],
|
||||
"formatRelative": [Function],
|
||||
"formatTime": [Function],
|
||||
"formats": Object {
|
||||
"date": Object {
|
||||
"full": Object {
|
||||
"day": "numeric",
|
||||
"month": "long",
|
||||
"weekday": "long",
|
||||
"year": "numeric",
|
||||
},
|
||||
"long": Object {
|
||||
"day": "numeric",
|
||||
"month": "long",
|
||||
"year": "numeric",
|
||||
},
|
||||
"medium": Object {
|
||||
"day": "numeric",
|
||||
"month": "short",
|
||||
"year": "numeric",
|
||||
},
|
||||
"short": Object {
|
||||
"day": "numeric",
|
||||
"month": "numeric",
|
||||
"year": "2-digit",
|
||||
},
|
||||
},
|
||||
"number": Object {
|
||||
"currency": Object {
|
||||
"style": "currency",
|
||||
},
|
||||
"percent": Object {
|
||||
"style": "percent",
|
||||
},
|
||||
},
|
||||
"relative": Object {
|
||||
"days": Object {
|
||||
"units": "day",
|
||||
},
|
||||
"hours": Object {
|
||||
"units": "hour",
|
||||
},
|
||||
"minutes": Object {
|
||||
"units": "minute",
|
||||
},
|
||||
"months": Object {
|
||||
"units": "month",
|
||||
},
|
||||
"seconds": Object {
|
||||
"units": "second",
|
||||
},
|
||||
"years": Object {
|
||||
"units": "year",
|
||||
},
|
||||
},
|
||||
"time": Object {
|
||||
"full": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
"second": "numeric",
|
||||
"timeZoneName": "short",
|
||||
},
|
||||
"long": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
"second": "numeric",
|
||||
"timeZoneName": "short",
|
||||
},
|
||||
"medium": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
"second": "numeric",
|
||||
},
|
||||
"short": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
},
|
||||
},
|
||||
},
|
||||
"formatters": Object {
|
||||
"getDateTimeFormat": [Function],
|
||||
"getMessageFormat": [Function],
|
||||
"getNumberFormat": [Function],
|
||||
"getPluralFormat": [Function],
|
||||
"getRelativeFormat": [Function],
|
||||
},
|
||||
"locale": "en",
|
||||
"messages": Object {},
|
||||
"now": [Function],
|
||||
"onError": [Function],
|
||||
"textComponent": Symbol(react.fragment),
|
||||
"timeZone": null,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Component>
|
||||
<EuiEmptyPrompt
|
||||
body={
|
||||
<React.Fragment>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="There is no uptime data available."
|
||||
id="xpack.uptime.emptyState.noDataDescription"
|
||||
values={Object {}}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="{configureHeartbeatLink} to start logging uptime data."
|
||||
id="xpack.uptime.emptyState.configureHeartbeatToGetStartedMessage"
|
||||
values={
|
||||
Object {
|
||||
"configureHeartbeatLink": <EuiLink
|
||||
color="primary"
|
||||
href="https://www.elastic.co/guide/en/beats/heartbeat/current/configuring-howto-heartbeat.html"
|
||||
target="_blank"
|
||||
type="button"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Configure Heartbeat"
|
||||
id="xpack.uptime.emptyState.configureHeartbeatLinkText"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiLink>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</React.Fragment>
|
||||
}
|
||||
iconColor="subdued"
|
||||
title={
|
||||
<EuiTitle
|
||||
size="l"
|
||||
textTransform="none"
|
||||
>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
defaultMessage="No Uptime Data"
|
||||
id="xpack.uptime.emptyState.noDataTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiEmptyPrompt"
|
||||
>
|
||||
<EuiTextColor
|
||||
color="subdued"
|
||||
component="span"
|
||||
>
|
||||
<span
|
||||
className="euiTextColor euiTextColor--subdued"
|
||||
>
|
||||
<EuiTitle
|
||||
size="m"
|
||||
textTransform="none"
|
||||
>
|
||||
<EuiTitle
|
||||
className="euiTitle euiTitle--medium"
|
||||
size="l"
|
||||
textTransform="none"
|
||||
>
|
||||
<h3
|
||||
className="euiTitle euiTitle--large euiTitle euiTitle--medium"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="No Uptime Data"
|
||||
id="xpack.uptime.emptyState.noDataTitle"
|
||||
values={Object {}}
|
||||
>
|
||||
No Uptime Data
|
||||
</FormattedMessage>
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
</EuiTitle>
|
||||
<EuiSpacer
|
||||
size="m"
|
||||
>
|
||||
<div
|
||||
className="euiSpacer euiSpacer--m"
|
||||
/>
|
||||
</EuiSpacer>
|
||||
<EuiText
|
||||
grow={true}
|
||||
size="m"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--medium"
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="There is no uptime data available."
|
||||
id="xpack.uptime.emptyState.noDataDescription"
|
||||
values={Object {}}
|
||||
>
|
||||
There is no uptime data available.
|
||||
</FormattedMessage>
|
||||
</p>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="{configureHeartbeatLink} to start logging uptime data."
|
||||
id="xpack.uptime.emptyState.configureHeartbeatToGetStartedMessage"
|
||||
values={
|
||||
Object {
|
||||
"configureHeartbeatLink": <EuiLink
|
||||
color="primary"
|
||||
href="https://www.elastic.co/guide/en/beats/heartbeat/current/configuring-howto-heartbeat.html"
|
||||
target="_blank"
|
||||
type="button"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Configure Heartbeat"
|
||||
id="xpack.uptime.emptyState.configureHeartbeatLinkText"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiLink>,
|
||||
}
|
||||
}
|
||||
>
|
||||
<EuiLink
|
||||
color="primary"
|
||||
href="https://www.elastic.co/guide/en/beats/heartbeat/current/configuring-howto-heartbeat.html"
|
||||
target="_blank"
|
||||
type="button"
|
||||
>
|
||||
<a
|
||||
className="euiLink euiLink--primary"
|
||||
href="https://www.elastic.co/guide/en/beats/heartbeat/current/configuring-howto-heartbeat.html"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Configure Heartbeat"
|
||||
id="xpack.uptime.emptyState.configureHeartbeatLinkText"
|
||||
values={Object {}}
|
||||
>
|
||||
Configure Heartbeat
|
||||
</FormattedMessage>
|
||||
</a>
|
||||
</EuiLink>
|
||||
to start logging uptime data.
|
||||
</FormattedMessage>
|
||||
</p>
|
||||
</div>
|
||||
</EuiText>
|
||||
</span>
|
||||
</EuiTextColor>
|
||||
</div>
|
||||
</EuiEmptyPrompt>
|
||||
</Component>
|
||||
</Component>
|
||||
`;
|
||||
|
||||
exports[`EmptyState component renders child components when count is truthy 1`] = `
|
||||
<Fragment>
|
||||
<div>
|
||||
Foo
|
||||
</div>
|
||||
<div>
|
||||
Bar
|
||||
</div>
|
||||
<div>
|
||||
Baz
|
||||
</div>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`EmptyState component renders message while loading 1`] = `
|
||||
<Component
|
||||
count={1}
|
||||
intl={
|
||||
Object {
|
||||
"defaultFormats": Object {},
|
||||
"defaultLocale": "en",
|
||||
"formatDate": [Function],
|
||||
"formatHTMLMessage": [Function],
|
||||
"formatMessage": [Function],
|
||||
"formatNumber": [Function],
|
||||
"formatPlural": [Function],
|
||||
"formatRelative": [Function],
|
||||
"formatTime": [Function],
|
||||
"formats": Object {
|
||||
"date": Object {
|
||||
"full": Object {
|
||||
"day": "numeric",
|
||||
"month": "long",
|
||||
"weekday": "long",
|
||||
"year": "numeric",
|
||||
},
|
||||
"long": Object {
|
||||
"day": "numeric",
|
||||
"month": "long",
|
||||
"year": "numeric",
|
||||
},
|
||||
"medium": Object {
|
||||
"day": "numeric",
|
||||
"month": "short",
|
||||
"year": "numeric",
|
||||
},
|
||||
"short": Object {
|
||||
"day": "numeric",
|
||||
"month": "numeric",
|
||||
"year": "2-digit",
|
||||
},
|
||||
},
|
||||
"number": Object {
|
||||
"currency": Object {
|
||||
"style": "currency",
|
||||
},
|
||||
"percent": Object {
|
||||
"style": "percent",
|
||||
},
|
||||
},
|
||||
"relative": Object {
|
||||
"days": Object {
|
||||
"units": "day",
|
||||
},
|
||||
"hours": Object {
|
||||
"units": "hour",
|
||||
},
|
||||
"minutes": Object {
|
||||
"units": "minute",
|
||||
},
|
||||
"months": Object {
|
||||
"units": "month",
|
||||
},
|
||||
"seconds": Object {
|
||||
"units": "second",
|
||||
},
|
||||
"years": Object {
|
||||
"units": "year",
|
||||
},
|
||||
},
|
||||
"time": Object {
|
||||
"full": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
"second": "numeric",
|
||||
"timeZoneName": "short",
|
||||
},
|
||||
"long": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
"second": "numeric",
|
||||
"timeZoneName": "short",
|
||||
},
|
||||
"medium": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
"second": "numeric",
|
||||
},
|
||||
"short": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
},
|
||||
},
|
||||
},
|
||||
"formatters": Object {
|
||||
"getDateTimeFormat": [Function],
|
||||
"getMessageFormat": [Function],
|
||||
"getNumberFormat": [Function],
|
||||
"getPluralFormat": [Function],
|
||||
"getRelativeFormat": [Function],
|
||||
},
|
||||
"locale": "en",
|
||||
"messages": Object {},
|
||||
"now": [Function],
|
||||
"onError": [Function],
|
||||
"textComponent": Symbol(react.fragment),
|
||||
"timeZone": null,
|
||||
}
|
||||
}
|
||||
loading={true}
|
||||
>
|
||||
<Component>
|
||||
<EuiEmptyPrompt
|
||||
iconColor="subdued"
|
||||
title={
|
||||
<EuiFlexGroup
|
||||
alignItems="stretch"
|
||||
component="div"
|
||||
direction="row"
|
||||
gutterSize="l"
|
||||
justifyContent="flexStart"
|
||||
responsive={true}
|
||||
wrap={false}
|
||||
>
|
||||
<EuiFlexItem
|
||||
component="div"
|
||||
grow={true}
|
||||
>
|
||||
<EuiTitle
|
||||
size="l"
|
||||
textTransform="none"
|
||||
>
|
||||
<h3>
|
||||
Loading…
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem
|
||||
component="div"
|
||||
grow={true}
|
||||
>
|
||||
<EuiLoadingSpinner
|
||||
size="xl"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiEmptyPrompt"
|
||||
>
|
||||
<EuiTextColor
|
||||
color="subdued"
|
||||
component="span"
|
||||
>
|
||||
<span
|
||||
className="euiTextColor euiTextColor--subdued"
|
||||
>
|
||||
<EuiTitle
|
||||
size="m"
|
||||
textTransform="none"
|
||||
>
|
||||
<EuiFlexGroup
|
||||
alignItems="stretch"
|
||||
className="euiTitle euiTitle--medium"
|
||||
component="div"
|
||||
direction="row"
|
||||
gutterSize="l"
|
||||
justifyContent="flexStart"
|
||||
responsive={true}
|
||||
wrap={false}
|
||||
>
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow euiFlexGroup--responsive euiTitle euiTitle--medium"
|
||||
>
|
||||
<EuiFlexItem
|
||||
component="div"
|
||||
grow={true}
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<EuiTitle
|
||||
size="l"
|
||||
textTransform="none"
|
||||
>
|
||||
<h3
|
||||
className="euiTitle euiTitle--large"
|
||||
>
|
||||
Loading…
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem
|
||||
component="div"
|
||||
grow={true}
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<EuiLoadingSpinner
|
||||
size="xl"
|
||||
>
|
||||
<div
|
||||
className="euiLoadingSpinner euiLoadingSpinner--xLarge"
|
||||
/>
|
||||
</EuiLoadingSpinner>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</div>
|
||||
</EuiFlexGroup>
|
||||
</EuiTitle>
|
||||
<EuiSpacer
|
||||
size="m"
|
||||
>
|
||||
<div
|
||||
className="euiSpacer euiSpacer--m"
|
||||
/>
|
||||
</EuiSpacer>
|
||||
</span>
|
||||
</EuiTextColor>
|
||||
</div>
|
||||
</EuiEmptyPrompt>
|
||||
</Component>
|
||||
</Component>
|
||||
`;
|
||||
|
||||
exports[`EmptyState component renders the message when an error occurs 1`] = `
|
||||
<Component
|
||||
count={1}
|
||||
error="An error occurred"
|
||||
intl={
|
||||
Object {
|
||||
"defaultFormats": Object {},
|
||||
"defaultLocale": "en",
|
||||
"formatDate": [Function],
|
||||
"formatHTMLMessage": [Function],
|
||||
"formatMessage": [Function],
|
||||
"formatNumber": [Function],
|
||||
"formatPlural": [Function],
|
||||
"formatRelative": [Function],
|
||||
"formatTime": [Function],
|
||||
"formats": Object {
|
||||
"date": Object {
|
||||
"full": Object {
|
||||
"day": "numeric",
|
||||
"month": "long",
|
||||
"weekday": "long",
|
||||
"year": "numeric",
|
||||
},
|
||||
"long": Object {
|
||||
"day": "numeric",
|
||||
"month": "long",
|
||||
"year": "numeric",
|
||||
},
|
||||
"medium": Object {
|
||||
"day": "numeric",
|
||||
"month": "short",
|
||||
"year": "numeric",
|
||||
},
|
||||
"short": Object {
|
||||
"day": "numeric",
|
||||
"month": "numeric",
|
||||
"year": "2-digit",
|
||||
},
|
||||
},
|
||||
"number": Object {
|
||||
"currency": Object {
|
||||
"style": "currency",
|
||||
},
|
||||
"percent": Object {
|
||||
"style": "percent",
|
||||
},
|
||||
},
|
||||
"relative": Object {
|
||||
"days": Object {
|
||||
"units": "day",
|
||||
},
|
||||
"hours": Object {
|
||||
"units": "hour",
|
||||
},
|
||||
"minutes": Object {
|
||||
"units": "minute",
|
||||
},
|
||||
"months": Object {
|
||||
"units": "month",
|
||||
},
|
||||
"seconds": Object {
|
||||
"units": "second",
|
||||
},
|
||||
"years": Object {
|
||||
"units": "year",
|
||||
},
|
||||
},
|
||||
"time": Object {
|
||||
"full": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
"second": "numeric",
|
||||
"timeZoneName": "short",
|
||||
},
|
||||
"long": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
"second": "numeric",
|
||||
"timeZoneName": "short",
|
||||
},
|
||||
"medium": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
"second": "numeric",
|
||||
},
|
||||
"short": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
},
|
||||
},
|
||||
},
|
||||
"formatters": Object {
|
||||
"getDateTimeFormat": [Function],
|
||||
"getMessageFormat": [Function],
|
||||
"getNumberFormat": [Function],
|
||||
"getPluralFormat": [Function],
|
||||
"getRelativeFormat": [Function],
|
||||
},
|
||||
"locale": "en",
|
||||
"messages": Object {},
|
||||
"now": [Function],
|
||||
"onError": [Function],
|
||||
"textComponent": Symbol(react.fragment),
|
||||
"timeZone": null,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Component
|
||||
errorMessage="An error occurred"
|
||||
>
|
||||
<EuiEmptyPrompt
|
||||
body={
|
||||
<p>
|
||||
An error occurred
|
||||
</p>
|
||||
}
|
||||
iconColor="subdued"
|
||||
title={
|
||||
<EuiTitle
|
||||
size="l"
|
||||
textTransform="none"
|
||||
>
|
||||
<h3>
|
||||
Error
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiEmptyPrompt"
|
||||
>
|
||||
<EuiTextColor
|
||||
color="subdued"
|
||||
component="span"
|
||||
>
|
||||
<span
|
||||
className="euiTextColor euiTextColor--subdued"
|
||||
>
|
||||
<EuiTitle
|
||||
size="m"
|
||||
textTransform="none"
|
||||
>
|
||||
<EuiTitle
|
||||
className="euiTitle euiTitle--medium"
|
||||
size="l"
|
||||
textTransform="none"
|
||||
>
|
||||
<h3
|
||||
className="euiTitle euiTitle--large euiTitle euiTitle--medium"
|
||||
>
|
||||
Error
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
</EuiTitle>
|
||||
<EuiSpacer
|
||||
size="m"
|
||||
>
|
||||
<div
|
||||
className="euiSpacer euiSpacer--m"
|
||||
/>
|
||||
</EuiSpacer>
|
||||
<EuiText
|
||||
grow={true}
|
||||
size="m"
|
||||
>
|
||||
<div
|
||||
className="euiText euiText--medium"
|
||||
>
|
||||
<p>
|
||||
An error occurred
|
||||
</p>
|
||||
</div>
|
||||
</EuiText>
|
||||
</span>
|
||||
</EuiTextColor>
|
||||
</div>
|
||||
</EuiEmptyPrompt>
|
||||
</Component>
|
||||
</Component>
|
||||
`;
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import { EmptyState } from '../empty_state';
|
||||
|
||||
describe('EmptyState component', () => {
|
||||
it('renders child components when count is truthy', () => {
|
||||
const component = shallowWithIntl(
|
||||
<EmptyState count={1}>
|
||||
<div>Foo</div>
|
||||
<div>Bar</div>
|
||||
<div>Baz</div>
|
||||
</EmptyState>
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
it(`doesn't render child components when count is falsey`, () => {
|
||||
const component = mountWithIntl(
|
||||
<EmptyState count={undefined}>
|
||||
<div>Shouldn't be rendered</div>
|
||||
</EmptyState>
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
it(`renders the message when an error occurs`, () => {
|
||||
const component = mountWithIntl(
|
||||
<EmptyState error={'An error occurred'} count={1}>
|
||||
<div>Shouldn't appear...</div>
|
||||
</EmptyState>
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
it('renders message while loading', () => {
|
||||
const component = mountWithIntl(
|
||||
<EmptyState loading={true} count={1}>
|
||||
<div>Shouldn't appear...</div>
|
||||
</EmptyState>
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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 { EuiEmptyPrompt, EuiLink, EuiTitle } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React, { Fragment } from 'react';
|
||||
|
||||
export const EmptyIndex = (props: any) => (
|
||||
<EuiEmptyPrompt
|
||||
title={
|
||||
<EuiTitle size="l">
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.emptyState.noDataTitle"
|
||||
defaultMessage="No Uptime Data"
|
||||
/>
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
}
|
||||
body={
|
||||
<Fragment>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.emptyState.noDataDescription"
|
||||
defaultMessage="There is no uptime data available."
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.emptyState.configureHeartbeatToGetStartedMessage"
|
||||
defaultMessage="{configureHeartbeatLink} to start logging uptime data."
|
||||
values={{
|
||||
configureHeartbeatLink: (
|
||||
<EuiLink
|
||||
target="_blank"
|
||||
href="https://www.elastic.co/guide/en/beats/heartbeat/current/configuring-howto-heartbeat.html"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.emptyState.configureHeartbeatLinkText"
|
||||
defaultMessage="Configure Heartbeat"
|
||||
/>
|
||||
</EuiLink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
</Fragment>
|
||||
}
|
||||
/>
|
||||
);
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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, { Fragment } from 'react';
|
||||
import { EmptyIndex } from './empty_index';
|
||||
import { EmptyStateError } from './empty_state_error';
|
||||
import { EmptyStateLoading } from './empty_state_loading';
|
||||
|
||||
interface EmptyStateProps {
|
||||
children: JSX.Element[] | JSX.Element;
|
||||
count: number | undefined;
|
||||
error?: string;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
export const EmptyState = ({ children, count, error, loading }: EmptyStateProps) => {
|
||||
if (error) {
|
||||
return <EmptyStateError errorMessage={error} />;
|
||||
}
|
||||
if (loading) {
|
||||
return <EmptyStateLoading />;
|
||||
} else if (!count) {
|
||||
return <EmptyIndex />;
|
||||
}
|
||||
return <Fragment>{children}</Fragment>;
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 { EuiEmptyPrompt, EuiTitle } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
|
||||
interface EmptyStateErrorProps {
|
||||
errorMessage?: string;
|
||||
}
|
||||
|
||||
export const EmptyStateError = ({ errorMessage }: EmptyStateErrorProps) => (
|
||||
<EuiEmptyPrompt
|
||||
title={
|
||||
<EuiTitle size="l">
|
||||
<h3>
|
||||
{i18n.translate('xpack.uptime.emptyStateError.title', {
|
||||
defaultMessage: 'Error',
|
||||
})}
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
}
|
||||
body={<p>{errorMessage ? errorMessage : ''}</p>}
|
||||
/>
|
||||
);
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 {
|
||||
EuiEmptyPrompt,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiLoadingSpinner,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
|
||||
export const EmptyStateLoading = (props: any) => (
|
||||
<EuiEmptyPrompt
|
||||
title={
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiTitle size="l">
|
||||
<h3>
|
||||
{i18n.translate('xpack.uptime.emptyState.loadingMessage', {
|
||||
defaultMessage: 'Loading…',
|
||||
})}
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiLoadingSpinner size="xl" />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
}
|
||||
/>
|
||||
);
|
|
@ -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 { EmptyState } from './empty_state';
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
|
@ -16,7 +17,14 @@ export const EmptyStatusBar = ({ message, monitorId }: Props) => (
|
|||
<EuiPanel>
|
||||
<EuiFlexGroup gutterSize="l">
|
||||
<EuiFlexItem grow={false}>
|
||||
{!message ? `No data found for monitor id ${monitorId}` : message}
|
||||
{!message
|
||||
? i18n.translate('xpack.uptime.emptyStatusBar.defaultMessage', {
|
||||
defaultMessage: 'No data found for monitor id {monitorId}',
|
||||
description:
|
||||
'This is the default message we display in a status bar when there is no data available for an uptime monitor.',
|
||||
values: { monitorId },
|
||||
})
|
||||
: message}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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 typings
|
||||
import { EuiInMemoryTable, EuiPanel, 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 { Link } from 'react-router-dom';
|
||||
import { ErrorListItem } from '../../../common/graphql/types';
|
||||
|
||||
interface ErrorListProps {
|
||||
loading: boolean;
|
||||
errorList: ErrorListItem[];
|
||||
}
|
||||
|
||||
export const ErrorList = ({ loading, errorList }: ErrorListProps) => (
|
||||
<Fragment>
|
||||
<EuiTitle size="xs">
|
||||
<h5>
|
||||
<FormattedMessage id="xpack.uptime.errorList.title" defaultMessage="Error list" />
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
<EuiPanel>
|
||||
<EuiInMemoryTable
|
||||
loading={loading}
|
||||
items={errorList}
|
||||
columns={[
|
||||
{
|
||||
field: 'type',
|
||||
name: i18n.translate('xpack.uptime.errorList.errorTypeColumnLabel', {
|
||||
defaultMessage: 'Error type',
|
||||
}),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'monitorId',
|
||||
name: i18n.translate('xpack.uptime.errorList.monitorIdColumnLabel', {
|
||||
defaultMessage: 'Monitor ID',
|
||||
}),
|
||||
render: (id: string) => <Link to={`/monitor/${id}`}>{id}</Link>,
|
||||
sortable: true,
|
||||
width: '25%',
|
||||
},
|
||||
{
|
||||
field: 'count',
|
||||
name: i18n.translate('xpack.uptime.errorList.CountColumnLabel', {
|
||||
defaultMessage: 'Count',
|
||||
}),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'timestamp',
|
||||
name: i18n.translate('xpack.uptime.errorList.latestErrorColumnLabel', {
|
||||
defaultMessage: 'Latest error',
|
||||
}),
|
||||
sortable: true,
|
||||
render: (timestamp: string) => moment(timestamp).fromNow(),
|
||||
},
|
||||
{
|
||||
field: 'statusCode',
|
||||
name: i18n.translate('xpack.uptime.errorList.statusCodeColumnLabel', {
|
||||
defaultMessage: 'Status code',
|
||||
}),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'latestMessage',
|
||||
name: i18n.translate('xpack.uptime.errorList.latestMessageColumnLabel', {
|
||||
defaultMessage: 'Latest message',
|
||||
}),
|
||||
sortable: true,
|
||||
width: '40%',
|
||||
},
|
||||
]}
|
||||
sorting={true}
|
||||
pagination={{ initialPageSize: 10, pageSizeOptions: [5, 10, 20, 50] }}
|
||||
/>
|
||||
</EuiPanel>
|
||||
</Fragment>
|
||||
);
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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 No typings for EuiSearchBar
|
||||
import { EuiFlexGroup, EuiFlexItem, 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 { filterBarSearchSchema } from './search_schema';
|
||||
|
||||
interface FilterBarProps {
|
||||
filterBar: FilterBarType;
|
||||
updateQuery: (query: object | undefined) => void;
|
||||
}
|
||||
|
||||
const SEARCH_THRESHOLD = 2;
|
||||
|
||||
export const FilterBar = ({
|
||||
filterBar: { names, ports, ids, schemes },
|
||||
updateQuery,
|
||||
}: FilterBarProps) => {
|
||||
// TODO: add a factory function + type for these filter options
|
||||
const filters = [
|
||||
{
|
||||
type: 'field_value_toggle_group',
|
||||
field: 'monitor.status',
|
||||
items: [
|
||||
{
|
||||
value: 'up',
|
||||
name: i18n.translate('xpack.uptime.filterBar.filterUpLabel', {
|
||||
defaultMessage: 'Up',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: 'down',
|
||||
name: i18n.translate('xpack.uptime.filterBar.filterDownLabel', {
|
||||
defaultMessage: 'Down',
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
// TODO: add health to this select
|
||||
{
|
||||
type: 'field_value_selection',
|
||||
field: 'monitor.id',
|
||||
name: i18n.translate('xpack.uptime.filterBar.options.idLabel', {
|
||||
defaultMessage: 'ID',
|
||||
}),
|
||||
multiSelect: false,
|
||||
options: ids
|
||||
? ids.map(({ key }: MonitorKey) => ({
|
||||
value: key,
|
||||
view: key,
|
||||
}))
|
||||
: [],
|
||||
searchThreshold: SEARCH_THRESHOLD,
|
||||
},
|
||||
{
|
||||
type: 'field_value_selection',
|
||||
field: 'monitor.name',
|
||||
name: i18n.translate('xpack.uptime.filterBar.options.nameLabel', {
|
||||
defaultMessage: 'Name',
|
||||
}),
|
||||
multiSelect: false,
|
||||
options: names
|
||||
? names.map((nameValue: string) => ({ value: nameValue, view: nameValue }))
|
||||
: [],
|
||||
searchThreshold: SEARCH_THRESHOLD,
|
||||
},
|
||||
{
|
||||
type: 'field_value_selection',
|
||||
field: 'url.full',
|
||||
name: i18n.translate('xpack.uptime.filterBar.options.urlLabel', {
|
||||
defaultMessage: 'URL',
|
||||
}),
|
||||
multiSelect: false,
|
||||
options: ids ? ids.map(({ url }: MonitorKey) => ({ value: url, view: url })) : [],
|
||||
searchThreshold: SEARCH_THRESHOLD,
|
||||
},
|
||||
{
|
||||
type: 'field_value_selection',
|
||||
field: 'url.port',
|
||||
name: i18n.translate('xpack.uptime.filterBar.options.portLabel', {
|
||||
defaultMessage: 'Port',
|
||||
}),
|
||||
multiSelect: false,
|
||||
options: ports
|
||||
? ports.map((portValue: any) => ({
|
||||
value: portValue,
|
||||
view: portValue,
|
||||
}))
|
||||
: [],
|
||||
searchThreshold: SEARCH_THRESHOLD,
|
||||
},
|
||||
{
|
||||
type: 'field_value_selection',
|
||||
field: 'monitor.type',
|
||||
name: i18n.translate('xpack.uptime.filterBar.options.typeLabel', {
|
||||
defaultMessage: 'Type',
|
||||
}),
|
||||
multiSelect: false,
|
||||
options: schemes
|
||||
? schemes.map((schemeValue: string) => ({
|
||||
value: schemeValue,
|
||||
view: schemeValue,
|
||||
}))
|
||||
: [],
|
||||
searchThreshold: SEARCH_THRESHOLD,
|
||||
},
|
||||
];
|
||||
return (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow>
|
||||
<EuiSearchBar
|
||||
// TODO: update typing
|
||||
onChange={({ query }: { query?: { text: string } }) => {
|
||||
try {
|
||||
let esQuery;
|
||||
if (query && query.text) {
|
||||
esQuery = EuiSearchBar.Query.toESQuery(query);
|
||||
}
|
||||
updateQuery(esQuery);
|
||||
} catch (e) {
|
||||
updateQuery(undefined);
|
||||
}
|
||||
}}
|
||||
filters={filters}
|
||||
schema={filterBarSearchSchema}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
|
@ -4,9 +4,15 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { EmptyState } from './empty_state';
|
||||
export { EmptyStatusBar } from './empty_status_bar';
|
||||
export { ErrorList } from './error_list';
|
||||
export { FilterBar } from './filter_bar';
|
||||
export { FilterBarLoading } from './filter_bar_loading';
|
||||
export { MonitorList } from './monitor_list';
|
||||
export { MonitorPageTitle } from './monitor_page_title';
|
||||
export { MonitorStatusBar } from './monitor_status_bar';
|
||||
export { PingList } from './ping_list';
|
||||
export { Snapshot } from './snapshot';
|
||||
export { SnapshotHistogram } from './snapshot_histogram';
|
||||
export { SnapshotLoading } from './snapshot_loading';
|
||||
export { StatusBar } from './status_bar';
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* 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 {
|
||||
EuiHealth,
|
||||
// @ts-ignore missing type definition
|
||||
EuiHistogramSeries,
|
||||
// @ts-ignore missing type definition
|
||||
EuiInMemoryTable,
|
||||
EuiLink,
|
||||
EuiPanel,
|
||||
// @ts-ignore missing type definition
|
||||
EuiSeriesChart,
|
||||
// @ts-ignore missing type definition
|
||||
EuiSeriesChartUtils,
|
||||
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 { Link } from 'react-router-dom';
|
||||
import { LatestMonitor } from '../../../common/graphql/types';
|
||||
import { formatSparklineCounts } from './format_sparkline_counts';
|
||||
|
||||
interface MonitorListProps {
|
||||
primaryColor: string;
|
||||
dangerColor: string;
|
||||
loading: boolean;
|
||||
monitors: LatestMonitor[];
|
||||
}
|
||||
|
||||
const MONITOR_LIST_DEFAULT_PAGINATION = 10;
|
||||
|
||||
const monitorListPagination = {
|
||||
initialPageSize: MONITOR_LIST_DEFAULT_PAGINATION,
|
||||
pageSizeOptions: [5, 10, 20, 50],
|
||||
};
|
||||
|
||||
export const MonitorList = ({ dangerColor, loading, monitors, primaryColor }: MonitorListProps) => (
|
||||
<Fragment>
|
||||
<EuiTitle size="xs">
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.monitorList.monitoringStatusTitle"
|
||||
defaultMessage="Monitor status"
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
<EuiPanel paddingSize="l">
|
||||
<EuiInMemoryTable
|
||||
columns={[
|
||||
{
|
||||
field: 'ping.monitor.status',
|
||||
name: i18n.translate('xpack.uptime.monitorList.statusColumnLabel', {
|
||||
defaultMessage: 'Status',
|
||||
}),
|
||||
render: (status: string) => (
|
||||
<EuiHealth color={status === 'up' ? 'success' : 'danger'}>
|
||||
{status === 'up'
|
||||
? i18n.translate('xpack.uptime.monitorList.statusColumn.upLabel', {
|
||||
defaultMessage: 'Up',
|
||||
})
|
||||
: i18n.translate('xpack.uptime.monitorList.statusColumn.downLabel', {
|
||||
defaultMessage: 'Down',
|
||||
})}
|
||||
</EuiHealth>
|
||||
),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'ping.timestamp',
|
||||
name: i18n.translate('xpack.uptime.monitorList.lastUpdatedColumnLabel', {
|
||||
defaultMessage: 'Last updated',
|
||||
}),
|
||||
render: (timestamp: string) => moment(timestamp).fromNow(),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'ping.monitor.id',
|
||||
name: i18n.translate('xpack.uptime.monitorList.idColumnLabel', {
|
||||
defaultMessage: 'ID',
|
||||
}),
|
||||
render: (id: string, monitor: LatestMonitor) => (
|
||||
<Link to={`/monitor/${id}`}>
|
||||
{monitor.ping && monitor.ping.monitor && monitor.ping.monitor.name
|
||||
? monitor.ping.monitor.name
|
||||
: id}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'ping.url.full',
|
||||
name: i18n.translate('xpack.uptime.monitorList.urlColumnLabel', {
|
||||
defaultMessage: 'URL',
|
||||
}),
|
||||
render: (url: string) => (
|
||||
<EuiLink href={url} target="_blank">
|
||||
{url}
|
||||
</EuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'ping.monitor.ip',
|
||||
name: i18n.translate('xpack.uptime.monitorList.ipColumnLabel', {
|
||||
defaultMessage: 'IP',
|
||||
}),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'upSeries',
|
||||
name: i18n.translate('xpack.uptime.monitorList.monitorHistoryColumnLabel', {
|
||||
defaultMessage: 'Monitor History',
|
||||
}),
|
||||
// @ts-ignore TODO fix typing
|
||||
render: (upSeries, monitor) => {
|
||||
const { downSeries } = monitor;
|
||||
return (
|
||||
<EuiSeriesChart
|
||||
showDefaultAxis={false}
|
||||
height={70}
|
||||
stackBy="y"
|
||||
// TODO: style hack
|
||||
style={{ marginBottom: '-20px' }}
|
||||
xType={EuiSeriesChartUtils.SCALE.TIME}
|
||||
>
|
||||
<EuiHistogramSeries
|
||||
data={formatSparklineCounts(downSeries)}
|
||||
name={i18n.translate('xpack.uptime.monitorList.downLineSeries.downLabel', {
|
||||
defaultMessage: 'Down',
|
||||
})}
|
||||
color={dangerColor}
|
||||
/>
|
||||
<EuiHistogramSeries
|
||||
data={formatSparklineCounts(upSeries)}
|
||||
name={i18n.translate('xpack.uptime.monitorList.upLineSeries.upLabel', {
|
||||
defaultMessage: 'Up',
|
||||
})}
|
||||
color={primaryColor}
|
||||
/>
|
||||
</EuiSeriesChart>
|
||||
);
|
||||
},
|
||||
},
|
||||
]}
|
||||
loading={loading}
|
||||
items={monitors}
|
||||
pagination={monitorListPagination}
|
||||
sorting={true}
|
||||
/>
|
||||
</EuiPanel>
|
||||
</Fragment>
|
||||
);
|
|
@ -17,7 +17,7 @@ interface Props {
|
|||
timestamp?: string;
|
||||
}
|
||||
|
||||
export const StatusBar = ({ timestamp, url, duration, status }: Props) => (
|
||||
export const MonitorStatusBar = ({ timestamp, url, duration, status }: Props) => (
|
||||
<EuiPanel>
|
||||
<EuiFlexGroup gutterSize="l">
|
||||
<EuiFlexItem grow={false}>
|
205
x-pack/plugins/uptime/public/components/functional/ping_list.tsx
Normal file
205
x-pack/plugins/uptime/public/components/functional/ping_list.tsx
Normal file
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* 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 {
|
||||
EuiBadge,
|
||||
EuiComboBox,
|
||||
EuiComboBoxOptionProps,
|
||||
EuiFieldNumber,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiHealth,
|
||||
// @ts-ignore
|
||||
EuiInMemoryTable,
|
||||
EuiPanel,
|
||||
EuiTitle,
|
||||
EuiToolTip,
|
||||
} 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 { Ping, PingResults } from '../../../common/graphql/types';
|
||||
|
||||
interface PingListProps {
|
||||
loading: boolean;
|
||||
maxSearchSize: number;
|
||||
pingResults: PingResults;
|
||||
searchSizeOnBlur: (e: React.FocusEvent<HTMLInputElement>) => void;
|
||||
selectedOption: EuiComboBoxOptionProps;
|
||||
selectedOptionChanged: (selectedOptions: EuiComboBoxOptionProps[]) => void;
|
||||
statusOptions: EuiComboBoxOptionProps[];
|
||||
}
|
||||
|
||||
export const PingList = ({
|
||||
loading,
|
||||
maxSearchSize,
|
||||
pingResults,
|
||||
searchSizeOnBlur,
|
||||
selectedOption,
|
||||
selectedOptionChanged,
|
||||
statusOptions,
|
||||
}: PingListProps) => {
|
||||
const columns = [
|
||||
{
|
||||
field: 'monitor.status',
|
||||
name: i18n.translate('xpack.uptime.pingList.statusColumnLabel', {
|
||||
defaultMessage: 'Status',
|
||||
}),
|
||||
render: (pingStatus: string) => (
|
||||
<EuiHealth color={pingStatus === 'up' ? 'success' : 'danger'}>
|
||||
{pingStatus === 'up'
|
||||
? i18n.translate('xpack.uptime.pingList.statusColumnHealthUpLabel', {
|
||||
defaultMessage: 'Up',
|
||||
})
|
||||
: i18n.translate('xpack.uptime.pingList.statusColumnHealthDownLabel', {
|
||||
defaultMessage: 'Down',
|
||||
})}
|
||||
</EuiHealth>
|
||||
),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'timestamp',
|
||||
name: i18n.translate('xpack.uptime.pingList.timestampColumnLabel', {
|
||||
defaultMessage: 'Timestamp',
|
||||
}),
|
||||
sortable: true,
|
||||
render: (timestamp: string) => moment(timestamp).fromNow(),
|
||||
},
|
||||
{
|
||||
field: 'monitor.ip',
|
||||
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',
|
||||
}),
|
||||
render: (duration: number) => duration / 1000,
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'error.type',
|
||||
name: i18n.translate('xpack.uptime.pingList.errorTypeColumnLabel', {
|
||||
defaultMessage: 'Error type',
|
||||
}),
|
||||
},
|
||||
{
|
||||
field: 'error.message',
|
||||
name: i18n.translate('xpack.uptime.pingList.errorMessageColumnLabel', {
|
||||
defaultMessage: 'Error message',
|
||||
}),
|
||||
render: (message: string) =>
|
||||
message && message.length > 25 ? (
|
||||
<EuiToolTip
|
||||
position="top"
|
||||
title={i18n.translate('xpack.uptime.pingList.columns.errorMessageTooltipTitle', {
|
||||
defaultMessage: 'Error message',
|
||||
})}
|
||||
content={<p>{message}</p>}
|
||||
>
|
||||
<div>{message.slice(0, 24)}…</div>
|
||||
</EuiToolTip>
|
||||
) : (
|
||||
message
|
||||
),
|
||||
},
|
||||
];
|
||||
let pings: Ping[] = [];
|
||||
let total: number = 0;
|
||||
if (pingResults && pingResults.pings) {
|
||||
pings = pingResults.pings;
|
||||
total = pingResults.total;
|
||||
const hasStatus: boolean = pings.reduce(
|
||||
(hasHttpStatus: boolean, currentPing: Ping) =>
|
||||
hasHttpStatus || !!get(currentPing, 'http.response.status_code'),
|
||||
false
|
||||
);
|
||||
if (hasStatus) {
|
||||
columns.push({
|
||||
field: 'http.response.status_code',
|
||||
name: i18n.translate('xpack.uptime.pingList.responseCodeColumnLabel', {
|
||||
defaultMessage: 'Response code',
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle size="xs">
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.pingList.checkHistoryTitle"
|
||||
defaultMessage="Check History"
|
||||
/>
|
||||
</h4>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
{!!total && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiBadge color="primary">{total}</EuiBadge>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
<EuiPanel paddingSize="l">
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.uptime.pingList.statusLabel', {
|
||||
defaultMessage: 'Status',
|
||||
})}
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
selectedOptions={[selectedOption]}
|
||||
options={statusOptions}
|
||||
onChange={selectedOptionChanged}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.uptime.pingList.maxSearchSizeLabel', {
|
||||
defaultMessage: 'Max Search Size',
|
||||
})}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
defaultValue={maxSearchSize.toString()}
|
||||
min={0}
|
||||
max={10000} // 10k is the max default size in ES, and a good max sane size for this page
|
||||
onBlur={searchSizeOnBlur}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiInMemoryTable
|
||||
loading={loading}
|
||||
columns={columns}
|
||||
items={pings}
|
||||
pagination={{ initialPageSize: 10, pageSizeOptions: [5, 10, 20, 100] }}
|
||||
sorting={true}
|
||||
/>
|
||||
</EuiPanel>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
137
x-pack/plugins/uptime/public/components/functional/snapshot.tsx
Normal file
137
x-pack/plugins/uptime/public/components/functional/snapshot.tsx
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* 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 {
|
||||
// @ts-ignore missing type
|
||||
EuiAreaSeries,
|
||||
EuiEmptyPrompt,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
// @ts-ignore missing type
|
||||
EuiHistogramSeries,
|
||||
// @ts-ignore missing type
|
||||
EuiPanel,
|
||||
// @ts-ignore missing type
|
||||
EuiSeriesChart,
|
||||
// @ts-ignore missing type
|
||||
EuiSeriesChartUtils,
|
||||
// @ts-ignore missing type
|
||||
EuiStat,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React from 'react';
|
||||
import { Snapshot as SnapshotType } from '../../../common/graphql/types';
|
||||
import { SnapshotHistogram } from './snapshot_histogram';
|
||||
|
||||
interface SnapshotProps {
|
||||
dangerColor: string;
|
||||
primaryColor: string;
|
||||
snapshot: SnapshotType;
|
||||
}
|
||||
|
||||
export const Snapshot = ({
|
||||
dangerColor,
|
||||
primaryColor,
|
||||
snapshot: { up, down, total, histogram },
|
||||
}: SnapshotProps) => (
|
||||
<EuiFlexGroup alignItems="baseline" gutterSize="xl">
|
||||
<EuiFlexItem>
|
||||
<EuiTitle size="xs">
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.snapshot.endpointStatusTitle"
|
||||
defaultMessage="Endpoint status"
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
<EuiPanel>
|
||||
<EuiFlexGroup justifyContent="spaceEvenly" gutterSize="xl">
|
||||
<EuiFlexItem>
|
||||
{/* TODO: this is a UI hack that needs to be replaced */}
|
||||
<EuiPanel>
|
||||
<EuiStat
|
||||
description={i18n.translate('xpack.uptime.snapshot.stats.upDescription', {
|
||||
defaultMessage: 'Up',
|
||||
})}
|
||||
textAlign="center"
|
||||
title={up}
|
||||
titleColor="primary"
|
||||
/>
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiPanel>
|
||||
<EuiStat
|
||||
description={i18n.translate('xpack.uptime.snapshot.stats.downDescription', {
|
||||
defaultMessage: 'Down',
|
||||
})}
|
||||
textAlign="center"
|
||||
title={down}
|
||||
titleColor="danger"
|
||||
/>
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiPanel>
|
||||
<EuiStat
|
||||
description={i18n.translate('xpack.uptime.snapshot.stats.totalDescription', {
|
||||
defaultMessage: 'Total',
|
||||
})}
|
||||
textAlign="center"
|
||||
title={total}
|
||||
titleColor="subdued"
|
||||
/>
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={{ paddingTop: '12px' }}>
|
||||
<EuiTitle size="xs">
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.snapshot.statusOverTimeTitle"
|
||||
defaultMessage="Status over time"
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
{/* TODO: this is a UI hack that should be replaced */}
|
||||
<EuiPanel paddingSize="s">
|
||||
{histogram && (
|
||||
<SnapshotHistogram
|
||||
dangerColor={dangerColor}
|
||||
primaryColor={primaryColor}
|
||||
histogram={histogram}
|
||||
/>
|
||||
)}
|
||||
{!histogram && (
|
||||
<EuiEmptyPrompt
|
||||
title={
|
||||
<EuiTitle>
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.snapshot.noDataTitle"
|
||||
defaultMessage="No histogram data available"
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
}
|
||||
body={
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.snapshot.noDataDescription"
|
||||
defaultMessage="Sorry, there is no data available for the histogram"
|
||||
/>
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* 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 { EuiEmptyPrompt, EuiLink, EuiTitle } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React, { Fragment } from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { UptimeCommonProps } from '../../../uptime_app';
|
||||
import { getDocCountQuery } from './get_doc_count';
|
||||
|
||||
interface EmptyStateProps {
|
||||
children: JSX.Element[];
|
||||
}
|
||||
|
||||
type Props = EmptyStateProps & UptimeCommonProps;
|
||||
|
||||
export const EmptyState = ({ autorefreshInterval, autorefreshIsPaused, children }: Props) => (
|
||||
<Query
|
||||
query={getDocCountQuery}
|
||||
pollInterval={autorefreshIsPaused ? undefined : autorefreshInterval}
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
if (loading) {
|
||||
return i18n.translate('xpack.uptime.emptyState.loadingMessage', {
|
||||
defaultMessage: 'Loading…',
|
||||
});
|
||||
}
|
||||
if (error) {
|
||||
return i18n.translate('xpack.uptime.emptyState.errorMessage', {
|
||||
values: { message: error.message },
|
||||
defaultMessage: 'Error {message}',
|
||||
});
|
||||
}
|
||||
|
||||
const {
|
||||
getDocCount: { count },
|
||||
} = data;
|
||||
return (
|
||||
<Fragment>
|
||||
{!count && (
|
||||
<EuiEmptyPrompt
|
||||
title={
|
||||
<EuiTitle size="l">
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.emptyState.noDataTitle"
|
||||
defaultMessage="No Uptime Data"
|
||||
/>
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
}
|
||||
body={
|
||||
<Fragment>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.emptyState.noDataDescription"
|
||||
defaultMessage="There is no uptime data available."
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.emptyState.configureHeartbeatToGetStartedMessage"
|
||||
defaultMessage="{configureHeartbeatLink} to start logging uptime data."
|
||||
values={{
|
||||
configureHeartbeatLink: (
|
||||
<EuiLink
|
||||
target="_blank"
|
||||
href="https://www.elastic.co/guide/en/beats/heartbeat/current/configuring-howto-heartbeat.html"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.emptyState.configureHeartbeatLinkText"
|
||||
defaultMessage="Configure Heartbeat"
|
||||
/>
|
||||
</EuiLink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
</Fragment>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{count > 0 && children}
|
||||
</Fragment>
|
||||
);
|
||||
}}
|
||||
</Query>
|
||||
);
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 { get } from 'lodash';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { UptimeCommonProps } from '../../../uptime_app';
|
||||
import { EmptyState } from '../../functional/empty_state';
|
||||
import { getDocCountQuery } from './get_doc_count';
|
||||
|
||||
interface EmptyStateProps {
|
||||
children: JSX.Element[];
|
||||
}
|
||||
|
||||
type Props = EmptyStateProps & UptimeCommonProps;
|
||||
|
||||
export const EmptyStateQuery = ({ autorefreshInterval, autorefreshIsPaused, children }: Props) => (
|
||||
<Query
|
||||
query={getDocCountQuery}
|
||||
pollInterval={autorefreshIsPaused ? undefined : autorefreshInterval}
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
const count = get(data, 'getDocCount.count', 0);
|
||||
return (
|
||||
<EmptyState
|
||||
children={children}
|
||||
count={count}
|
||||
error={
|
||||
error
|
||||
? i18n.translate('xpack.uptime.emptyState.errorMessage', {
|
||||
values: { message: error.message },
|
||||
defaultMessage: 'Error {message}',
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
loading={loading}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Query>
|
||||
);
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { EmptyState } from './empty_state';
|
||||
export { EmptyStateQuery } from './empty_state_query';
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* 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 typings
|
||||
import { EuiInMemoryTable, EuiPanel, 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 { Query } from 'react-apollo';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { UptimeCommonProps } from '../../../uptime_app';
|
||||
import { getErrorListQuery } from './get_error_list';
|
||||
|
||||
interface ErrorListProps {
|
||||
filters?: string;
|
||||
}
|
||||
|
||||
type Props = ErrorListProps & UptimeCommonProps;
|
||||
|
||||
export const ErrorList = ({
|
||||
autorefreshInterval,
|
||||
autorefreshIsPaused,
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
filters,
|
||||
}: Props) => (
|
||||
<Query
|
||||
pollInterval={autorefreshIsPaused ? undefined : autorefreshInterval}
|
||||
query={getErrorListQuery}
|
||||
variables={{ dateRangeStart, dateRangeEnd, filters }}
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
if (error) {
|
||||
return i18n.translate('xpack.uptime.errorList.errorMessage', {
|
||||
values: { message: error.message },
|
||||
defaultMessage: 'Error {message}',
|
||||
});
|
||||
}
|
||||
const { errorList } = data;
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiTitle size="xs">
|
||||
<h5>
|
||||
<FormattedMessage id="xpack.uptime.errorList.title" defaultMessage="Error list" />
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
<EuiPanel>
|
||||
<EuiInMemoryTable
|
||||
loading={loading}
|
||||
items={errorList}
|
||||
columns={[
|
||||
{
|
||||
field: 'type',
|
||||
name: i18n.translate('xpack.uptime.errorList.errorTypeColumnLabel', {
|
||||
defaultMessage: 'Error type',
|
||||
}),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'monitorId',
|
||||
name: i18n.translate('xpack.uptime.errorList.monitorIdColumnLabel', {
|
||||
defaultMessage: 'Monitor ID',
|
||||
}),
|
||||
render: (id: string) => <Link to={`/monitor/${id}`}>{id}</Link>,
|
||||
sortable: true,
|
||||
width: '25%',
|
||||
},
|
||||
{
|
||||
field: 'count',
|
||||
name: i18n.translate('xpack.uptime.errorList.CountColumnLabel', {
|
||||
defaultMessage: 'Count',
|
||||
}),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'timestamp',
|
||||
name: i18n.translate('xpack.uptime.errorList.latestErrorColumnLabel', {
|
||||
defaultMessage: 'Latest error',
|
||||
}),
|
||||
sortable: true,
|
||||
render: (timestamp: string) => moment(timestamp).fromNow(),
|
||||
},
|
||||
{
|
||||
field: 'statusCode',
|
||||
name: i18n.translate('xpack.uptime.errorList.statusCodeColumnLabel', {
|
||||
defaultMessage: 'Status code',
|
||||
}),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'latestMessage',
|
||||
name: i18n.translate('xpack.uptime.errorList.latestMessageColumnLabel', {
|
||||
defaultMessage: 'Latest message',
|
||||
}),
|
||||
sortable: true,
|
||||
width: '40%',
|
||||
},
|
||||
]}
|
||||
sorting={true}
|
||||
pagination={{ initialPageSize: 10, pageSizeOptions: [5, 10, 20, 50] }}
|
||||
/>
|
||||
</EuiPanel>
|
||||
</Fragment>
|
||||
);
|
||||
}}
|
||||
</Query>
|
||||
);
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { UptimeCommonProps } from '../../../uptime_app';
|
||||
import { ErrorList } from '../../functional';
|
||||
import { getErrorListQuery } from './get_error_list';
|
||||
|
||||
interface ErrorListProps {
|
||||
filters?: string;
|
||||
}
|
||||
|
||||
type Props = ErrorListProps & UptimeCommonProps;
|
||||
|
||||
export const ErrorListQuery = ({
|
||||
autorefreshInterval,
|
||||
autorefreshIsPaused,
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
filters,
|
||||
}: Props) => (
|
||||
<Query
|
||||
pollInterval={autorefreshIsPaused ? undefined : autorefreshInterval}
|
||||
query={getErrorListQuery}
|
||||
variables={{ dateRangeStart, dateRangeEnd, filters }}
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
if (error) {
|
||||
return i18n.translate('xpack.uptime.errorList.errorMessage', {
|
||||
values: { message: error.message },
|
||||
defaultMessage: 'Error {message}',
|
||||
});
|
||||
}
|
||||
const { errorList } = data;
|
||||
return <ErrorList loading={loading} errorList={errorList} />;
|
||||
}}
|
||||
</Query>
|
||||
);
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { ErrorList } from './error_list';
|
||||
export { ErrorListQuery } from './error_list_query';
|
||||
|
|
|
@ -1,166 +0,0 @@
|
|||
/*
|
||||
* 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 No typings for EuiSearchBar
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSearchBar, EuiToolTip } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { FilterBar as FilterBarType, MonitorKey } from '../../../../common/graphql/types';
|
||||
import { UptimeCommonProps } from '../../../uptime_app';
|
||||
import { FilterBarLoading } from '../../functional';
|
||||
import { getFilterBarQuery } from './get_filter_bar';
|
||||
import { filterBarSearchSchema } from './search_schema';
|
||||
|
||||
interface FilterBarProps {
|
||||
updateQuery: (query: object | undefined) => void;
|
||||
}
|
||||
|
||||
type Props = FilterBarProps & UptimeCommonProps;
|
||||
|
||||
const SEARCH_THRESHOLD = 8;
|
||||
|
||||
export const FilterBar = ({
|
||||
autorefreshInterval,
|
||||
autorefreshIsPaused,
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
updateQuery,
|
||||
}: Props) => (
|
||||
<Query
|
||||
pollInterval={autorefreshIsPaused ? undefined : autorefreshInterval}
|
||||
query={getFilterBarQuery}
|
||||
variables={{ dateRangeStart, dateRangeEnd }}
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
if (loading) {
|
||||
return <FilterBarLoading />;
|
||||
}
|
||||
if (error) {
|
||||
return i18n.translate('xpack.uptime.filterBar.errorMessage', {
|
||||
values: { message: error.message },
|
||||
defaultMessage: 'Error {message}',
|
||||
});
|
||||
}
|
||||
const {
|
||||
filterBar: { names, ports, ids, schemes },
|
||||
}: { filterBar: FilterBarType } = data;
|
||||
|
||||
// TODO: add a factory function + type for these filter options
|
||||
const filters = [
|
||||
{
|
||||
type: 'field_value_toggle_group',
|
||||
field: 'monitor.status',
|
||||
items: [
|
||||
{
|
||||
value: 'up',
|
||||
name: i18n.translate('xpack.uptime.filterBar.filterUpLabel', {
|
||||
defaultMessage: 'Up',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: 'down',
|
||||
name: i18n.translate('xpack.uptime.filterBar.filterDownLabel', {
|
||||
defaultMessage: 'Down',
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
// TODO: add health to this select
|
||||
{
|
||||
type: 'field_value_selection',
|
||||
field: 'monitor.id',
|
||||
name: i18n.translate('xpack.uptime.filterBar.options.idLabel', {
|
||||
defaultMessage: 'ID',
|
||||
}),
|
||||
multiSelect: false,
|
||||
options: ids
|
||||
? ids.map(({ key }: MonitorKey) => ({
|
||||
value: key,
|
||||
view: key,
|
||||
}))
|
||||
: [],
|
||||
searchThreshold: SEARCH_THRESHOLD,
|
||||
},
|
||||
{
|
||||
type: 'field_value_selection',
|
||||
field: 'monitor.name',
|
||||
name: i18n.translate('xpack.uptime.filterBar.options.nameLabel', {
|
||||
defaultMessage: 'Name',
|
||||
}),
|
||||
multiSelect: false,
|
||||
options: names
|
||||
? names.map((nameValue: string) => ({ value: nameValue, view: nameValue }))
|
||||
: [],
|
||||
searchThreshold: SEARCH_THRESHOLD,
|
||||
},
|
||||
{
|
||||
type: 'field_value_selection',
|
||||
field: 'url.full',
|
||||
name: i18n.translate('xpack.uptime.filterBar.options.urlLabel', {
|
||||
defaultMessage: 'URL',
|
||||
}),
|
||||
multiSelect: false,
|
||||
options: ids ? ids.map(({ url }: MonitorKey) => ({ value: url, view: url })) : [],
|
||||
searchThreshold: SEARCH_THRESHOLD,
|
||||
},
|
||||
{
|
||||
type: 'field_value_selection',
|
||||
field: 'url.port',
|
||||
name: i18n.translate('xpack.uptime.filterBar.options.portLabel', {
|
||||
defaultMessage: 'Port',
|
||||
}),
|
||||
multiSelect: false,
|
||||
options: ports
|
||||
? ports.map((portValue: any) => ({
|
||||
value: portValue,
|
||||
view: portValue,
|
||||
}))
|
||||
: [],
|
||||
searchThreshold: SEARCH_THRESHOLD,
|
||||
},
|
||||
{
|
||||
type: 'field_value_selection',
|
||||
field: 'monitor.type',
|
||||
name: i18n.translate('xpack.uptime.filterBar.options.typeLabel', {
|
||||
defaultMessage: 'Type',
|
||||
}),
|
||||
multiSelect: false,
|
||||
options: schemes
|
||||
? schemes.map((schemeValue: string) => ({
|
||||
value: schemeValue,
|
||||
view: schemeValue,
|
||||
}))
|
||||
: [],
|
||||
searchThreshold: SEARCH_THRESHOLD,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow>
|
||||
<EuiSearchBar
|
||||
// TODO: update typing
|
||||
onChange={({ query }: { query?: { text: string } }) => {
|
||||
try {
|
||||
let esQuery;
|
||||
if (query && query.text) {
|
||||
esQuery = EuiSearchBar.Query.toESQuery(query);
|
||||
}
|
||||
updateQuery(esQuery);
|
||||
} catch (e) {
|
||||
updateQuery(undefined);
|
||||
}
|
||||
}}
|
||||
filters={filters}
|
||||
schema={filterBarSearchSchema}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}}
|
||||
</Query>
|
||||
);
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { UptimeCommonProps } from '../../../uptime_app';
|
||||
import { FilterBar } from '../../functional';
|
||||
import { getFilterBarQuery } from './get_filter_bar';
|
||||
|
||||
interface FilterBarProps {
|
||||
updateQuery: (query: object | undefined) => void;
|
||||
}
|
||||
|
||||
type Props = FilterBarProps & UptimeCommonProps;
|
||||
|
||||
export const FilterBarQuery = ({
|
||||
autorefreshInterval,
|
||||
autorefreshIsPaused,
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
updateQuery,
|
||||
}: Props) => (
|
||||
<Query
|
||||
pollInterval={autorefreshIsPaused ? undefined : autorefreshInterval}
|
||||
query={getFilterBarQuery}
|
||||
variables={{ dateRangeStart, dateRangeEnd }}
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
if (loading) {
|
||||
return i18n.translate('xpack.uptime.filterBar.loadingMessage', {
|
||||
defaultMessage: 'Loading…',
|
||||
});
|
||||
}
|
||||
if (error) {
|
||||
return i18n.translate('xpack.uptime.filterBar.errorMessage', {
|
||||
values: { message: error.message },
|
||||
defaultMessage: 'Error {message}',
|
||||
});
|
||||
}
|
||||
const { filterBar } = data;
|
||||
return <FilterBar filterBar={filterBar} updateQuery={updateQuery} />;
|
||||
}}
|
||||
</Query>
|
||||
);
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { FilterBar } from './filter_bar';
|
||||
export { FilterBarQuery } from './filter_bar_query';
|
||||
|
|
15
x-pack/plugins/uptime/public/components/queries/index.ts
Normal file
15
x-pack/plugins/uptime/public/components/queries/index.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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 { EmptyStateQuery } from './empty_state';
|
||||
export { ErrorListQuery } from './error_list';
|
||||
export { FilterBarQuery } from './filter_bar';
|
||||
export { MonitorChartsQuery } from './monitor_charts';
|
||||
export { MonitorListQuery } from './monitor_list';
|
||||
export { MonitorPageTitleQuery } from './monitor_page_title';
|
||||
export { MonitorStatusBarQuery } from './monitor_status_bar';
|
||||
export { PingListQuery } from './ping_list';
|
||||
export { SnapshotQuery } from './snapshot';
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { MonitorCharts } from './monitor_charts';
|
||||
export { MonitorChartsQuery } from './monitor_charts_query';
|
||||
|
|
|
@ -38,7 +38,7 @@ interface MonitorChartsState {
|
|||
|
||||
type Props = MonitorChartsProps & UptimeCommonProps;
|
||||
|
||||
export class MonitorCharts extends React.Component<Props, MonitorChartsState> {
|
||||
export class MonitorChartsQuery extends React.Component<Props, MonitorChartsState> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = { crosshairLocation: 0 };
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { MonitorList } from './monitor_list';
|
||||
export { MonitorListQuery } from './monitor_list_query';
|
||||
|
|
|
@ -1,187 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
EuiHealth,
|
||||
// @ts-ignore missing type definition
|
||||
EuiHistogramSeries,
|
||||
// @ts-ignore missing type definition
|
||||
EuiInMemoryTable,
|
||||
EuiLink,
|
||||
EuiPanel,
|
||||
// @ts-ignore missing type definition
|
||||
EuiSeriesChart,
|
||||
// @ts-ignore missing type definition
|
||||
EuiSeriesChartUtils,
|
||||
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 { Query } from 'react-apollo';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { LatestMonitor, LatestMonitorsResult } from '../../../../common/graphql/types';
|
||||
import { UptimeCommonProps } from '../../../uptime_app';
|
||||
import { formatSparklineCounts } from './format_sparkline_counts';
|
||||
import { getMonitorListQuery } from './get_monitor_list';
|
||||
|
||||
interface MonitorListProps {
|
||||
filters?: string;
|
||||
}
|
||||
|
||||
type Props = MonitorListProps & UptimeCommonProps;
|
||||
|
||||
const MONITOR_LIST_DEFAULT_PAGINATION = 10;
|
||||
|
||||
const monitorListPagination = {
|
||||
initialPageSize: MONITOR_LIST_DEFAULT_PAGINATION,
|
||||
pageSizeOptions: [5, 10, 20, 50],
|
||||
};
|
||||
|
||||
export const MonitorList = ({
|
||||
autorefreshInterval,
|
||||
autorefreshIsPaused,
|
||||
colors: { danger, primary },
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
filters,
|
||||
}: Props) => (
|
||||
<Query
|
||||
pollInterval={autorefreshIsPaused ? undefined : autorefreshInterval}
|
||||
query={getMonitorListQuery}
|
||||
variables={{ dateRangeStart, dateRangeEnd, filters }}
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
if (error) {
|
||||
return i18n.translate('xpack.uptime.monitorList.errorMessage', {
|
||||
values: { message: error.message },
|
||||
defaultMessage: 'Error {message}',
|
||||
});
|
||||
}
|
||||
const monitors: LatestMonitorsResult | undefined = get(data, 'monitorStatus.monitors');
|
||||
// TODO: add a better loading message than "no items found", which it displays today
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiTitle size="xs">
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.monitorList.monitoringStatusTitle"
|
||||
defaultMessage="Monitor status"
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
<EuiPanel paddingSize="l">
|
||||
<EuiInMemoryTable
|
||||
columns={[
|
||||
{
|
||||
field: 'ping.monitor.status',
|
||||
name: i18n.translate('xpack.uptime.monitorList.statusColumnLabel', {
|
||||
defaultMessage: 'Status',
|
||||
}),
|
||||
render: (status: string) => (
|
||||
<EuiHealth color={status === 'up' ? 'success' : 'danger'}>
|
||||
{status === 'up'
|
||||
? i18n.translate('xpack.uptime.monitorList.statusColumn.upLabel', {
|
||||
defaultMessage: 'Up',
|
||||
})
|
||||
: i18n.translate('xpack.uptime.monitorList.statusColumn.downLabel', {
|
||||
defaultMessage: 'Down',
|
||||
})}
|
||||
</EuiHealth>
|
||||
),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'ping.timestamp',
|
||||
name: i18n.translate('xpack.uptime.monitorList.lastUpdatedColumnLabel', {
|
||||
defaultMessage: 'Last updated',
|
||||
}),
|
||||
render: (timestamp: string) => moment(timestamp).fromNow(),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'ping.monitor.id',
|
||||
name: i18n.translate('xpack.uptime.monitorList.idColumnLabel', {
|
||||
defaultMessage: 'ID',
|
||||
}),
|
||||
render: (id: string, monitor: LatestMonitor) => (
|
||||
<Link to={`/monitor/${id}`}>
|
||||
{monitor.ping && monitor.ping.monitor && monitor.ping.monitor.name
|
||||
? monitor.ping.monitor.name
|
||||
: id}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'ping.url.full',
|
||||
name: i18n.translate('xpack.uptime.monitorList.urlColumnLabel', {
|
||||
defaultMessage: 'URL',
|
||||
}),
|
||||
render: (url: string) => (
|
||||
<EuiLink href={url} target="_blank">
|
||||
{url}
|
||||
</EuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'ping.monitor.ip',
|
||||
name: i18n.translate('xpack.uptime.monitorList.ipColumnLabel', {
|
||||
defaultMessage: 'IP',
|
||||
}),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'upSeries',
|
||||
name: i18n.translate('xpack.uptime.monitorList.monitorHistoryColumnLabel', {
|
||||
defaultMessage: 'Monitor History',
|
||||
}),
|
||||
// @ts-ignore TODO fix typing
|
||||
render: (upSeries, monitor) => {
|
||||
const { downSeries } = monitor;
|
||||
return (
|
||||
<EuiSeriesChart
|
||||
showDefaultAxis={false}
|
||||
height={70}
|
||||
stackBy="y"
|
||||
// TODO: style hack
|
||||
style={{ marginBottom: '-20px' }}
|
||||
xType={EuiSeriesChartUtils.SCALE.TIME}
|
||||
>
|
||||
<EuiHistogramSeries
|
||||
data={formatSparklineCounts(downSeries)}
|
||||
name={i18n.translate(
|
||||
'xpack.uptime.monitorList.downLineSeries.downLabel',
|
||||
{
|
||||
defaultMessage: 'Down',
|
||||
}
|
||||
)}
|
||||
color={danger}
|
||||
/>
|
||||
<EuiHistogramSeries
|
||||
data={formatSparklineCounts(upSeries)}
|
||||
name={i18n.translate('xpack.uptime.monitorList.upLineSeries.upLabel', {
|
||||
defaultMessage: 'Up',
|
||||
})}
|
||||
color={primary}
|
||||
/>
|
||||
</EuiSeriesChart>
|
||||
);
|
||||
},
|
||||
},
|
||||
]}
|
||||
loading={loading}
|
||||
items={monitors}
|
||||
pagination={monitorListPagination}
|
||||
sorting={true}
|
||||
/>
|
||||
</EuiPanel>
|
||||
</Fragment>
|
||||
);
|
||||
}}
|
||||
</Query>
|
||||
);
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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 { 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 { getMonitorListQuery } from './get_monitor_list';
|
||||
|
||||
interface MonitorListProps {
|
||||
filters?: string;
|
||||
}
|
||||
|
||||
type Props = MonitorListProps & UptimeCommonProps;
|
||||
|
||||
export const MonitorListQuery = ({
|
||||
autorefreshInterval,
|
||||
autorefreshIsPaused,
|
||||
colors: { primary, danger },
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
filters,
|
||||
}: Props) => (
|
||||
<Query
|
||||
pollInterval={autorefreshIsPaused ? undefined : autorefreshInterval}
|
||||
query={getMonitorListQuery}
|
||||
variables={{ dateRangeStart, dateRangeEnd, filters }}
|
||||
>
|
||||
{({ 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 (
|
||||
<MonitorList
|
||||
dangerColor={danger}
|
||||
loading={loading}
|
||||
monitors={monitors || []}
|
||||
primaryColor={primary}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Query>
|
||||
);
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { MonitorStatusBar } from './monitor_status_bar';
|
||||
export { MonitorStatusBarQuery } from './monitor_status_bar_query';
|
||||
|
|
|
@ -11,8 +11,7 @@ import React from 'react';
|
|||
import { Query } from 'react-apollo';
|
||||
import { Ping } from 'x-pack/plugins/uptime/common/graphql/types';
|
||||
import { UptimeCommonProps } from '../../../uptime_app';
|
||||
import { StatusBar } from '../../functional';
|
||||
import { EmptyStatusBar } from '../../functional/empty_status_bar';
|
||||
import { EmptyStatusBar, MonitorStatusBar } from '../../functional';
|
||||
import { formatDuration } from './format_duration';
|
||||
import { getMonitorStatusBarQuery } from './get_monitor_status_bar';
|
||||
|
||||
|
@ -28,7 +27,7 @@ interface MonitorStatusBarQueryParams {
|
|||
|
||||
type Props = MonitorStatusBarProps & UptimeCommonProps;
|
||||
|
||||
export const MonitorStatusBar = ({
|
||||
export const MonitorStatusBarQuery = ({
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
monitorId,
|
||||
|
@ -42,7 +41,14 @@ export const MonitorStatusBar = ({
|
|||
>
|
||||
{({ loading, error, data }: MonitorStatusBarQueryParams) => {
|
||||
if (loading) {
|
||||
return <EmptyStatusBar message="Fetching data" monitorId={monitorId} />;
|
||||
return (
|
||||
<EmptyStatusBar
|
||||
message={i18n.translate('xpack.uptime.monitorStatusBar.loadingMessage', {
|
||||
defaultMessage: 'Loading…',
|
||||
})}
|
||||
monitorId={monitorId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (error) {
|
||||
return i18n.translate('xpack.uptime.monitorStatusBar.errorMessage', {
|
||||
|
@ -61,7 +67,7 @@ export const MonitorStatusBar = ({
|
|||
const full = get(url, 'full', undefined);
|
||||
|
||||
return (
|
||||
<StatusBar
|
||||
<MonitorStatusBar
|
||||
duration={formatDuration(duration)}
|
||||
status={status}
|
||||
timestamp={timestamp}
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { Pings } from './ping_list';
|
||||
export { PingListQuery } from './ping_list_query';
|
||||
|
|
|
@ -1,281 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
EuiBadge,
|
||||
EuiComboBox,
|
||||
EuiComboBoxOptionProps,
|
||||
EuiFieldNumber,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiHealth,
|
||||
// @ts-ignore
|
||||
EuiInMemoryTable,
|
||||
EuiPanel,
|
||||
EuiTitle,
|
||||
EuiToolTip,
|
||||
} 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 { Query } from 'react-apollo';
|
||||
import { UMPingSortDirectionArg } from '../../../../common/domain_types';
|
||||
import { Ping } from '../../../../common/graphql/types';
|
||||
import { UptimeCommonProps } from '../../../uptime_app';
|
||||
import { getPingsQuery } from './get_pings';
|
||||
|
||||
interface PingListProps {
|
||||
monitorId?: string;
|
||||
sort?: UMPingSortDirectionArg;
|
||||
size?: number;
|
||||
}
|
||||
|
||||
type Props = PingListProps & UptimeCommonProps;
|
||||
|
||||
interface PingListState {
|
||||
statusOptions: EuiComboBoxOptionProps[];
|
||||
selectedOption: EuiComboBoxOptionProps;
|
||||
maxSearchSize: number;
|
||||
}
|
||||
|
||||
export class Pings extends React.Component<Props, PingListState> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
const statusOptions = [
|
||||
{
|
||||
label: i18n.translate('xpack.uptime.pingList.statusOptions.allStatusOptionLabel', {
|
||||
defaultMessage: 'All',
|
||||
}),
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.uptime.pingList.statusOptions.upStatusOptionLabel', {
|
||||
defaultMessage: 'Up',
|
||||
}),
|
||||
value: 'up',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.uptime.pingList.statusOptions.downStatusOptionLabel', {
|
||||
defaultMessage: 'Down',
|
||||
}),
|
||||
value: 'down',
|
||||
},
|
||||
];
|
||||
this.state = {
|
||||
statusOptions,
|
||||
selectedOption: statusOptions[2],
|
||||
maxSearchSize: 200,
|
||||
};
|
||||
}
|
||||
public render() {
|
||||
const {
|
||||
monitorId,
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
autorefreshIsPaused,
|
||||
autorefreshInterval,
|
||||
sort,
|
||||
size,
|
||||
} = this.props;
|
||||
const { statusOptions, selectedOption } = this.state;
|
||||
return (
|
||||
<Query
|
||||
pollInterval={autorefreshIsPaused ? undefined : autorefreshInterval}
|
||||
variables={{
|
||||
monitorId,
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
status:
|
||||
selectedOption.value === 'up' || selectedOption.value === 'down'
|
||||
? selectedOption.value
|
||||
: '',
|
||||
// TODO: get rid of the magic number
|
||||
size: this.state.maxSearchSize || size || 200,
|
||||
sort: sort || 'desc',
|
||||
}}
|
||||
query={getPingsQuery}
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
if (error) {
|
||||
return i18n.translate('xpack.uptime.pingList.errorMessage', {
|
||||
values: { message: error.message },
|
||||
defaultMessage: 'Error {message}',
|
||||
});
|
||||
}
|
||||
const total = get(data, 'allPings.total');
|
||||
const pings = get(data, 'allPings.pings', []);
|
||||
const columns = [
|
||||
{
|
||||
field: 'monitor.status',
|
||||
name: i18n.translate('xpack.uptime.pingList.statusColumnLabel', {
|
||||
defaultMessage: 'Status',
|
||||
}),
|
||||
render: (pingStatus: string) => (
|
||||
<EuiHealth color={pingStatus === 'up' ? 'success' : 'danger'}>
|
||||
{pingStatus === 'up'
|
||||
? i18n.translate('xpack.uptime.pingList.statusColumnHealthUpLabel', {
|
||||
defaultMessage: 'Up',
|
||||
})
|
||||
: i18n.translate('xpack.uptime.pingList.statusColumnHealthDownLabel', {
|
||||
defaultMessage: 'Down',
|
||||
})}
|
||||
</EuiHealth>
|
||||
),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'timestamp',
|
||||
name: i18n.translate('xpack.uptime.pingList.timestampColumnLabel', {
|
||||
defaultMessage: 'Timestamp',
|
||||
}),
|
||||
sortable: true,
|
||||
render: (timestamp: string) => moment(timestamp).fromNow(),
|
||||
},
|
||||
{
|
||||
field: 'monitor.ip',
|
||||
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',
|
||||
}),
|
||||
render: (duration: number) => duration / 1000,
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'error.type',
|
||||
name: i18n.translate('xpack.uptime.pingList.errorTypeColumnLabel', {
|
||||
defaultMessage: 'Error type',
|
||||
}),
|
||||
},
|
||||
{
|
||||
field: 'error.message',
|
||||
name: i18n.translate('xpack.uptime.pingList.errorMessageColumnLabel', {
|
||||
defaultMessage: 'Error message',
|
||||
}),
|
||||
render: (message: string) =>
|
||||
message && message.length > 25 ? (
|
||||
<EuiToolTip
|
||||
position="top"
|
||||
title={i18n.translate(
|
||||
'xpack.uptime.pingList.columns.errorMessageTooltipTitle',
|
||||
{
|
||||
defaultMessage: 'Error message',
|
||||
}
|
||||
)}
|
||||
content={<p>{message}</p>}
|
||||
>
|
||||
<div>{message.slice(0, 24)}…</div>
|
||||
</EuiToolTip>
|
||||
) : (
|
||||
message
|
||||
),
|
||||
},
|
||||
];
|
||||
const hasStatus = pings.reduce(
|
||||
(hasHttpStatus: boolean, currentPing: Ping) =>
|
||||
hasHttpStatus || get(currentPing, 'http.response.status_code'),
|
||||
false
|
||||
);
|
||||
if (hasStatus) {
|
||||
columns.push({
|
||||
field: 'http.response.status_code',
|
||||
name: i18n.translate('xpack.uptime.pingList.responseCodeColumnLabel', {
|
||||
defaultMessage: 'Response code',
|
||||
}),
|
||||
});
|
||||
}
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle size="xs">
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.pingList.checkHistoryTitle"
|
||||
defaultMessage="Check History"
|
||||
/>
|
||||
</h4>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiBadge color="primary">{total}</EuiBadge>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiPanel paddingSize="l">
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.uptime.pingList.statusLabel', {
|
||||
defaultMessage: 'Status',
|
||||
})}
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
selectedOptions={[this.state.selectedOption]}
|
||||
options={statusOptions}
|
||||
onChange={selectedOptions => {
|
||||
if (selectedOptions[0]) {
|
||||
this.setState({ selectedOption: selectedOptions[0] });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.uptime.pingList.maxSearchSizeLabel', {
|
||||
defaultMessage: 'Max Search Size',
|
||||
})}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
defaultValue={this.state.maxSearchSize.toString()}
|
||||
min={0}
|
||||
max={10000} // 10k is the max default size in ES, and a good max sane size for this page
|
||||
onBlur={e => {
|
||||
const sanitizedValue = parseInt(e.target.value, 10);
|
||||
if (!isNaN(sanitizedValue)) {
|
||||
this.setState({
|
||||
maxSearchSize: sanitizedValue >= 10000 ? 10000 : sanitizedValue,
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiInMemoryTable
|
||||
loading={loading}
|
||||
columns={columns}
|
||||
items={pings}
|
||||
pagination={{ initialPageSize: 10, pageSizeOptions: [5, 10, 20, 100] }}
|
||||
sorting={true}
|
||||
/>
|
||||
</EuiPanel>
|
||||
</Fragment>
|
||||
);
|
||||
}}
|
||||
</Query>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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 { EuiComboBoxOptionProps } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { UMPingSortDirectionArg } from '../../../../common/domain_types';
|
||||
import { UptimeCommonProps } from '../../../uptime_app';
|
||||
import { PingList } from '../../functional';
|
||||
import { getPingsQuery } from './get_pings';
|
||||
|
||||
interface PingListProps {
|
||||
monitorId?: string;
|
||||
sort?: UMPingSortDirectionArg;
|
||||
size?: number;
|
||||
}
|
||||
|
||||
type Props = PingListProps & UptimeCommonProps;
|
||||
|
||||
interface PingListState {
|
||||
statusOptions: EuiComboBoxOptionProps[];
|
||||
selectedOption: EuiComboBoxOptionProps;
|
||||
maxSearchSize: number;
|
||||
}
|
||||
|
||||
export class PingListQuery extends React.Component<Props, PingListState> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
const statusOptions = [
|
||||
{
|
||||
label: i18n.translate('xpack.uptime.pingList.statusOptions.allStatusOptionLabel', {
|
||||
defaultMessage: 'All',
|
||||
}),
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.uptime.pingList.statusOptions.upStatusOptionLabel', {
|
||||
defaultMessage: 'Up',
|
||||
}),
|
||||
value: 'up',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.uptime.pingList.statusOptions.downStatusOptionLabel', {
|
||||
defaultMessage: 'Down',
|
||||
}),
|
||||
value: 'down',
|
||||
},
|
||||
];
|
||||
this.state = {
|
||||
statusOptions,
|
||||
selectedOption: statusOptions[2],
|
||||
maxSearchSize: 200,
|
||||
};
|
||||
}
|
||||
public render() {
|
||||
const {
|
||||
monitorId,
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
autorefreshIsPaused,
|
||||
autorefreshInterval,
|
||||
sort,
|
||||
size,
|
||||
} = this.props;
|
||||
const { selectedOption } = this.state;
|
||||
return (
|
||||
<Query
|
||||
pollInterval={autorefreshIsPaused ? undefined : autorefreshInterval}
|
||||
variables={{
|
||||
monitorId,
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
status:
|
||||
selectedOption.value === 'up' || selectedOption.value === 'down'
|
||||
? selectedOption.value
|
||||
: '',
|
||||
// TODO: get rid of the magic number
|
||||
size: this.state.maxSearchSize || size || 200,
|
||||
sort: sort || 'desc',
|
||||
}}
|
||||
query={getPingsQuery}
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
if (error) {
|
||||
return i18n.translate('xpack.uptime.pingList.errorMessage', {
|
||||
values: { message: error.message },
|
||||
defaultMessage: 'Error {message}',
|
||||
});
|
||||
}
|
||||
const { allPings } = data;
|
||||
return (
|
||||
<PingList
|
||||
loading={loading}
|
||||
maxSearchSize={this.state.maxSearchSize}
|
||||
pingResults={allPings}
|
||||
searchSizeOnBlur={this.onSearchSizeBlur}
|
||||
selectedOption={this.state.selectedOption}
|
||||
selectedOptionChanged={this.onSelectedOptionChange}
|
||||
statusOptions={this.state.statusOptions}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Query>
|
||||
);
|
||||
}
|
||||
|
||||
private onSearchSizeBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
||||
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] });
|
||||
}
|
||||
};
|
||||
}
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { Snapshot } from './snapshot';
|
||||
export { SnapshotQuery } from './snapshot_query';
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
// @ts-ignore missing type
|
||||
EuiAreaSeries,
|
||||
EuiEmptyPrompt,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
// @ts-ignore missing type
|
||||
EuiHistogramSeries,
|
||||
// @ts-ignore missing type
|
||||
EuiPanel,
|
||||
// @ts-ignore missing type
|
||||
EuiSeriesChart,
|
||||
// @ts-ignore missing type
|
||||
EuiSeriesChartUtils,
|
||||
// @ts-ignore missing type
|
||||
EuiStat,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { UptimeCommonProps } from '../../../uptime_app';
|
||||
import { SnapshotHistogram, SnapshotLoading } from '../../functional';
|
||||
import { getSnapshotQuery } from './get_snapshot';
|
||||
|
||||
interface SnapshotProps {
|
||||
filters?: string;
|
||||
}
|
||||
|
||||
type Props = SnapshotProps & UptimeCommonProps;
|
||||
|
||||
export const Snapshot = ({
|
||||
autorefreshIsPaused,
|
||||
autorefreshInterval,
|
||||
colors: { danger, primary },
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
filters,
|
||||
}: Props) => (
|
||||
<Query
|
||||
pollInterval={autorefreshIsPaused ? undefined : autorefreshInterval}
|
||||
query={getSnapshotQuery}
|
||||
variables={{ dateRangeStart, dateRangeEnd, filters }}
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
if (loading) {
|
||||
return <SnapshotLoading />;
|
||||
}
|
||||
if (error) {
|
||||
return i18n.translate('xpack.uptime.snapshot.errorMessage', {
|
||||
values: { message: error.message },
|
||||
defaultMessage: 'Error {message}',
|
||||
});
|
||||
}
|
||||
const {
|
||||
snapshot: { up, down, total, histogram },
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<EuiFlexGroup alignItems="baseline" gutterSize="xl">
|
||||
<EuiFlexItem>
|
||||
<EuiTitle size="xs">
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.snapshot.endpointStatusTitle"
|
||||
defaultMessage="Endpoint status"
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
<EuiPanel>
|
||||
<EuiFlexGroup justifyContent="spaceEvenly" gutterSize="xl">
|
||||
<EuiFlexItem>
|
||||
{/* TODO: this is a UI hack that needs to be replaced */}
|
||||
<EuiPanel>
|
||||
<EuiStat
|
||||
description={i18n.translate('xpack.uptime.snapshot.stats.upDescription', {
|
||||
defaultMessage: 'Up',
|
||||
})}
|
||||
textAlign="center"
|
||||
title={up}
|
||||
titleColor="primary"
|
||||
/>
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiPanel>
|
||||
<EuiStat
|
||||
description={i18n.translate('xpack.uptime.snapshot.stats.downDescription', {
|
||||
defaultMessage: 'Down',
|
||||
})}
|
||||
textAlign="center"
|
||||
title={down}
|
||||
titleColor="danger"
|
||||
/>
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiPanel>
|
||||
<EuiStat
|
||||
description={i18n.translate('xpack.uptime.snapshot.stats.totalDescription', {
|
||||
defaultMessage: 'Total',
|
||||
})}
|
||||
textAlign="center"
|
||||
title={total}
|
||||
titleColor="subdued"
|
||||
/>
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={{ paddingTop: '12px' }}>
|
||||
<EuiTitle size="xs">
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.snapshot.statusOverTimeTitle"
|
||||
defaultMessage="Status over time"
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
{/* TODO: this is a UI hack that should be replaced */}
|
||||
<EuiPanel paddingSize="s">
|
||||
{histogram && (
|
||||
<SnapshotHistogram
|
||||
dangerColor={danger}
|
||||
primaryColor={primary}
|
||||
histogram={histogram}
|
||||
/>
|
||||
)}
|
||||
{!histogram && (
|
||||
<EuiEmptyPrompt
|
||||
title={
|
||||
<EuiTitle>
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.snapshot.noDataTitle"
|
||||
defaultMessage="No histogram data available"
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
}
|
||||
body={
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.uptime.snapshot.noDataDescription"
|
||||
defaultMessage="Sorry, there is no data available for the histogram"
|
||||
/>
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}}
|
||||
</Query>
|
||||
);
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { UptimeCommonProps } from '../../../uptime_app';
|
||||
import { Snapshot } from '../../functional';
|
||||
import { getSnapshotQuery } from './get_snapshot';
|
||||
|
||||
interface SnapshotProps {
|
||||
filters?: string;
|
||||
}
|
||||
|
||||
type Props = SnapshotProps & UptimeCommonProps;
|
||||
|
||||
export const SnapshotQuery = ({
|
||||
autorefreshIsPaused,
|
||||
autorefreshInterval,
|
||||
colors: { primary, danger },
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
filters,
|
||||
}: Props) => (
|
||||
<Query
|
||||
pollInterval={autorefreshIsPaused ? undefined : autorefreshInterval}
|
||||
query={getSnapshotQuery}
|
||||
variables={{ dateRangeStart, dateRangeEnd, filters }}
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
if (loading) {
|
||||
return i18n.translate('xpack.uptime.snapshot.loadingMessage', {
|
||||
defaultMessage: 'Loading…',
|
||||
});
|
||||
}
|
||||
if (error) {
|
||||
return i18n.translate('xpack.uptime.snapshot.errorMessage', {
|
||||
values: { message: error.message },
|
||||
defaultMessage: 'Error {message}',
|
||||
});
|
||||
}
|
||||
const { snapshot } = data;
|
||||
|
||||
return <Snapshot dangerColor={danger} primaryColor={primary} snapshot={snapshot} />;
|
||||
}}
|
||||
</Query>
|
||||
);
|
|
@ -0,0 +1,137 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`formatHistogramData adds to existing down count 1`] = `
|
||||
Object {
|
||||
"downSeriesData": Array [
|
||||
Object {
|
||||
"x": 10,
|
||||
"x0": 11,
|
||||
"y": 2,
|
||||
},
|
||||
Object {
|
||||
"x": 11,
|
||||
"x0": 12,
|
||||
"y": 2,
|
||||
},
|
||||
Object {
|
||||
"x": 12,
|
||||
"x0": 13,
|
||||
"y": 1,
|
||||
},
|
||||
],
|
||||
"upSeriesData": Array [
|
||||
Object {
|
||||
"x": 10,
|
||||
"x0": 11,
|
||||
"y": 1,
|
||||
},
|
||||
Object {
|
||||
"x": 11,
|
||||
"x0": 12,
|
||||
"y": 1,
|
||||
},
|
||||
Object {
|
||||
"x": 12,
|
||||
"x0": 13,
|
||||
"y": 2,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`formatHistogramData adds to existing up count 1`] = `
|
||||
Object {
|
||||
"downSeriesData": Array [
|
||||
Object {
|
||||
"x": 10,
|
||||
"x0": 11,
|
||||
"y": 1,
|
||||
},
|
||||
Object {
|
||||
"x": 11,
|
||||
"x0": 12,
|
||||
"y": 1,
|
||||
},
|
||||
],
|
||||
"upSeriesData": Array [
|
||||
Object {
|
||||
"x": 10,
|
||||
"x0": 11,
|
||||
"y": 1,
|
||||
},
|
||||
Object {
|
||||
"x": 11,
|
||||
"x0": 12,
|
||||
"y": 1,
|
||||
},
|
||||
Object {
|
||||
"x": 12,
|
||||
"x0": 13,
|
||||
"y": 2,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`formatHistogramData doesn't add an entry to either count when none exists 1`] = `
|
||||
Object {
|
||||
"downSeriesData": Array [
|
||||
Object {
|
||||
"x": 10,
|
||||
"x0": 11,
|
||||
"y": 2,
|
||||
},
|
||||
Object {
|
||||
"x": 11,
|
||||
"x0": 12,
|
||||
"y": 1,
|
||||
},
|
||||
Object {
|
||||
"x": 12,
|
||||
"x0": 13,
|
||||
"y": 1,
|
||||
},
|
||||
],
|
||||
"upSeriesData": Array [
|
||||
Object {
|
||||
"x": 10,
|
||||
"x0": 11,
|
||||
"y": 1,
|
||||
},
|
||||
Object {
|
||||
"x": 11,
|
||||
"x0": 12,
|
||||
"y": 1,
|
||||
},
|
||||
Object {
|
||||
"x": 12,
|
||||
"x0": 13,
|
||||
"y": 2,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`formatHistogramData filters out null data sets 1`] = `
|
||||
Object {
|
||||
"downSeriesData": Array [
|
||||
Object {
|
||||
"x": 10,
|
||||
"x0": 11,
|
||||
"y": 1,
|
||||
},
|
||||
Object {
|
||||
"x": 11,
|
||||
"x0": 12,
|
||||
"y": 1,
|
||||
},
|
||||
],
|
||||
"upSeriesData": Array [
|
||||
Object {
|
||||
"x": 12,
|
||||
"x0": 13,
|
||||
"y": 1,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* 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 { HistogramSeries } from 'x-pack/plugins/uptime/common/graphql/types';
|
||||
import { formatHistogramData } from '../format_histogram_data';
|
||||
|
||||
describe('formatHistogramData', () => {
|
||||
it('returns an empty arrays when no data is provided', () => {
|
||||
const result = formatHistogramData([]);
|
||||
expect(result).toEqual({ downSeriesData: [], upSeriesData: [] });
|
||||
});
|
||||
it('filters out null data sets', () => {
|
||||
const seriesList: HistogramSeries[] = [
|
||||
{
|
||||
monitorId: 'monitor1',
|
||||
data: null,
|
||||
},
|
||||
{
|
||||
monitorId: 'monitor2',
|
||||
data: [
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 2,
|
||||
x: 10,
|
||||
x0: 11,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 2,
|
||||
x: 11,
|
||||
x0: 12,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: 4,
|
||||
downCount: null,
|
||||
x: 12,
|
||||
x0: 13,
|
||||
y: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const result = formatHistogramData(seriesList);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('adds to existing up count', () => {
|
||||
const seriesList: HistogramSeries[] = [
|
||||
{
|
||||
monitorId: 'monitor1',
|
||||
data: [
|
||||
{
|
||||
upCount: 3,
|
||||
downCount: null,
|
||||
x: 10,
|
||||
x0: 11,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: 3,
|
||||
downCount: null,
|
||||
x: 11,
|
||||
x0: 12,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: 3,
|
||||
downCount: null,
|
||||
x: 12,
|
||||
x0: 13,
|
||||
y: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'monitor2',
|
||||
data: [
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 2,
|
||||
x: 10,
|
||||
x0: 11,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 2,
|
||||
x: 11,
|
||||
x0: 12,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: 4,
|
||||
downCount: null,
|
||||
x: 12,
|
||||
x0: 13,
|
||||
y: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const result = formatHistogramData(seriesList);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
it('adds to existing down count', () => {
|
||||
const seriesList: HistogramSeries[] = [
|
||||
{
|
||||
monitorId: 'monitor1',
|
||||
data: [
|
||||
{
|
||||
upCount: 3,
|
||||
downCount: null,
|
||||
x: 10,
|
||||
x0: 11,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: 3,
|
||||
downCount: null,
|
||||
x: 11,
|
||||
x0: 12,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: 3,
|
||||
downCount: null,
|
||||
x: 12,
|
||||
x0: 13,
|
||||
y: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'monitor2',
|
||||
data: [
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 2,
|
||||
x: 10,
|
||||
x0: 11,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 2,
|
||||
x: 11,
|
||||
x0: 12,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: 4,
|
||||
downCount: null,
|
||||
x: 12,
|
||||
x0: 13,
|
||||
y: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'monitor3',
|
||||
data: [
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 24,
|
||||
x: 10,
|
||||
x0: 11,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 23,
|
||||
x: 11,
|
||||
x0: 12,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 35,
|
||||
x: 12,
|
||||
x0: 13,
|
||||
y: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const result = formatHistogramData(seriesList);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it(`doesn't add an entry to either count when none exists`, () => {
|
||||
const seriesList: HistogramSeries[] = [
|
||||
{
|
||||
monitorId: 'monitor1',
|
||||
data: [
|
||||
{
|
||||
upCount: 3,
|
||||
downCount: null,
|
||||
x: 10,
|
||||
x0: 11,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: 3,
|
||||
downCount: null,
|
||||
x: 11,
|
||||
x0: 12,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: 3,
|
||||
downCount: null,
|
||||
x: 12,
|
||||
x0: 13,
|
||||
y: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'monitor2',
|
||||
data: [
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 2,
|
||||
x: 10,
|
||||
x0: 11,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 2,
|
||||
x: 11,
|
||||
x0: 12,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: 4,
|
||||
downCount: null,
|
||||
x: 12,
|
||||
x0: 13,
|
||||
y: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
monitorId: 'monitor3',
|
||||
data: [
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 24,
|
||||
x: 10,
|
||||
x0: 11,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: null,
|
||||
downCount: null,
|
||||
x: 11,
|
||||
x0: 12,
|
||||
y: 4,
|
||||
},
|
||||
{
|
||||
upCount: null,
|
||||
downCount: 35,
|
||||
x: 12,
|
||||
x0: 13,
|
||||
y: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const result = formatHistogramData(seriesList);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -6,36 +6,48 @@
|
|||
|
||||
import { HistogramDataPoint, HistogramSeries } from '../../../../common/graphql/types';
|
||||
|
||||
export const formatHistogramData = (histogram: HistogramSeries[]) => {
|
||||
const histogramSeriesData: { upSeriesData: any[]; downSeriesData: any[] } = {
|
||||
upSeriesData: [],
|
||||
downSeriesData: [],
|
||||
};
|
||||
// TODO: there's a lot of nesting here, refactor this function
|
||||
histogram.forEach(({ data }) => {
|
||||
if (data) {
|
||||
data.forEach(dataPoint => {
|
||||
if (dataPoint) {
|
||||
const { x, x0, downCount } = dataPoint;
|
||||
interface FormattedHistogramData {
|
||||
upSeriesData: HistogramDataPoint[];
|
||||
downSeriesData: HistogramDataPoint[];
|
||||
}
|
||||
|
||||
/**
|
||||
* This function reduces a series of monitors' histograms into a singular
|
||||
* series, which is then displayed as a unified snapshot of the performance
|
||||
* of all the monitors over time.
|
||||
* @param histograms The series data for the provided monitors
|
||||
*/
|
||||
export const formatHistogramData = (histograms: HistogramSeries[]): FormattedHistogramData => {
|
||||
return histograms
|
||||
.map(({ data }) => data)
|
||||
.filter(series => series !== null && series !== undefined)
|
||||
.reduce(
|
||||
(accumulatedData: FormattedHistogramData, data) => {
|
||||
// `data` will not be null/undefined because those elements are filtered
|
||||
data!.forEach(dataPoint => {
|
||||
const { x, x0, downCount, upCount } = dataPoint;
|
||||
const findPointInSeries = (hdp: HistogramDataPoint) => hdp.x === x && hdp.x0 === x0;
|
||||
const upEntry = histogramSeriesData.upSeriesData.find(findPointInSeries);
|
||||
const downEntry = histogramSeriesData.downSeriesData.find(findPointInSeries);
|
||||
const upEntry = accumulatedData.upSeriesData.find(findPointInSeries);
|
||||
const downEntry = accumulatedData.downSeriesData.find(findPointInSeries);
|
||||
if (downCount) {
|
||||
if (downEntry) {
|
||||
downEntry.y += 1;
|
||||
} else {
|
||||
histogramSeriesData.downSeriesData.push({ x, x0, y: 1 });
|
||||
accumulatedData.downSeriesData.push({ x, x0, y: 1 });
|
||||
}
|
||||
} else {
|
||||
} else if (upCount) {
|
||||
if (upEntry) {
|
||||
upEntry.y += 1;
|
||||
} else {
|
||||
histogramSeriesData.upSeriesData.push({ x, x0, y: 1 });
|
||||
accumulatedData.upSeriesData.push({ x, x0, y: 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return histogramSeriesData;
|
||||
});
|
||||
return accumulatedData;
|
||||
},
|
||||
{
|
||||
upSeriesData: [],
|
||||
downSeriesData: [],
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -12,10 +12,12 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import React, { Fragment } from 'react';
|
||||
import { getMonitorPageBreadcrumb } from '../breadcrumbs';
|
||||
import { MonitorCharts } from '../components/queries/monitor_charts';
|
||||
import { MonitorPageTitleQuery } from '../components/queries/monitor_page_title';
|
||||
import { MonitorStatusBar } from '../components/queries/monitor_status_bar';
|
||||
import { Pings } from '../components/queries/ping_list';
|
||||
import {
|
||||
MonitorChartsQuery,
|
||||
MonitorPageTitleQuery,
|
||||
MonitorStatusBarQuery,
|
||||
PingListQuery,
|
||||
} from '../components/queries';
|
||||
import { UMUpdateBreadcrumbs } from '../lib/lib';
|
||||
import { UptimeCommonProps } from '../uptime_app';
|
||||
|
||||
|
@ -45,11 +47,11 @@ export class MonitorPage extends React.Component<Props> {
|
|||
<Fragment>
|
||||
<MonitorPageTitleQuery monitorId={id} {...this.props} />
|
||||
<EuiSpacer />
|
||||
<MonitorStatusBar monitorId={id} {...this.props} />
|
||||
<MonitorStatusBarQuery monitorId={id} {...this.props} />
|
||||
<EuiSpacer />
|
||||
<MonitorCharts monitorId={id} {...this.props} />
|
||||
<MonitorChartsQuery monitorId={id} {...this.props} />
|
||||
<EuiSpacer />
|
||||
<Pings monitorId={id} {...this.props} />
|
||||
<PingListQuery monitorId={id} {...this.props} />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
import { EuiSpacer } from '@elastic/eui';
|
||||
import React, { Fragment } from 'react';
|
||||
import { getOverviewPageBreadcrumbs } from '../breadcrumbs';
|
||||
import { EmptyState } from '../components/queries/empty_state';
|
||||
import { ErrorList } from '../components/queries/error_list';
|
||||
import { FilterBar } from '../components/queries/filter_bar';
|
||||
import { MonitorList } from '../components/queries/monitor_list';
|
||||
import { Snapshot } from '../components/queries/snapshot';
|
||||
import {
|
||||
EmptyStateQuery,
|
||||
ErrorListQuery,
|
||||
FilterBarQuery,
|
||||
MonitorListQuery,
|
||||
SnapshotQuery,
|
||||
} from '../components/queries';
|
||||
import { UMUpdateBreadcrumbs } from '../lib/lib';
|
||||
import { UptimeCommonProps } from '../uptime_app';
|
||||
|
||||
|
@ -40,19 +42,19 @@ export class OverviewPage extends React.Component<Props, OverviewPageState> {
|
|||
public render() {
|
||||
return (
|
||||
<Fragment>
|
||||
<EmptyState {...this.props}>
|
||||
<FilterBar
|
||||
<EmptyStateQuery {...this.props}>
|
||||
<FilterBarQuery
|
||||
{...this.props}
|
||||
updateQuery={(query: object | undefined) => {
|
||||
this.setState({ currentFilterQuery: query ? JSON.stringify(query) : query });
|
||||
}}
|
||||
/>
|
||||
<Snapshot filters={this.state.currentFilterQuery} {...this.props} />
|
||||
<SnapshotQuery filters={this.state.currentFilterQuery} {...this.props} />
|
||||
<EuiSpacer size="xl" />
|
||||
<MonitorList filters={this.state.currentFilterQuery} {...this.props} />
|
||||
<MonitorListQuery filters={this.state.currentFilterQuery} {...this.props} />
|
||||
<EuiSpacer />
|
||||
<ErrorList filters={this.state.currentFilterQuery} {...this.props} />
|
||||
</EmptyState>
|
||||
<ErrorListQuery filters={this.state.currentFilterQuery} {...this.props} />
|
||||
</EmptyStateQuery>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -25,14 +25,14 @@ export const monitorsSchema = gql`
|
|||
|
||||
type HistogramSeries {
|
||||
monitorId: String
|
||||
data: [HistogramDataPoint]
|
||||
data: [HistogramDataPoint!]
|
||||
}
|
||||
|
||||
type Snapshot {
|
||||
up: Int
|
||||
down: Int
|
||||
total: Int
|
||||
histogram: [HistogramSeries]
|
||||
histogram: [HistogramSeries!]
|
||||
}
|
||||
|
||||
type DataPoint {
|
||||
|
@ -78,7 +78,7 @@ export const monitorsSchema = gql`
|
|||
}
|
||||
|
||||
type LatestMonitorsResult {
|
||||
monitors: [LatestMonitor]
|
||||
monitors: [LatestMonitor!]
|
||||
}
|
||||
|
||||
type ErrorListItem {
|
||||
|
@ -115,7 +115,7 @@ export const monitorsSchema = gql`
|
|||
|
||||
getFilterBar(dateRangeStart: String!, dateRangeEnd: String!): FilterBar
|
||||
|
||||
getErrorsList(dateRangeStart: String!, dateRangeEnd: String!, filters: String): [ErrorListItem]
|
||||
getErrorsList(dateRangeStart: String!, dateRangeEnd: String!, filters: String): [ErrorListItem!]
|
||||
|
||||
getMonitorPageTitle(monitorId: String!): MonitorPageTitle
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ export default function ({ getService }) {
|
|||
.post('/api/uptime/graphql')
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send({ ...getMonitorStatusBarQuery });
|
||||
|
||||
expect({ monitorStatus: responseData.map(status => omit(status, 'millisFromNow')) }).to.eql(
|
||||
monitorStatus
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue