webapp.src.components.WorkerStatus.jsx Maven / Gradle / Ivy
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from "react";
import {
addToHistory,
formatCount,
formatDataSize,
getFirstParameter,
precisionRound
} from "../utils";
const SMALL_SPARKLINE_PROPERTIES = {
width: '100%',
height: '57px',
fillColor: '#3F4552',
lineColor: '#747F96',
spotColor: '#1EDCFF',
tooltipClassname: 'sparkline-tooltip',
disableHiddenCheck: true,
};
export class WorkerStatus extends React.Component {
constructor(props) {
super(props);
this.state = {
serverInfo: null,
initialized: false,
ended: false,
processCpuLoad: [],
systemCpuLoad: [],
heapPercentUsed: [],
nonHeapUsed: [],
};
this.refreshLoop = this.refreshLoop.bind(this);
}
resetTimer() {
clearTimeout(this.timeoutId);
// stop refreshing when query finishes or fails
if (this.state.query === null || !this.state.ended) {
this.timeoutId = setTimeout(this.refreshLoop, 1000);
}
}
refreshLoop() {
clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously
const nodeId = getFirstParameter(window.location.search);
$.get('/ui/api/worker/' + nodeId + '/status', function (serverInfo) {
this.setState({
serverInfo: serverInfo,
initialized: true,
processCpuLoad: addToHistory(serverInfo.processCpuLoad * 100.0, this.state.processCpuLoad),
systemCpuLoad: addToHistory(serverInfo.systemCpuLoad * 100.0, this.state.systemCpuLoad),
heapPercentUsed: addToHistory(serverInfo.heapUsed * 100.0 / serverInfo.heapAvailable, this.state.heapPercentUsed),
nonHeapUsed: addToHistory(serverInfo.nonHeapUsed, this.state.nonHeapUsed),
});
this.resetTimer();
}.bind(this))
.fail(function () {
this.setState({
initialized: true,
});
this.resetTimer();
}.bind(this));
}
componentDidMount() {
this.refreshLoop();
}
componentDidUpdate() {
$('#process-cpu-load-sparkline').sparkline(this.state.processCpuLoad, $.extend({}, SMALL_SPARKLINE_PROPERTIES, {chartRangeMin: 0, numberFormatter: precisionRound}));
$('#system-cpu-load-sparkline').sparkline(this.state.systemCpuLoad, $.extend({}, SMALL_SPARKLINE_PROPERTIES, {chartRangeMin: 0, numberFormatter: precisionRound}));
$('#heap-percent-used-sparkline').sparkline(this.state.heapPercentUsed, $.extend({}, SMALL_SPARKLINE_PROPERTIES, {chartRangeMin: 0, numberFormatter: precisionRound}));
$('#nonheap-used-sparkline').sparkline(this.state.nonHeapUsed, $.extend({}, SMALL_SPARKLINE_PROPERTIES, {chartRangeMin: 0, numberFormatter: formatDataSize}));
$('[data-toggle="tooltip"]').tooltip();
new window.ClipboardJS('.copy-button');
}
static renderPoolBar(name, pool) {
if (!pool) {
return;
}
const size = pool.maxBytes;
const reserved = pool.reservedBytes;
const revocable = pool.reservedRevocableBytes;
const percentageReservedNonRevocable = reserved === 0 ? 0 : Math.max(Math.round(reserved * 100.0 / size), 15);
const percentageRevocable = revocable === 0 ? 0 : Math.max(Math.round(revocable * 100.0 / size), 15);
const percentageFree = 100 - (percentageRevocable + percentageReservedNonRevocable);
return (
{name} Pool
{formatDataSize(size)} total
{formatDataSize(reserved)}
{formatDataSize(revocable)}
{formatDataSize(size - reserved - revocable)}
)
}
static renderPoolQuery(query, reserved, revocable, total) {
return (
{Math.round(reserved * 100.0 / total)}%
{formatDataSize(reserved)}
)
}
renderPoolQueries(pool) {
if (!pool) {
return;
}
const queries = {};
const reservations = pool.queryMemoryReservations;
const revocableReservations = pool.queryMemoryRevocableReservations;
for (let query in reservations) {
queries[query] = [reservations[query], 0]
}
for (let query in revocableReservations) {
if (queries.hasOwnProperty(query)) {
queries[query][1] = revocableReservations[query]
}
else {
queries[query] = [0, revocableReservations[query]]
}
}
const size = pool.maxBytes;
if (Object.keys(queries).length === 0) {
return (
No queries using pool
);
}
return (
{Object.keys(queries).map(key => WorkerStatus.renderPoolQuery(key, queries[key][0], queries[key][1], size))}
)
}
render() {
const serverInfo = this.state.serverInfo;
if (serverInfo === null) {
if (this.state.initialized === false) {
return (
Loading...
);
}
else {
return (
Node information could not be loaded
);
}
}
return (
Overview
Resource Utilization
Process CPU Utilization
Loading ...
{formatCount(this.state.processCpuLoad[this.state.processCpuLoad.length - 1])}%
System CPU Utilization
Loading ...
{formatCount(this.state.systemCpuLoad[this.state.systemCpuLoad.length - 1])}%
Heap Utilization
Loading ...
{formatCount(this.state.heapPercentUsed[this.state.heapPercentUsed.length - 1])}%
Non-Heap Memory Used
Loading ...
{formatDataSize(this.state.nonHeapUsed[this.state.nonHeapUsed.length - 1])}
Memory
{WorkerStatus.renderPoolBar("Memory Usage", serverInfo.memoryInfo.pool)}
{this.renderPoolQueries(serverInfo.memoryInfo.pool)}
);
}
}