[Monitoring] Fix issue with ES node detail status (#72298)
* Fix issue with ES node detail status * Add test
This commit is contained in:
parent
f487867fda
commit
f0d3cb96a4
|
@ -20,6 +20,10 @@ interface Props {
|
||||||
export const AlertsStatus: React.FC<Props> = (props: Props) => {
|
export const AlertsStatus: React.FC<Props> = (props: Props) => {
|
||||||
const { alerts, showBadge = false, showOnlyCount = false } = props;
|
const { alerts, showBadge = false, showOnlyCount = false } = props;
|
||||||
|
|
||||||
|
if (!alerts) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
let atLeastOneDanger = false;
|
let atLeastOneDanger = false;
|
||||||
const count = Object.values(alerts).reduce((cnt, alertStatus) => {
|
const count = Object.values(alerts).reduce((cnt, alertStatus) => {
|
||||||
if (alertStatus.states.length) {
|
if (alertStatus.states.length) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { NodeDetailStatus } from '../node_detail_status';
|
||||||
import { MonitoringTimeseriesContainer } from '../../chart';
|
import { MonitoringTimeseriesContainer } from '../../chart';
|
||||||
import { FormattedMessage } from '@kbn/i18n/react';
|
import { FormattedMessage } from '@kbn/i18n/react';
|
||||||
|
|
||||||
export const AdvancedNode = ({ nodeSummary, metrics, ...props }) => {
|
export const AdvancedNode = ({ nodeSummary, metrics, alerts, ...props }) => {
|
||||||
const metricsToShow = [
|
const metricsToShow = [
|
||||||
metrics.node_gc,
|
metrics.node_gc,
|
||||||
metrics.node_gc_time,
|
metrics.node_gc_time,
|
||||||
|
@ -50,7 +50,7 @@ export const AdvancedNode = ({ nodeSummary, metrics, ...props }) => {
|
||||||
</h1>
|
</h1>
|
||||||
</EuiScreenReaderOnly>
|
</EuiScreenReaderOnly>
|
||||||
<EuiPanel>
|
<EuiPanel>
|
||||||
<NodeDetailStatus stats={nodeSummary} />
|
<NodeDetailStatus stats={nodeSummary} alerts={alerts} />
|
||||||
</EuiPanel>
|
</EuiPanel>
|
||||||
<EuiSpacer size="m" />
|
<EuiSpacer size="m" />
|
||||||
<EuiPageContent>
|
<EuiPageContent>
|
||||||
|
|
|
@ -9,8 +9,9 @@ import { SummaryStatus } from '../../summary_status';
|
||||||
import { NodeStatusIcon } from '../node';
|
import { NodeStatusIcon } from '../node';
|
||||||
import { formatMetric } from '../../../lib/format_number';
|
import { formatMetric } from '../../../lib/format_number';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import { AlertsStatus } from '../../../alerts/status';
|
||||||
|
|
||||||
export function NodeDetailStatus({ stats, alerts }) {
|
export function NodeDetailStatus({ stats, alerts = {} }) {
|
||||||
const {
|
const {
|
||||||
transport_address: transportAddress,
|
transport_address: transportAddress,
|
||||||
usedHeap,
|
usedHeap,
|
||||||
|
@ -29,8 +30,10 @@ export function NodeDetailStatus({ stats, alerts }) {
|
||||||
|
|
||||||
const metrics = [
|
const metrics = [
|
||||||
{
|
{
|
||||||
label: 'Alerts',
|
label: i18n.translate('xpack.monitoring.elasticsearch.nodeDetailStatus.alerts', {
|
||||||
value: <span>{Object.values(alerts).length}</span>,
|
defaultMessage: 'Alerts',
|
||||||
|
}),
|
||||||
|
value: <AlertsStatus alerts={alerts} showOnlyCount={true} />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.translate('xpack.monitoring.elasticsearch.nodeDetailStatus.transportAddress', {
|
label: i18n.translate('xpack.monitoring.elasticsearch.nodeDetailStatus.transportAddress', {
|
||||||
|
|
|
@ -90,6 +90,7 @@
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
ng-if="monitoringMain.instance && (monitoringMain.name === 'nodes' || monitoringMain.name === 'indices')"
|
ng-if="monitoringMain.instance && (monitoringMain.name === 'nodes' || monitoringMain.name === 'indices')"
|
||||||
|
data-test-subj="esNodeDetailAdvancedLink"
|
||||||
kbn-href="#/elasticsearch/{{ monitoringMain.name }}/{{ monitoringMain.resolver }}/advanced"
|
kbn-href="#/elasticsearch/{{ monitoringMain.name }}/{{ monitoringMain.resolver }}/advanced"
|
||||||
class="euiTab"
|
class="euiTab"
|
||||||
ng-class="{'euiTab-isSelected': monitoringMain.page === 'advanced'}"
|
ng-class="{'euiTab-isSelected': monitoringMain.page === 'advanced'}"
|
||||||
|
|
|
@ -16,7 +16,7 @@ import template from './index.html';
|
||||||
import { Legacy } from '../../../../legacy_shims';
|
import { Legacy } from '../../../../legacy_shims';
|
||||||
import { AdvancedNode } from '../../../../components/elasticsearch/node/advanced';
|
import { AdvancedNode } from '../../../../components/elasticsearch/node/advanced';
|
||||||
import { MonitoringViewBaseController } from '../../../base_controller';
|
import { MonitoringViewBaseController } from '../../../base_controller';
|
||||||
import { CODE_PATH_ELASTICSEARCH } from '../../../../../common/constants';
|
import { CODE_PATH_ELASTICSEARCH, ALERT_CPU_USAGE } from '../../../../../common/constants';
|
||||||
|
|
||||||
function getPageData($injector) {
|
function getPageData($injector) {
|
||||||
const $http = $injector.get('$http');
|
const $http = $injector.get('$http');
|
||||||
|
@ -53,12 +53,26 @@ uiRoutes.when('/elasticsearch/nodes/:node/advanced', {
|
||||||
},
|
},
|
||||||
controller: class extends MonitoringViewBaseController {
|
controller: class extends MonitoringViewBaseController {
|
||||||
constructor($injector, $scope) {
|
constructor($injector, $scope) {
|
||||||
|
const $route = $injector.get('$route');
|
||||||
|
const nodeName = $route.current.params.node;
|
||||||
|
|
||||||
super({
|
super({
|
||||||
defaultData: {},
|
defaultData: {},
|
||||||
getPageData,
|
getPageData,
|
||||||
reactNodeId: 'monitoringElasticsearchAdvancedNodeApp',
|
reactNodeId: 'monitoringElasticsearchAdvancedNodeApp',
|
||||||
$scope,
|
$scope,
|
||||||
$injector,
|
$injector,
|
||||||
|
alerts: {
|
||||||
|
shouldFetch: true,
|
||||||
|
options: {
|
||||||
|
alertTypeIds: [ALERT_CPU_USAGE],
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
nodeUuid: nodeName,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$watch(
|
$scope.$watch(
|
||||||
|
@ -80,6 +94,7 @@ uiRoutes.when('/elasticsearch/nodes/:node/advanced', {
|
||||||
this.renderReact(
|
this.renderReact(
|
||||||
<AdvancedNode
|
<AdvancedNode
|
||||||
nodeSummary={data.nodeSummary}
|
nodeSummary={data.nodeSummary}
|
||||||
|
alerts={this.alerts}
|
||||||
metrics={data.metrics}
|
metrics={data.metrics}
|
||||||
onBrush={this.onBrush}
|
onBrush={this.onBrush}
|
||||||
zoomInfo={this.zoomInfo}
|
zoomInfo={this.zoomInfo}
|
||||||
|
|
|
@ -103,5 +103,64 @@ export default function ({ getService, getPageObjects }) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Advanced', () => {
|
||||||
|
describe('Active Nodes', () => {
|
||||||
|
const { setup, tearDown } = getLifecycleMethods(getService, getPageObjects);
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
await setup('monitoring/singlecluster-three-nodes-shard-relocation', {
|
||||||
|
from: 'Oct 5, 2017 @ 20:31:48.354',
|
||||||
|
to: 'Oct 5, 2017 @ 20:35:12.176',
|
||||||
|
});
|
||||||
|
|
||||||
|
// go to nodes listing
|
||||||
|
await overview.clickEsNodes();
|
||||||
|
expect(await nodesList.isOnListing()).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await tearDown();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await PageObjects.monitoring.clickBreadcrumb('~breadcrumbEsNodes'); // return back for next test
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show node summary of master node with 20 indices and 38 shards', async () => {
|
||||||
|
await nodesList.clickRowByResolver('jUT5KdxfRbORSCWkb5zjmA');
|
||||||
|
await nodeDetail.clickAdvanced();
|
||||||
|
|
||||||
|
expect(await nodeDetail.getSummary()).to.eql({
|
||||||
|
transportAddress: 'Transport Address\n127.0.0.1:9300',
|
||||||
|
jvmHeap: 'JVM Heap\n29%',
|
||||||
|
freeDiskSpace: 'Free Disk Space\n173.9 GB (37.42%)',
|
||||||
|
documentCount: 'Documents\n24.8k',
|
||||||
|
dataSize: 'Data\n50.4 MB',
|
||||||
|
indicesCount: 'Indices\n20',
|
||||||
|
shardsCount: 'Shards\n38',
|
||||||
|
nodeType: 'Type\nMaster Node',
|
||||||
|
status: 'Status: Online',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show node summary of data node with 4 indices and 4 shards', async () => {
|
||||||
|
await nodesList.clickRowByResolver('bwQWH-7IQY-mFPpfoaoFXQ');
|
||||||
|
await nodeDetail.clickAdvanced();
|
||||||
|
|
||||||
|
expect(await nodeDetail.getSummary()).to.eql({
|
||||||
|
transportAddress: 'Transport Address\n127.0.0.1:9302',
|
||||||
|
jvmHeap: 'JVM Heap\n17%',
|
||||||
|
freeDiskSpace: 'Free Disk Space\n173.9 GB (37.42%)',
|
||||||
|
documentCount: 'Documents\n240',
|
||||||
|
dataSize: 'Data\n1.4 MB',
|
||||||
|
indicesCount: 'Indices\n4',
|
||||||
|
shardsCount: 'Shards\n4',
|
||||||
|
nodeType: 'Type\nNode',
|
||||||
|
status: 'Status: Online',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,10 @@ export function MonitoringElasticsearchNodeDetailProvider({ getService }) {
|
||||||
const SUBJ_SUMMARY_STATUS = `${SUBJ_SUMMARY} > statusIcon`;
|
const SUBJ_SUMMARY_STATUS = `${SUBJ_SUMMARY} > statusIcon`;
|
||||||
|
|
||||||
return new (class ElasticsearchNodeDetail {
|
return new (class ElasticsearchNodeDetail {
|
||||||
|
async clickAdvanced() {
|
||||||
|
return testSubjects.click('esNodeDetailAdvancedLink');
|
||||||
|
}
|
||||||
|
|
||||||
async getSummary() {
|
async getSummary() {
|
||||||
return {
|
return {
|
||||||
transportAddress: await testSubjects.getVisibleText(SUBJ_SUMMARY_TRANSPORT_ADDRESS),
|
transportAddress: await testSubjects.getVisibleText(SUBJ_SUMMARY_TRANSPORT_ADDRESS),
|
||||||
|
|
Loading…
Reference in a new issue