From a1594dfb6a2f516ffc4093da9c7338aebc509c13 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 24 Sep 2018 12:59:18 -0400 Subject: [PATCH] [Monitoring] APM Monitoring UI (#22975) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Merge in boilerplate branch * Manually copy over the specific metrics and UIs * Add api integration tests * Fix tests * Remove unused metrics * Update snapshot * Fix tests * Remove types agg * Use ApmClusterMetric * provide description for apm-server monitoring metrics (#23331) * Vis LESS to SASS (cont.) (#23199) * Tweak migrations integraiton tests to have a stable sort (#23265) * Fix: plugin api route with security enabled (#23334) Closes https://github.com/elastic/kibana/issues/23266 This is more of a quick fix than the final solution. The issue was that Canvas tries to check the plugins API without checking to see if the user it logged in. As a result, instead of the plugins response, it gets the HTML from the login page and that causes an error to be thrown when attempting to parse the results. For now, this PR just disables the auth requirement on the Canvas plugin API endpoint. * [migrations/tests] sort results before assertion (#23347) There have been several failures in this test, seemingly caused by a lack of sorting in the results. It makes sense that since both migrations are run simultaneously that sometimes one would succeed and sometimes another would, so I've just sorted the results before checking. ![image](https://user-images.githubusercontent.com/1329312/45791153-44e9cc80-bc3d-11e8-88c4-760d4c7b35bd.png) cc: @chrisdavies * [ML] Moves custom URL editor Add button and form to top of flyout (#23326) * [ML] Moves custom URL editor Add button and form to top of flyout * [ML] Edits to custom URL editor class name * Graph LESS to SASS (#23348) * Developer documentation for integrating with the telemetry service (#23295) * Developer documentation for integrating with the telemetry service * open with a bang * more faqs * thing about tracking ui interactions * talk to the plat team * create and register * Fix a bug where ES sends a string and migrations expect a boolean (#23313) * chore: use cheerio in i18n.html.getDirectiveMessages (#23342) this was only using jsdom to parse html, but cheerio allows parsing html without requiring a dom. cheerio was also already in the dependency list. * [core/utils] add shareWeakReplay() operator (#23333) * Chore: fix canvas test runner (#23336) Blocked by https://github.com/elastic/kibana/pull/23342 This fixes the local test runner in Canvas. It should not affect anything else, including the CI test runner. - Bumps JSDOM to ^12.0.0 - I matched Kibana's version on migration, but nothing else in X-Pack uses JSDOM, so we can use the newer version (which has a very different API) - I had to match it because of a script that enforces version matching, but #23342 removed jsdom from Kibana, so we no longer have a version to match - Restores the local `.babelrc` file - I thought it was only used for building plugins; I was wrong 😢 * Convert Discover open top nav to EUI flyout (#22971) * move find logic to SavedObjectFinder component since savedObjectClient is no longer coupled to angular * implement flyout open saved searches * remove old open stuff * add jest test for OpenSearchPanel and simplify panel title * fix functional tests * fix _lab_mode functional test * Migrate save top nav in Discover and Visualize to EUI (#23190) * extract reusable save component from DashboardSaveModal * update discover search to use SavedObjectSaveModal * create generic show_save_model that works for both discover and dashboard * fix last bits of discover save * remove old save functionallity * migrate visualize save to EUI * fix functional tests * disable save button if title is empty * mark title input as invalid when title is not provided * fix funtional tests * Moves styleSheetPath to uiExports (#23007) This was previously defined in uiExports.app, which limited plugins which are not an app of providing a stylesheet. This allows any plugin to define a stylesheet which will be available on page load. * Timelion less to sass (#23339) * Consistent casing * Fix snapshot * Update tests --- .../public/components/apm/instance/index.js | 7 + .../components/apm/instance/instance.js | 59 + .../public/components/apm/instance/status.js | 64 + .../public/components/apm/instances/index.js | 7 + .../components/apm/instances/instances.js | 107 ++ .../public/components/apm/instances/status.js | 54 + .../public/components/apm/overview/index.js | 63 + .../public/components/apm/status_icon.js | 23 + .../components/cluster/overview/apm_panel.js | 88 ++ .../components/cluster/overview/helpers.js | 1 + .../components/cluster/overview/index.js | 3 + .../public/directives/main/index.html | 6 + .../public/directives/main/index.js | 2 + .../public/services/breadcrumbs_provider.js | 16 + x-pack/plugins/monitoring/public/views/all.js | 3 + .../public/views/apm/instance/index.html | 8 + .../public/views/apm/instance/index.js | 64 + .../public/views/apm/instances/index.html | 7 + .../public/views/apm/instances/index.js | 70 ++ .../public/views/apm/overview/index.html | 7 + .../public/views/apm/overview/index.js | 54 + .../monitoring/server/lib/apm/_apm_stats.js | 114 ++ .../server/lib/apm/_get_time_of_last_event.js | 43 + .../server/lib/apm/create_apm_query.js | 34 + .../monitoring/server/lib/apm/get_apm_info.js | 111 ++ .../monitoring/server/lib/apm/get_apms.js | 140 +++ .../server/lib/apm/get_apms_for_clusters.js | 80 ++ .../monitoring/server/lib/apm/get_stats.js | 70 ++ .../monitoring/server/lib/apm/index.js | 10 + .../get_clusters_summary.test.js.snap | 4 + .../lib/cluster/get_clusters_from_request.js | 17 +- .../lib/cluster/get_clusters_summary.js | 2 + .../server/lib/details/get_series.js | 4 + .../__snapshots__/metrics.test.js.snap | 1035 +++++++++++++++++ .../server/lib/metrics/apm/classes.js | 118 ++ .../server/lib/metrics/apm/metrics.js | 222 ++++ .../monitoring/server/lib/metrics/index.js | 1 + .../monitoring/server/lib/metrics/metrics.js | 4 +- .../api/v1/apm/_get_apm_cluster_status.js | 14 + .../server/routes/api/v1/apm/index.js | 9 + .../server/routes/api/v1/apm/instance.js | 55 + .../server/routes/api/v1/apm/instances.js | 53 + .../routes/api/v1/apm/metric_set_instance.js | 80 ++ .../routes/api/v1/apm/metric_set_overview.js | 80 ++ .../server/routes/api/v1/apm/overview.js | 56 + .../server/routes/api/v1/cluster/cluster.js | 3 +- .../server/routes/api/v1/cluster/clusters.js | 3 +- .../monitoring/server/routes/api/v1/ui.js | 5 + .../apis/monitoring/apm/fixtures/cluster.json | 712 ++++++++++++ .../monitoring/apm/fixtures/instance.json | 718 ++++++++++++ .../apis/monitoring/apm/index.js | 13 + .../apis/monitoring/apm/instance.js | 39 + .../apis/monitoring/apm/instances.js | 73 ++ .../apis/monitoring/apm/overview.js | 39 + .../cluster/fixtures/multicluster.json | 24 + .../monitoring/cluster/fixtures/overview.json | 8 + .../api_integration/apis/monitoring/index.js | 1 + .../es_archives/monitoring/apm/data.json.gz | Bin 0 -> 6660 bytes .../es_archives/monitoring/apm/mappings.json | 688 +++++++++++ 59 files changed, 5391 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/monitoring/public/components/apm/instance/index.js create mode 100644 x-pack/plugins/monitoring/public/components/apm/instance/instance.js create mode 100644 x-pack/plugins/monitoring/public/components/apm/instance/status.js create mode 100644 x-pack/plugins/monitoring/public/components/apm/instances/index.js create mode 100644 x-pack/plugins/monitoring/public/components/apm/instances/instances.js create mode 100644 x-pack/plugins/monitoring/public/components/apm/instances/status.js create mode 100644 x-pack/plugins/monitoring/public/components/apm/overview/index.js create mode 100644 x-pack/plugins/monitoring/public/components/apm/status_icon.js create mode 100644 x-pack/plugins/monitoring/public/components/cluster/overview/apm_panel.js create mode 100644 x-pack/plugins/monitoring/public/views/apm/instance/index.html create mode 100644 x-pack/plugins/monitoring/public/views/apm/instance/index.js create mode 100644 x-pack/plugins/monitoring/public/views/apm/instances/index.html create mode 100644 x-pack/plugins/monitoring/public/views/apm/instances/index.js create mode 100644 x-pack/plugins/monitoring/public/views/apm/overview/index.html create mode 100644 x-pack/plugins/monitoring/public/views/apm/overview/index.js create mode 100644 x-pack/plugins/monitoring/server/lib/apm/_apm_stats.js create mode 100644 x-pack/plugins/monitoring/server/lib/apm/_get_time_of_last_event.js create mode 100644 x-pack/plugins/monitoring/server/lib/apm/create_apm_query.js create mode 100644 x-pack/plugins/monitoring/server/lib/apm/get_apm_info.js create mode 100644 x-pack/plugins/monitoring/server/lib/apm/get_apms.js create mode 100644 x-pack/plugins/monitoring/server/lib/apm/get_apms_for_clusters.js create mode 100644 x-pack/plugins/monitoring/server/lib/apm/get_stats.js create mode 100644 x-pack/plugins/monitoring/server/lib/apm/index.js create mode 100644 x-pack/plugins/monitoring/server/lib/metrics/apm/classes.js create mode 100644 x-pack/plugins/monitoring/server/lib/metrics/apm/metrics.js create mode 100644 x-pack/plugins/monitoring/server/routes/api/v1/apm/_get_apm_cluster_status.js create mode 100644 x-pack/plugins/monitoring/server/routes/api/v1/apm/index.js create mode 100644 x-pack/plugins/monitoring/server/routes/api/v1/apm/instance.js create mode 100644 x-pack/plugins/monitoring/server/routes/api/v1/apm/instances.js create mode 100644 x-pack/plugins/monitoring/server/routes/api/v1/apm/metric_set_instance.js create mode 100644 x-pack/plugins/monitoring/server/routes/api/v1/apm/metric_set_overview.js create mode 100644 x-pack/plugins/monitoring/server/routes/api/v1/apm/overview.js create mode 100644 x-pack/test/api_integration/apis/monitoring/apm/fixtures/cluster.json create mode 100644 x-pack/test/api_integration/apis/monitoring/apm/fixtures/instance.json create mode 100644 x-pack/test/api_integration/apis/monitoring/apm/index.js create mode 100644 x-pack/test/api_integration/apis/monitoring/apm/instance.js create mode 100644 x-pack/test/api_integration/apis/monitoring/apm/instances.js create mode 100644 x-pack/test/api_integration/apis/monitoring/apm/overview.js create mode 100644 x-pack/test/functional/es_archives/monitoring/apm/data.json.gz create mode 100644 x-pack/test/functional/es_archives/monitoring/apm/mappings.json diff --git a/x-pack/plugins/monitoring/public/components/apm/instance/index.js b/x-pack/plugins/monitoring/public/components/apm/instance/index.js new file mode 100644 index 000000000000000..50462a66fc13448 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/apm/instance/index.js @@ -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 { ApmServerInstance } from './instance'; diff --git a/x-pack/plugins/monitoring/public/components/apm/instance/instance.js b/x-pack/plugins/monitoring/public/components/apm/instance/instance.js new file mode 100644 index 000000000000000..c40d19d384a0d11 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/apm/instance/instance.js @@ -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 { MonitoringTimeseriesContainer } from '../../chart'; +import { + EuiFlexItem, + EuiPanel, + EuiSpacer, + EuiPage, + EuiPageBody, + EuiFlexGroup +} from '@elastic/eui'; +import { Status } from './status'; + +export function ApmServerInstance({ summary, metrics, ...props }) { + const seriesToShow = [ + metrics.apm_responses_valid, + metrics.apm_responses_errors, + + metrics.apm_output_events_rate_success, + metrics.apm_output_events_rate_failure, + + metrics.apm_requests, + metrics.apm_transformations, + + + metrics.apm_cpu, + metrics.apm_memory, + + metrics.apm_os_load, + ]; + + const charts = seriesToShow.map((data, index) => ( + + + + + + )); + + return ( + + + + + + {charts} + + + + ); +} diff --git a/x-pack/plugins/monitoring/public/components/apm/instance/status.js b/x-pack/plugins/monitoring/public/components/apm/instance/status.js new file mode 100644 index 000000000000000..f68bf6a72d2f810 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/apm/instance/status.js @@ -0,0 +1,64 @@ +/* + * 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 moment from 'moment'; +import { SummaryStatus } from '../../summary_status'; +import { ApmStatusIcon } from '../status_icon'; +import { formatMetric } from '../../../lib/format_number'; +import { formatTimestampToDuration } from '../../../../common'; + +export function Status({ stats }) { + const { + name, + output, + version, + uptime, + timeOfLastEvent, + } = stats; + + const metrics = [ + { + label: 'Name', + value: name, + dataTestSubj: 'name' + }, + { + label: 'Output', + value: output, + dataTestSubj: 'output' + }, + { + label: 'Version', + value: version, + dataTestSubj: 'version' + }, + { + label: 'Uptime', + value: formatMetric(uptime, 'time_since'), + dataTestSubj: 'uptime' + }, + { + label: 'Last Event', + value: formatTimestampToDuration(+moment(timeOfLastEvent), 'since') + ' ago', + dataTestSubj: 'timeOfLastEvent', + } + ]; + + const IconComponent = ({ status }) => ( + + Status: + + ); + + return ( + + ); +} diff --git a/x-pack/plugins/monitoring/public/components/apm/instances/index.js b/x-pack/plugins/monitoring/public/components/apm/instances/index.js new file mode 100644 index 000000000000000..b6d0d6fa853ba70 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/apm/instances/index.js @@ -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 { ApmServerInstances } from './instances'; diff --git a/x-pack/plugins/monitoring/public/components/apm/instances/instances.js b/x-pack/plugins/monitoring/public/components/apm/instances/instances.js new file mode 100644 index 000000000000000..66b67cedbf0654c --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/apm/instances/instances.js @@ -0,0 +1,107 @@ +/* + * 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 moment from 'moment'; +import { MonitoringTable } from '../../table'; +import { + KuiTableRowCell, + KuiTableRow +} from '@kbn/ui-framework/components'; +import { EuiLink } from '@elastic/eui'; +import { Status } from './status'; +import { SORT_ASCENDING, SORT_DESCENDING, TABLE_ACTION_UPDATE_FILTER } from '../../../../common/constants'; +import { formatMetric } from '../../../lib/format_number'; +import { formatTimestampToDuration } from '../../../../common'; + + +const filterFields = [ 'name', 'type', 'version', 'output' ]; +const columns = [ + { title: 'Name', sortKey: 'name', sortOrder: SORT_ASCENDING }, + { title: 'Output Enabled', sortKey: 'output' }, + { title: 'Total Events Rate', sortKey: 'total_events_rate', secondarySortOrder: SORT_DESCENDING }, + { title: 'Bytes Sent Rate', sortKey: 'bytes_sent_rate' }, + { title: 'Output Errors', sortKey: 'errors' }, + { title: 'Last Event', sortKey: 'time_of_last_event' }, + { title: 'Allocated Memory', sortKey: 'memory' }, + { title: 'Version', sortKey: 'version' }, +]; +const instanceRowFactory = () => { + return function KibanaRow(props) { + const applyFiltering = filterText => () => { + props.dispatchTableAction(TABLE_ACTION_UPDATE_FILTER, filterText); + }; + + return ( + + +
+ + {props.name} + +
+
+ + {props.output} + + + {formatMetric(props.total_events_rate, '', '/s')} + + + {formatMetric(props.bytes_sent_rate, 'byte', '/s')} + + + {formatMetric(props.errors, '0')} + + + {formatTimestampToDuration(+moment(props.time_of_last_event), 'since') + ' ago'} + + + {formatMetric(props.memory, 'byte')} + + + + {props.version} + + +
+ ); + }; +}; + +export function ApmServerInstances({ apms }) { + const { + pageIndex, + filterText, + sortKey, + sortOrder, + onNewState, + } = apms; + + return ( +
+ + +
+ ); +} diff --git a/x-pack/plugins/monitoring/public/components/apm/instances/status.js b/x-pack/plugins/monitoring/public/components/apm/instances/status.js new file mode 100644 index 000000000000000..e51063f02979b60 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/apm/instances/status.js @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Fragment } from 'react'; +import moment from 'moment'; +import { SummaryStatus } from '../../summary_status'; +import { ApmStatusIcon } from '../status_icon'; +import { formatMetric } from '../../../lib/format_number'; +import { formatTimestampToDuration } from '../../../../common'; + +export function Status({ stats }) { + const { + apms: { + total + }, + totalEvents, + timeOfLastEvent, + } = stats; + + const metrics = [ + { + label: 'Servers', + value: total, + dataTestSubj: 'total' + }, + { + label: 'Total Events', + value: formatMetric(totalEvents, '0.[0]a'), + dataTestSubj: 'totalEvents' + }, + { + label: 'Last Event', + value: formatTimestampToDuration(+moment(timeOfLastEvent), 'since') + ' ago', + dataTestSubj: 'timeOfLastEvent', + } + ]; + + const IconComponent = ({ status }) => ( + + Status: + + ); + + return ( + + ); +} diff --git a/x-pack/plugins/monitoring/public/components/apm/overview/index.js b/x-pack/plugins/monitoring/public/components/apm/overview/index.js new file mode 100644 index 000000000000000..634a5e78127c0a4 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/apm/overview/index.js @@ -0,0 +1,63 @@ +/* + * 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 { MonitoringTimeseriesContainer } from '../../chart'; +import { + EuiSpacer, + EuiPage, + EuiFlexGroup, + EuiFlexItem, + EuiPageBody, + EuiPanel +} from '@elastic/eui'; +import { Status } from '../instances/status'; + +export function ApmOverview({ + stats, + metrics, + ...props +}) { + const seriesToShow = [ + metrics.apm_responses_valid, + metrics.apm_responses_errors, + + metrics.apm_output_events_rate_success, + metrics.apm_output_events_rate_failure, + + metrics.apm_requests, + metrics.apm_transformations, + + + metrics.apm_cpu, + metrics.apm_memory, + + metrics.apm_os_load, + ]; + + const charts = seriesToShow.map((data, index) => ( + + + + + + )); + + return ( + + + + + + {charts} + + + + ); +} diff --git a/x-pack/plugins/monitoring/public/components/apm/status_icon.js b/x-pack/plugins/monitoring/public/components/apm/status_icon.js new file mode 100644 index 000000000000000..49fe0faed1ad1b4 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/apm/status_icon.js @@ -0,0 +1,23 @@ +/* + * 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 { StatusIcon } from 'plugins/monitoring/components/status_icon'; + +export function ApmStatusIcon({ status, availability = true }) { + const type = (() => { + if (!availability) { + return StatusIcon.TYPES.GRAY; + } + + const statusKey = status.toUpperCase(); + return StatusIcon.TYPES[statusKey] || StatusIcon.TYPES.YELLOW; + })(); + + return ( + + ); +} diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/apm_panel.js b/x-pack/plugins/monitoring/public/components/cluster/overview/apm_panel.js new file mode 100644 index 000000000000000..a5726ab46666c15 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/apm_panel.js @@ -0,0 +1,88 @@ +/* + * 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 moment from 'moment'; +import { get } from 'lodash'; +import { formatMetric } from 'plugins/monitoring/lib/format_number'; +import { ClusterItemContainer, BytesPercentageUsage } from './helpers'; + +import { + EuiFlexGrid, + EuiFlexItem, + EuiLink, + EuiTitle, + EuiPanel, + EuiDescriptionList, + EuiDescriptionListTitle, + EuiDescriptionListDescription, + EuiHorizontalRule, +} from '@elastic/eui'; +import { formatTimestampToDuration } from '../../../../common'; + +export function ApmPanel(props) { + if (!get(props, 'apms.total', 0) > 0) { + return null; + } + + const goToApm = () => props.changeUrl('apm'); + const goToInstances = () => props.changeUrl('apm/instances'); + + return ( + + + + + +

+ + Overview + +

+
+ + + Processed Events + + {formatMetric(props.totalEvents, '0.[0]a')} + + Last Event + + {formatTimestampToDuration(+moment(props.timeOfLastEvent), 'since') + ' ago'} + + +
+
+ + + +

+ + APM Servers: {props.apms.total} + +

+
+ + + Memory Usage + + + + +
+
+
+
+ ); +} diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/helpers.js b/x-pack/plugins/monitoring/public/components/cluster/overview/helpers.js index c0e3a6a6b28e4c6..88c0e1b91940f79 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/overview/helpers.js +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/helpers.js @@ -53,6 +53,7 @@ export function ClusterItemContainer(props) { kibana: 'logoKibana', logstash: 'logoLogstash', beats: 'logoBeats', + apm: 'apmApp' }; const icon = iconMap[props.url]; diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/index.js b/x-pack/plugins/monitoring/public/components/cluster/overview/index.js index ba166d73e449b1d..67549912e531563 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/overview/index.js +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/index.js @@ -12,6 +12,7 @@ import { AlertsPanel } from './alerts_panel'; import { BeatsPanel } from './beats_panel'; import { EuiPage, EuiPageBody } from '@elastic/eui'; +import { ApmPanel } from './apm_panel'; export function Overview(props) { return ( @@ -33,6 +34,8 @@ export function Overview(props) { + + ); diff --git a/x-pack/plugins/monitoring/public/directives/main/index.html b/x-pack/plugins/monitoring/public/directives/main/index.html index 2804898b85283aa..c48775107dd4c07 100644 --- a/x-pack/plugins/monitoring/public/directives/main/index.html +++ b/x-pack/plugins/monitoring/public/directives/main/index.html @@ -60,6 +60,12 @@ {{ monitoringMain.instance }} + +