This commit is contained in:
parent
d1b245f55d
commit
2e3b66a22f
15 changed files with 699 additions and 34 deletions
BIN
resources/WebContent/img/error.png
Normal file
BIN
resources/WebContent/img/error.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
BIN
resources/WebContent/img/hdd.png
Normal file
BIN
resources/WebContent/img/hdd.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
resources/WebContent/img/hdd_fail.png
Normal file
BIN
resources/WebContent/img/hdd_fail.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
BIN
resources/WebContent/img/hdd_ok.png
Normal file
BIN
resources/WebContent/img/hdd_ok.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
BIN
resources/WebContent/img/hdd_warn.png
Normal file
BIN
resources/WebContent/img/hdd_warn.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
133
src/wa/server/page/ServicePage.tmpl
Normal file
133
src/wa/server/page/ServicePage.tmpl
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
<div class="col-md-12"><div class="panel panel-default">
|
||||||
|
<div class="panel-heading">Cpu Status</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div><canvas id="cpu-chart" height="300"></canvas></div>
|
||||||
|
</div>
|
||||||
|
</div></div>
|
||||||
|
<div class="col-md-4"><div class="panel panel-default">
|
||||||
|
<div class="panel-heading">Memory</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<center><canvas id="mem-chart" height="300"></canvas></center>
|
||||||
|
<br>
|
||||||
|
<table class="table">
|
||||||
|
<tr><th></th><th>Used</th><th>Free</th></tr>
|
||||||
|
<tr><th><b>Memory</b></th>
|
||||||
|
<td id="mem-used"></td><td id="mem-free"></td></tr>
|
||||||
|
<tr><th><b>Swap</b></th>
|
||||||
|
<td id="swap-used"></td><td id="swap-free"></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div></div>
|
||||||
|
<div class="col-md-8"><div class="panel panel-default">
|
||||||
|
<div class="panel-heading">Process List</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<table id="proc-list" class="table table-hover small" data-sort-name="cpu" data-sort-order="desc">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th data-field="pid" data-sortable="true"><b>PID</b></th>
|
||||||
|
<th data-field="user" data-sortable="true">User</th>
|
||||||
|
<th data-field="cpu" data-sortable="true">CPU</th>
|
||||||
|
<th data-field="cputime" data-sortable="true">CpuTime</th>
|
||||||
|
<th data-field="mem" data-sortable="true">Memory(MB)</th>
|
||||||
|
<th data-field="cmd" data-sortable="true" style="word-wrap: break-word;">Proc</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div></div>
|
||||||
|
|
||||||
|
<script language="javascript" type="text/javascript">
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
updateCpuChart();
|
||||||
|
updateMemChart();
|
||||||
|
updateProcTable();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var cpu_chart = null;
|
||||||
|
var cpu_data = {
|
||||||
|
labels : ["","","","","","","","","","",
|
||||||
|
"","","","","","","","","","",
|
||||||
|
"","","","","","","","","","",],
|
||||||
|
datasets: []
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateCpuChart(){
|
||||||
|
$.getJSON("{{nav.url}}&json&cpu", function( data ) {
|
||||||
|
// Setup graph
|
||||||
|
if(cpu_chart == null){
|
||||||
|
// Fill in cpus
|
||||||
|
for(i=0; i<data['cpu'].length; ++i){
|
||||||
|
cpu_data['datasets'].push({
|
||||||
|
strokeColor: "rgba(151,187,205,1)",
|
||||||
|
fillColor: "rgba(151,187,205,0.2)",
|
||||||
|
data: [0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Graph
|
||||||
|
var ctx = $("#cpu-chart").get(0).getContext("2d");
|
||||||
|
cpu_chart = new Chart(ctx).Line(cpu_data, {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false, // Fixes stuped behaviour with size
|
||||||
|
datasetFill: true, pointDot: false, showTooltips: false,
|
||||||
|
scaleOverride: true, scaleStartValue: 0, scaleStepWidth: 0.1, scaleSteps: 10, scaleIntegersOnly: false,
|
||||||
|
animation : false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update graph
|
||||||
|
cpu_chart.addData(data['cpu'], "");
|
||||||
|
cpu_chart.removeData();
|
||||||
|
});
|
||||||
|
setTimeout(updateCpuChart, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var mem_chart = null;
|
||||||
|
var mem_data = [
|
||||||
|
{
|
||||||
|
value: 0,
|
||||||
|
color:"#46BFBD",
|
||||||
|
highlight: "#5AD3D1",
|
||||||
|
label: "Used"
|
||||||
|
},{
|
||||||
|
value: 1,
|
||||||
|
color: "#EEEEEE",
|
||||||
|
highlight: "#DDDDDD",
|
||||||
|
label: "Free"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function updateMemChart(){
|
||||||
|
$.getJSON("{{nav.url}}&json&memory", function( data ) {
|
||||||
|
if(mem_chart == null){
|
||||||
|
var ctx = $("#mem-chart").get(0).getContext("2d");
|
||||||
|
mem_chart = new Chart(ctx).Doughnut(mem_data, {
|
||||||
|
animateScale: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
mem_chart.segments[0].value = data.memory.used;
|
||||||
|
mem_chart.segments[1].value = data.memory.free;
|
||||||
|
mem_chart.update();
|
||||||
|
|
||||||
|
$("#mem-used").html(data.memory.used + " MB");
|
||||||
|
$("#mem-free").html(data.memory.free + " MB");
|
||||||
|
$("#swap-used").html(data.swap.used + " MB");
|
||||||
|
$("#swap-free").html(data.swap.free + " MB");
|
||||||
|
});
|
||||||
|
setTimeout(updateMemChart, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function updateProcTable(){
|
||||||
|
$.getJSON("{{nav.url}}&json&proc", function( data ) {
|
||||||
|
$('#proc-list').bootstrapTable({
|
||||||
|
data: data['proc']
|
||||||
|
});
|
||||||
|
});
|
||||||
|
setTimeout(updateProcTable, 10000);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -26,18 +26,26 @@ import wa.server.WAAbstractPage;
|
||||||
import wa.server.WAContext;
|
import wa.server.WAContext;
|
||||||
import wa.server.page.struct.WANavigation;
|
import wa.server.page.struct.WANavigation;
|
||||||
import wa.server.plugin.WAService;
|
import wa.server.plugin.WAService;
|
||||||
|
import zutil.io.file.FileUtil;
|
||||||
|
import zutil.log.LogUtil;
|
||||||
import zutil.net.http.HttpHeaderParser;
|
import zutil.net.http.HttpHeaderParser;
|
||||||
import zutil.parser.DataNode;
|
import zutil.parser.DataNode;
|
||||||
import zutil.parser.Templator;
|
import zutil.parser.Templator;
|
||||||
import zutil.plugin.PluginManager;
|
import zutil.plugin.PluginManager;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ziver on 2015-04-06.
|
* Created by Ziver on 2015-04-06.
|
||||||
*/
|
*/
|
||||||
public class ServicesPage implements WAPage {
|
public class ServicesPage implements WAPage {
|
||||||
|
private static final Logger log = LogUtil.getLogger();
|
||||||
|
private static final String TMPL_FILE = "";
|
||||||
|
|
||||||
private ArrayList<WAService> plugins;
|
private ArrayList<WAService> plugins;
|
||||||
|
|
||||||
public ServicesPage(PluginManager pluginManager){
|
public ServicesPage(PluginManager pluginManager){
|
||||||
|
|
@ -56,6 +64,18 @@ public class ServicesPage implements WAPage {
|
||||||
Map<String, Object> session,
|
Map<String, Object> session,
|
||||||
Map<String, String> cookie,
|
Map<String, String> cookie,
|
||||||
Map<String, String> request) {
|
Map<String, String> request) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
WAService obj = getPlugin(context);
|
||||||
|
|
||||||
|
if (obj != null) {
|
||||||
|
Templator tmpl = new Templator(FileUtil.find(TMPL_FILE));
|
||||||
|
tmpl.set("nav", context.getBreadcrumb().get(1));
|
||||||
|
return tmpl;
|
||||||
|
}
|
||||||
|
}catch (IOException e){
|
||||||
|
log.log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,6 +84,17 @@ public class ServicesPage implements WAPage {
|
||||||
Map<String, Object> session,
|
Map<String, Object> session,
|
||||||
Map<String, String> cookie,
|
Map<String, String> cookie,
|
||||||
Map<String, String> request){
|
Map<String, String> request){
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private WAService getPlugin(WAContext context){
|
||||||
|
if(context.getBreadcrumb().size() >= 2){
|
||||||
|
int i = plugins.indexOf(context.getBreadcrumb().get(1).getResource());
|
||||||
|
if(i >= 0)
|
||||||
|
return plugins.get(i);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
package wa.server.plugin;
|
package wa.server.plugin;
|
||||||
|
|
||||||
public interface WAService {
|
public interface WAService {
|
||||||
public enum WAServiceStatus{
|
|
||||||
RUNNING,
|
|
||||||
NOT_RESPONDING,
|
|
||||||
UNAVAILABLE,
|
|
||||||
UNKNOWN
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName();
|
public String getName();
|
||||||
public void start();
|
|
||||||
public void stop();
|
/**
|
||||||
|
* @return a service status object or null if it is not possible to check status
|
||||||
|
*/
|
||||||
public WAServiceStatus getStatus();
|
public WAServiceStatus getStatus();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a installer object that will install the service or null if the installer is not available
|
||||||
|
*/
|
||||||
|
public WAInstaller getInstaller();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
36
src/wa/server/plugin/WAServiceStatus.java
Normal file
36
src/wa/server/plugin/WAServiceStatus.java
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Ziver
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package wa.server.plugin;
|
||||||
|
|
||||||
|
public interface WAServiceStatus {
|
||||||
|
public enum ServiceStatusType{
|
||||||
|
RUNNING,
|
||||||
|
NOT_RESPONDING,
|
||||||
|
UNAVAILABLE,
|
||||||
|
UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start();
|
||||||
|
public void stop();
|
||||||
|
public ServiceStatusType getStatus();
|
||||||
|
}
|
||||||
|
|
@ -30,14 +30,15 @@ import zutil.osal.OSAbstractionLayer;
|
||||||
* Created by Ziver on 2014-11-09.
|
* Created by Ziver on 2014-11-09.
|
||||||
*/
|
*/
|
||||||
public class ApacheInstaller implements WAInstaller {
|
public class ApacheInstaller implements WAInstaller {
|
||||||
|
private static final String PACKAGES = "apache php5 php5-mcrypt php5-gd imagemagick";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void install() {
|
public void install() {
|
||||||
AptGet.install("apache php5 php5-mcrypt php5-gd imagemagick");
|
AptGet.install(PACKAGES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void uninstall() {
|
public void uninstall() {
|
||||||
AptGet.purge("apache php5 php5-mcrypt php5-gd imagemagick");
|
AptGet.purge(PACKAGES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,10 @@
|
||||||
|
|
||||||
package wa.server.plugin.apache;
|
package wa.server.plugin.apache;
|
||||||
|
|
||||||
|
import wa.server.plugin.WAInstaller;
|
||||||
import wa.server.plugin.WAService;
|
import wa.server.plugin.WAService;
|
||||||
|
import wa.server.plugin.WAServiceStatus;
|
||||||
|
import wa.server.util.AptGet;
|
||||||
import wa.server.util.Ps;
|
import wa.server.util.Ps;
|
||||||
import zutil.io.file.FileUtil;
|
import zutil.io.file.FileUtil;
|
||||||
import zutil.log.LogUtil;
|
import zutil.log.LogUtil;
|
||||||
|
|
@ -39,35 +42,25 @@ import java.util.logging.Logger;
|
||||||
public class ApacheService implements WAService {
|
public class ApacheService implements WAService {
|
||||||
private static Logger log = LogUtil.getLogger();
|
private static Logger log = LogUtil.getLogger();
|
||||||
|
|
||||||
private static OSAbstractionLayer os = OSAbstractionLayer.getInstance();
|
private ApacheStatus status;
|
||||||
private static final String PID_FILE = "/var/run/apache2.pid";
|
private ApacheInstaller installer;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Apache2";
|
return "Apache2";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start() {
|
|
||||||
os.runCommand("service apache2 start");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stop() {
|
|
||||||
os.runCommand("service apache2 stop");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WAServiceStatus getStatus() {
|
public WAServiceStatus getStatus() {
|
||||||
try {
|
if(status == null)
|
||||||
int pid = Integer.parseInt(
|
status = new ApacheStatus();
|
||||||
FileUtil.getContent(new File(PID_FILE)));
|
return status;
|
||||||
if(Ps.isRunning(pid))
|
|
||||||
return WAServiceStatus.RUNNING;
|
|
||||||
return WAServiceStatus.UNAVAILABLE;
|
|
||||||
}catch(IOException e){
|
|
||||||
log.log(Level.WARNING, null, e);
|
|
||||||
}
|
}
|
||||||
return WAServiceStatus.UNKNOWN;
|
|
||||||
|
@Override
|
||||||
|
public WAInstaller getInstaller() {
|
||||||
|
if(installer == null)
|
||||||
|
installer = new ApacheInstaller();
|
||||||
|
return installer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
64
src/wa/server/plugin/apache/ApacheStatus.java
Normal file
64
src/wa/server/plugin/apache/ApacheStatus.java
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Ziver
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package wa.server.plugin.apache;
|
||||||
|
|
||||||
|
import wa.server.plugin.WAServiceStatus;
|
||||||
|
import wa.server.util.Ps;
|
||||||
|
import zutil.io.file.FileUtil;
|
||||||
|
import zutil.log.LogUtil;
|
||||||
|
import zutil.osal.OSAbstractionLayer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class ApacheStatus implements WAServiceStatus {
|
||||||
|
private static final Logger log = LogUtil.getLogger();
|
||||||
|
private static OSAbstractionLayer os = OSAbstractionLayer.getInstance();
|
||||||
|
private static final String PID_FILE = "/var/run/apache2.pid";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
os.runCommand("service apache2 start");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
os.runCommand("service apache2 stop");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServiceStatusType getStatus() {
|
||||||
|
try {
|
||||||
|
int pid = Integer.parseInt(
|
||||||
|
FileUtil.getContent(new File(PID_FILE)));
|
||||||
|
if(Ps.isRunning(pid))
|
||||||
|
return ServiceStatusType.RUNNING;
|
||||||
|
return ServiceStatusType.UNAVAILABLE;
|
||||||
|
}catch(IOException e){
|
||||||
|
log.log(Level.WARNING, null, e);
|
||||||
|
}
|
||||||
|
return ServiceStatusType.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"name": "Apache Web Server",
|
"name": "Apache Web Server",
|
||||||
"interfaces": {
|
"interfaces": {
|
||||||
"wa.server.plugin.WAInstaller": "wa.server.plugin.apache.ApacheInstaller",
|
|
||||||
"wa.server.plugin.WAConfigurator": "wa.server.plugin.apache.ApacheConfigurator",
|
|
||||||
"wa.server.plugin.WAService": "wa.server.plugin.apache.ApacheService"
|
"wa.server.plugin.WAService": "wa.server.plugin.apache.ApacheService"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
215
src/wa/server/util/ProcDiskstats.java
Normal file
215
src/wa/server/util/ProcDiskstats.java
Normal file
|
|
@ -0,0 +1,215 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 ezivkoc
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package wa.server.util;
|
||||||
|
|
||||||
|
import zutil.log.LogUtil;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Documentation from https://www.kernel.org/doc/Documentation/block/stat.txt
|
||||||
|
*
|
||||||
|
* Created by ezivkoc on 2015-05-19.
|
||||||
|
*/
|
||||||
|
public class ProcDiskstats {
|
||||||
|
private static final Logger log = LogUtil.getLogger();
|
||||||
|
private static final String PROC_PATH = "/proc/diskstats";
|
||||||
|
private static final int TTL = 500; // update stats every 0.5 second
|
||||||
|
|
||||||
|
private static HashMap<String, HddStats> hdds = new HashMap<String, HddStats>();
|
||||||
|
private static long updateTimestamp;
|
||||||
|
|
||||||
|
|
||||||
|
private synchronized static void update(){
|
||||||
|
if(System.currentTimeMillis() - updateTimestamp < TTL)
|
||||||
|
return;
|
||||||
|
updateTimestamp = System.currentTimeMillis();
|
||||||
|
try {
|
||||||
|
BufferedReader in = new BufferedReader(new FileReader(PROC_PATH));
|
||||||
|
String line = null;
|
||||||
|
while((line=in.readLine()) != null){
|
||||||
|
String[] str = line.split("\\w*", 4);
|
||||||
|
if(str.length >= 4) {
|
||||||
|
String devName = str[2];
|
||||||
|
if(!hdds.containsKey(devName)){
|
||||||
|
HddStats hdd = new HddStats(devName);
|
||||||
|
hdds.put(hdd.getDevName(), hdd);
|
||||||
|
}
|
||||||
|
hdds.get(devName).update(str[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HddStats getStats(String devName){
|
||||||
|
update();
|
||||||
|
return hdds.get(devName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class HddStats {
|
||||||
|
private String devName;
|
||||||
|
//read I/Os requests number of read I/Os processed
|
||||||
|
private long readIO = -1;
|
||||||
|
//read merges requests number of read I/Os merged with in-queue I/O
|
||||||
|
private long readMerges = -1;
|
||||||
|
//read sectors sectors number of sectors read
|
||||||
|
private long readSectors = -1;
|
||||||
|
//read ticks milliseconds total wait time for read requests
|
||||||
|
private long readTicks = -1;
|
||||||
|
//write I/Os requests number of write I/Os processed
|
||||||
|
private long writeIO = -1;
|
||||||
|
//write merges requests number of write I/Os merged with in-queue I/O
|
||||||
|
private long writeMerges = -1;
|
||||||
|
//write sectors sectors number of sectors written
|
||||||
|
private long writeSectors = -1;
|
||||||
|
//write ticks milliseconds total wait time for write requests
|
||||||
|
private long writeTicks = -1;
|
||||||
|
//in_flight requests number of I/Os currently in flight
|
||||||
|
private long inFlight = -1;
|
||||||
|
//io_ticks milliseconds total time this block device has been active
|
||||||
|
private long ioTicks = -1;
|
||||||
|
//time_in_queue milliseconds total wait time for all requests
|
||||||
|
private long timeInQueue = -1;
|
||||||
|
|
||||||
|
protected HddStats(String devName) {
|
||||||
|
this.devName = devName;
|
||||||
|
}
|
||||||
|
protected void update(String line){
|
||||||
|
String[] stats = line.split("\\w*");
|
||||||
|
if(stats.length >= 11){
|
||||||
|
readIO = Long.parseLong(stats[0]);
|
||||||
|
readMerges = Long.parseLong(stats[1]);
|
||||||
|
readSectors = Long.parseLong(stats[2]);
|
||||||
|
readTicks = Long.parseLong(stats[3]);
|
||||||
|
writeIO = Long.parseLong(stats[4]);
|
||||||
|
writeMerges = Long.parseLong(stats[5]);
|
||||||
|
writeSectors = Long.parseLong(stats[6]);
|
||||||
|
writeTicks = Long.parseLong(stats[7]);
|
||||||
|
inFlight = Long.parseLong(stats[8]);
|
||||||
|
ioTicks = Long.parseLong(stats[9]);
|
||||||
|
timeInQueue = Long.parseLong(stats[10]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getDevName() {
|
||||||
|
return devName;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This values increment when an I/O request completes.
|
||||||
|
*/
|
||||||
|
public long getReadIO() {
|
||||||
|
return readIO;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This value increment when an I/O request is merged with an
|
||||||
|
* already-queued I/O request.
|
||||||
|
*/
|
||||||
|
public long getReadMerges() {
|
||||||
|
return readMerges;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This value count the number of sectors read from to this
|
||||||
|
* block device. The "sectors" in question are the standard UNIX 512-byte
|
||||||
|
* sectors, not any device- or filesystem-specific block size. The
|
||||||
|
* counter is incremented when the I/O completes.
|
||||||
|
*/
|
||||||
|
public long getReadSectors() {
|
||||||
|
return readSectors;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This value count the number of milliseconds that I/O requests have
|
||||||
|
* waited on this block device. If there are multiple I/O requests waiting,
|
||||||
|
* this value will increase at a rate greater than 1000/second; for
|
||||||
|
* example, if 60 read requests wait for an average of 30 ms, the read_ticks
|
||||||
|
* field will increase by 60*30 = 1800.
|
||||||
|
*/
|
||||||
|
public long getReadTicks() {
|
||||||
|
return readTicks;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This values increment when an I/O request completes.
|
||||||
|
*/
|
||||||
|
public long getWriteIO() {
|
||||||
|
return writeIO;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This value increment when an I/O request is merged with an
|
||||||
|
* already-queued I/O request.
|
||||||
|
*/
|
||||||
|
public long getWriteMerges() {
|
||||||
|
return writeMerges;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This value count the number of sectors written to this
|
||||||
|
* block device. The "sectors" in question are the standard UNIX 512-byte
|
||||||
|
* sectors, not any device- or filesystem-specific block size. The
|
||||||
|
* counter is incremented when the I/O completes.
|
||||||
|
*/
|
||||||
|
public long getWriteSectors() {
|
||||||
|
return writeSectors;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This value count the number of milliseconds that I/O requests have
|
||||||
|
* waited on this block device. If there are multiple I/O requests waiting,
|
||||||
|
* this value will increase at a rate greater than 1000/second; for
|
||||||
|
* example, if 60 write requests wait for an average of 30 ms, the write_ticks
|
||||||
|
* field will increase by 60*30 = 1800.
|
||||||
|
*/
|
||||||
|
public long getWriteTicks() {
|
||||||
|
return writeTicks;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This value counts the number of I/O requests that have been issued to
|
||||||
|
* the device driver but have not yet completed. It does not include I/O
|
||||||
|
* requests that are in the queue but not yet issued to the device driver.
|
||||||
|
*/
|
||||||
|
public long getInFlight() {
|
||||||
|
return inFlight;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This value counts the number of milliseconds during which the device has
|
||||||
|
* had I/O requests queued.
|
||||||
|
*/
|
||||||
|
public long getIoTicks() {
|
||||||
|
return ioTicks;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This value counts the number of milliseconds that I/O requests have waited
|
||||||
|
* on this block device. If there are multiple I/O requests waiting, this
|
||||||
|
* value will increase as the product of the number of milliseconds times the
|
||||||
|
* number of requests waiting (see "read ticks" above for an example).
|
||||||
|
*/
|
||||||
|
public long getTimeInQueue() {
|
||||||
|
return timeInQueue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
193
src/wa/server/util/ProcStat.java
Normal file
193
src/wa/server/util/ProcStat.java
Normal file
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 ezivkoc
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package wa.server.util;
|
||||||
|
|
||||||
|
import zutil.log.LogUtil;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Documentation from https://www.kernel.org/doc/Documentation/block/stat.txt
|
||||||
|
*
|
||||||
|
* Created by ezivkoc on 2015-05-19.
|
||||||
|
*/
|
||||||
|
public class ProcStat {
|
||||||
|
private static final Logger log = LogUtil.getLogger();
|
||||||
|
private static final String PROC_PATH = "/proc/stat";
|
||||||
|
private static final int TTL = 500; // update stats every 0.5 second
|
||||||
|
|
||||||
|
private static CpuStats cpuTotal = new CpuStats();
|
||||||
|
private static ArrayList<CpuStats> cpus = new ArrayList<CpuStats>();
|
||||||
|
private static long uptime;
|
||||||
|
private static long processes;
|
||||||
|
private static long updateTimestamp;
|
||||||
|
|
||||||
|
|
||||||
|
private synchronized static void update(){
|
||||||
|
if(System.currentTimeMillis() - updateTimestamp < TTL)
|
||||||
|
return;
|
||||||
|
updateTimestamp = System.currentTimeMillis();
|
||||||
|
try {
|
||||||
|
BufferedReader in = new BufferedReader(new FileReader(PROC_PATH));
|
||||||
|
String line = null;
|
||||||
|
while((line=in.readLine()) != null){
|
||||||
|
String[] str = line.split("\\w*");
|
||||||
|
if(str[0].equals("cpu"))
|
||||||
|
cpuTotal.update(str);
|
||||||
|
else if(str[0].startsWith("cpu")){
|
||||||
|
int cpuId = Integer.parseInt(str[0].substring(3));
|
||||||
|
if(cpus.size() < cpuId)
|
||||||
|
cpus.add(new CpuStats());
|
||||||
|
cpus.get(cpuId).update(str);
|
||||||
|
}
|
||||||
|
else if(str[0].startsWith("btime")){
|
||||||
|
uptime = Long.parseLong(str[1]);
|
||||||
|
}
|
||||||
|
else if(str[0].startsWith("processes")){
|
||||||
|
processes = Long.parseLong(str[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CpuStats getTotalCpuStats(){
|
||||||
|
update();
|
||||||
|
return cpuTotal;
|
||||||
|
}
|
||||||
|
public static Iterator<CpuStats> getCpuStats(){
|
||||||
|
update();
|
||||||
|
return cpus.iterator();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return the time at which the system booted, in seconds since the Unix epoch.
|
||||||
|
*/
|
||||||
|
public static long getUptime(){
|
||||||
|
update();
|
||||||
|
return uptime;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return the number of processes and threads created, which includes (but is not limited to) those created by calls to the fork() and clone() system calls.
|
||||||
|
*/
|
||||||
|
public static long getProcesses(){
|
||||||
|
update();
|
||||||
|
return processes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static class CpuStats {
|
||||||
|
// normal processes executing in user mode
|
||||||
|
private long user;
|
||||||
|
// processes executing in kernel mode
|
||||||
|
private long system;
|
||||||
|
// twiddling thumbs
|
||||||
|
private long idle;
|
||||||
|
// waiting for I/O to complete
|
||||||
|
private long iowait;
|
||||||
|
private long steal;
|
||||||
|
// virtual processes
|
||||||
|
private long guest;
|
||||||
|
private long total;
|
||||||
|
|
||||||
|
// Percentage
|
||||||
|
private float load_total;
|
||||||
|
private float load_user;
|
||||||
|
private float load_system;
|
||||||
|
private float load_iowait;
|
||||||
|
private float load_virtual;
|
||||||
|
|
||||||
|
protected CpuStats(){}
|
||||||
|
protected void update(String[] stats){
|
||||||
|
long newUser=0, newNice=0, newSystem=0, newIdle=0, newIowait=0, newIrq=0, newSoftirq=0, newSteal=0, newGuest=0, newGuestNice=0;
|
||||||
|
if(stats.length >= 1+8){
|
||||||
|
newUser = Long.parseLong(stats[1]);
|
||||||
|
newNice = Long.parseLong(stats[2]);
|
||||||
|
newSystem = Long.parseLong(stats[3]);
|
||||||
|
newIdle = Long.parseLong(stats[4]);
|
||||||
|
newIowait = Long.parseLong(stats[5]);
|
||||||
|
newIrq = Long.parseLong(stats[6]);
|
||||||
|
newSoftirq = Long.parseLong(stats[7]);
|
||||||
|
if(stats.length >= 1+8+3){
|
||||||
|
newSteal = Long.parseLong(stats[8]);
|
||||||
|
newGuest = Long.parseLong(stats[9]);
|
||||||
|
newGuestNice = Long.parseLong(stats[10]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Summarize
|
||||||
|
newUser = newUser + newNice - newGuest - newGuestNice;
|
||||||
|
newSystem = newSystem + newIrq + newSoftirq;
|
||||||
|
newGuest = newGuest + newGuestNice;
|
||||||
|
|
||||||
|
// Calculate the diffs
|
||||||
|
long userDiff = newUser - user;
|
||||||
|
long idleDiff = (newIdle + newIowait) - (idle + iowait);
|
||||||
|
long systemDiff = newSystem - system;
|
||||||
|
long stealDiff = newSteal - steal;
|
||||||
|
long virtualDiff = newGuest - guest;
|
||||||
|
long newTotal = userDiff + systemDiff + idleDiff + stealDiff + virtualDiff;
|
||||||
|
// Calculate load
|
||||||
|
load_total = (float)(newTotal-idleDiff)/newTotal;
|
||||||
|
load_user = (float)userDiff/newTotal;
|
||||||
|
load_system = (float)systemDiff/newTotal;
|
||||||
|
load_iowait = (float)(newIowait - iowait)/newTotal;
|
||||||
|
load_virtual = (float)virtualDiff/newTotal;
|
||||||
|
|
||||||
|
// update old values
|
||||||
|
user = newUser;
|
||||||
|
system = newSystem;
|
||||||
|
idle = newIdle;
|
||||||
|
iowait = newIowait;
|
||||||
|
steal = newSteal;
|
||||||
|
guest = newGuest;
|
||||||
|
total = newTotal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getTotalLoad() {
|
||||||
|
return load_total;
|
||||||
|
}
|
||||||
|
public float getUserLoad() {
|
||||||
|
return load_user;
|
||||||
|
}
|
||||||
|
public float getSystemLoad() {
|
||||||
|
return load_system;
|
||||||
|
}
|
||||||
|
public float getIOWaitLoad() {
|
||||||
|
return load_iowait;
|
||||||
|
}
|
||||||
|
public float getVirtualLoad() {
|
||||||
|
return load_virtual;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue