mirror of https://github.com/tp4a/teleport
dashboard的CPU负载和内存用量展示可用了。
parent
145e3a0d5c
commit
5b8f882f61
|
@ -1,7 +1,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
$app.on_init = function (cb_stack) {
|
$app.on_init = function (cb_stack) {
|
||||||
$app.MAX_OVERLOAD_DATA = 20;
|
$app.MAX_OVERLOAD_DATA = 10 * 60 / 5;
|
||||||
$app.dom = {
|
$app.dom = {
|
||||||
count_user: $('#count-user')
|
count_user: $('#count-user')
|
||||||
, count_host: $('#count-host')
|
, count_host: $('#count-host')
|
||||||
|
@ -12,7 +12,7 @@ $app.on_init = function (cb_stack) {
|
||||||
// refresh basic info every 1m.
|
// refresh basic info every 1m.
|
||||||
$app.load_basic_info();
|
$app.load_basic_info();
|
||||||
// refresh overload info every 5m.
|
// refresh overload info every 5m.
|
||||||
$app.load_overload_info();
|
//$app.load_overload_info();
|
||||||
|
|
||||||
$app.ws = null;
|
$app.ws = null;
|
||||||
$app.init_ws();
|
$app.init_ws();
|
||||||
|
@ -42,50 +42,40 @@ $app.load_basic_info = function () {
|
||||||
setTimeout($app.load_basic_info, 60 * 1000);
|
setTimeout($app.load_basic_info, 60 * 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.load_overload_info = function () {
|
$app.init_sys_status_info = function (data) {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
// var bar_x = [];
|
// var t = (Math.floor(Date.now() / 1000) - $app.MAX_OVERLOAD_DATA - 1) * 1000;
|
||||||
// for (i = 0; i < $app.MAX_OVERLOAD_DATA; i++) {
|
console.log(data);
|
||||||
// bar_x.push(i);
|
|
||||||
// }
|
|
||||||
|
|
||||||
var now = Math.floor(Date.now() / 1000);
|
//=====================================
|
||||||
console.log('now', now);
|
// CPU
|
||||||
|
//=====================================
|
||||||
|
|
||||||
$app.bar_cpu_user = [];
|
$app.bar_cpu_user = [];
|
||||||
$app.bar_cpu_sys = [];
|
$app.bar_cpu_sys = [];
|
||||||
var t = tp_local2utc(now - $app.MAX_OVERLOAD_DATA - 1);
|
for (i = 0; i < data.length; i++) {
|
||||||
console.log(t);
|
// var x = t + i * 1000;
|
||||||
for (i = 0; i < $app.MAX_OVERLOAD_DATA; i++) {
|
$app.bar_cpu_user.push({name: tp_format_datetime(tp_utc2local(data[i].t), 'HH:mm:ss'), value: [tp_utc2local(data[i].t)*1000, data[i].c.u]});
|
||||||
var x = t + i;
|
$app.bar_cpu_sys.push({name: tp_format_datetime(tp_utc2local(data[i].t), 'HH:mm:ss'), value: [tp_utc2local(data[i].t)*1000, data[i].c.s]});
|
||||||
console.log(x, t);
|
|
||||||
$app.bar_cpu_user.push([
|
|
||||||
{
|
|
||||||
name: x.toString()
|
|
||||||
, value: [tp_format_datetime(tp_utc2local(x)), 0]
|
|
||||||
}
|
}
|
||||||
]);
|
|
||||||
$app.bar_cpu_sys.push([
|
var clr_user = '#e2524c';
|
||||||
{
|
var clr_user_area = '#f7827a';
|
||||||
name: x.toString()
|
var clr_sys = '#558c5a';
|
||||||
, value: [tp_format_datetime(tp_utc2local(x)), 0]
|
var clr_sys_area = '#3dc34a';
|
||||||
}
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
//console.log('--', $app.bar_cpu_data);
|
|
||||||
|
|
||||||
$app.bar_cpu = echarts.init(document.getElementById('bar-cpu'));
|
$app.bar_cpu = echarts.init(document.getElementById('bar-cpu'));
|
||||||
$app.bar_cpu.setOption({
|
$app.bar_cpu.setOption({
|
||||||
title: {
|
title: {
|
||||||
// show: false
|
// show: false
|
||||||
text: 'CPU负载'
|
text: 'CPU负载',
|
||||||
, top: 0
|
top: 0,
|
||||||
, left: 50
|
textStyle: {
|
||||||
, textStyle: {
|
color: 'rgba(0,0,0,0.5)',
|
||||||
color: 'rgba(0,0,0,0.5)'
|
fontSize: 14
|
||||||
, fontSize: 14
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
color: [clr_sys, clr_user],
|
||||||
grid: {
|
grid: {
|
||||||
show: true
|
show: true
|
||||||
, left: 30
|
, left: 30
|
||||||
|
@ -94,54 +84,151 @@ $app.load_overload_info = function () {
|
||||||
, bottom: 20
|
, bottom: 20
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis'
|
trigger: 'axis',
|
||||||
, formatter: function (params) {
|
formatter: function (params) {
|
||||||
console.log(params);
|
return params[0].name + '<br/>'+ params[1].seriesName + ': ' + params[1].value[1] + '%<br/>' + params[0].seriesName + ': ' + params[0].value[1] + '%';
|
||||||
//params = params[0];
|
},
|
||||||
var t = parseInt(params[0].name);
|
axisPointer: {
|
||||||
return tp_format_datetime(tp_utc2local(t), 'HH:mm:ss') + '<br/>' + params[0].value[1] + '%, ' + params[1].value[1] + '%';
|
|
||||||
}
|
|
||||||
, axisPointer: {
|
|
||||||
animation: false
|
animation: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// legend: {
|
legend: {
|
||||||
// // show: false
|
right: 20,
|
||||||
// },
|
data: [
|
||||||
xAxis: {
|
{name: '系统', icon: 'rect'},
|
||||||
type: 'time'
|
{name: '用户', icon: 'rect'}
|
||||||
, boundaryGap: false
|
]
|
||||||
, axisLine: {show: false}
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'time',
|
||||||
|
boundaryGap: false,
|
||||||
|
splitNumber: 10,
|
||||||
|
axisLine: {show: false}
|
||||||
},
|
},
|
||||||
// yAxis: {type: 'value', min: 'dataMin', axisLine: {show: false}, splitLine: {show: false}},
|
|
||||||
yAxis: {
|
yAxis: {
|
||||||
type: 'value'
|
type: 'value',
|
||||||
, axisLine: {
|
axisLine: {show: false},
|
||||||
show: false
|
min: 0,
|
||||||
}
|
max: 100,
|
||||||
, min: 0
|
containLabel: true
|
||||||
, max: 100
|
|
||||||
, boundaryGap: [0, '50%']
|
|
||||||
|
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: 'cpu-sys'
|
name: '系统',
|
||||||
, type: 'line'
|
type: 'line', smooth: true, symbol: 'none', stack: 'a', showSymbol: false,
|
||||||
, smooth: true
|
lineStyle: {
|
||||||
, symbol: 'none'
|
normal: {
|
||||||
, stack: 'a'
|
width: 1
|
||||||
, showSymbol: false
|
|
||||||
, data: $app.bar_cpu_sys
|
|
||||||
}
|
}
|
||||||
, {
|
},
|
||||||
name: 'cpu-user'
|
areaStyle: {
|
||||||
, type: 'line'
|
normal: {
|
||||||
, smooth: true
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||||||
, symbol: 'none'
|
offset: 0,
|
||||||
, stack: 'a'
|
color: clr_sys
|
||||||
, showSymbol: false
|
}, {
|
||||||
, data: $app.bar_cpu_user
|
offset: 1,
|
||||||
|
color: clr_sys_area
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: $app.bar_cpu_sys
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '用户', type: 'line', smooth: true, symbol: 'none', stack: 'a', showSymbol: false,
|
||||||
|
lineStyle: {
|
||||||
|
normal: {width: 1}
|
||||||
|
},
|
||||||
|
areaStyle: {
|
||||||
|
normal: {
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||||||
|
offset: 0,
|
||||||
|
color: clr_user
|
||||||
|
}, {
|
||||||
|
offset: 1,
|
||||||
|
color: clr_user_area
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: $app.bar_cpu_user
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
//=====================================
|
||||||
|
// Memory
|
||||||
|
//=====================================
|
||||||
|
|
||||||
|
$app.bar_mem_used = [];
|
||||||
|
for (i = 0; i < data.length; i++) {
|
||||||
|
$app.bar_mem_used.push({name: tp_format_datetime(tp_utc2local(data[i].t), 'HH:mm:ss'), value: [tp_utc2local(data[i].t)*1000, tp_digital_precision(data[i].m.u * 100 / data[i].m.t, 1)]});
|
||||||
|
}
|
||||||
|
|
||||||
|
var clr_mem = '#5671e2';
|
||||||
|
var clr_mem_area = '#8da4f9';
|
||||||
|
|
||||||
|
$app.bar_mem = echarts.init(document.getElementById('bar-mem'));
|
||||||
|
$app.bar_mem.setOption({
|
||||||
|
title: {
|
||||||
|
text: '内存用量',
|
||||||
|
top: 0,
|
||||||
|
textStyle: {
|
||||||
|
color: 'rgba(0,0,0,0.5)',
|
||||||
|
fontSize: 14
|
||||||
|
}
|
||||||
|
},
|
||||||
|
color: [clr_mem],
|
||||||
|
grid: {
|
||||||
|
show: true
|
||||||
|
, left: 30
|
||||||
|
, right: 20
|
||||||
|
, top: 30
|
||||||
|
, bottom: 20
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
formatter: function (params) {
|
||||||
|
return params[0].name + ': '+ params[0].value[1] + '%';
|
||||||
|
},
|
||||||
|
axisPointer: {
|
||||||
|
animation: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'time',
|
||||||
|
boundaryGap: false,
|
||||||
|
splitNumber: 10,
|
||||||
|
axisLine: {show: false}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
axisLine: {show: false},
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
//name: '系统',
|
||||||
|
type: 'line', smooth: true, symbol: 'none', stack: 'a', showSymbol: false,
|
||||||
|
lineStyle: {
|
||||||
|
normal: {
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
areaStyle: {
|
||||||
|
normal: {
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||||||
|
offset: 0,
|
||||||
|
color: clr_mem
|
||||||
|
}, {
|
||||||
|
offset: 1,
|
||||||
|
color: clr_mem_area
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: $app.bar_mem_used
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@ -155,8 +242,9 @@ $app.init_ws = function () {
|
||||||
$app.ws = new WebSocket('ws://' + location.host + '/ws/' + _sid);
|
$app.ws = new WebSocket('ws://' + location.host + '/ws/' + _sid);
|
||||||
|
|
||||||
$app.ws.onopen = function (e) {
|
$app.ws.onopen = function (e) {
|
||||||
|
$app.ws.send('{"method": "request", "param": "sys_status"}');
|
||||||
// 订阅:
|
// 订阅:
|
||||||
$app.ws.send('{"method": "subscribe", "params": ["sys_real_status"]}');
|
// $app.ws.send('{"method": "subscribe", "params": ["sys_status"]}');
|
||||||
};
|
};
|
||||||
$app.ws.onclose = function (e) {
|
$app.ws.onclose = function (e) {
|
||||||
// console.log('[ws] ws-on-close', e);
|
// console.log('[ws] ws-on-close', e);
|
||||||
|
@ -164,36 +252,28 @@ $app.init_ws = function () {
|
||||||
};
|
};
|
||||||
$app.ws.onmessage = function (e) {
|
$app.ws.onmessage = function (e) {
|
||||||
var t = JSON.parse(e.data);
|
var t = JSON.parse(e.data);
|
||||||
// console.log('[ws] ws-on-message', t);
|
// console.log(t);
|
||||||
|
|
||||||
if (t.subscribe === 'sys_real_status') {
|
if (t.method === 'request' && t.param === 'sys_status') {
|
||||||
|
$app.init_sys_status_info(t.data);
|
||||||
|
// 订阅系统状态信息
|
||||||
|
$app.ws.send('{"method": "subscribe", "params": ["sys_status"]}');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.method === 'subscribe' && t.param === 'sys_status') {
|
||||||
$app.bar_cpu_user.shift();
|
$app.bar_cpu_user.shift();
|
||||||
$app.bar_cpu_user.push({
|
$app.bar_cpu_user.push({name: tp_format_datetime(tp_utc2local(t.data.t), 'HH:mm:ss'), value: [tp_utc2local(t.data.t) * 1000, t.data.c.u]});
|
||||||
'name': t.data.t.toString(),
|
|
||||||
'value': [tp_format_datetime(tp_utc2local(t.data.t)), t.data.c.u]
|
|
||||||
});
|
|
||||||
$app.bar_cpu_sys.shift();
|
$app.bar_cpu_sys.shift();
|
||||||
$app.bar_cpu_sys.push({
|
$app.bar_cpu_sys.push({name: tp_format_datetime(tp_utc2local(t.data.t), 'HH:mm:ss'), value: [tp_utc2local(t.data.t) * 1000, t.data.c.s]});
|
||||||
'name': t.data.t.toString(),
|
|
||||||
'value': [tp_format_datetime(tp_utc2local(t.data.t)), t.data.c.s]
|
|
||||||
});
|
|
||||||
//console.log($app.bar_cpu_data);
|
|
||||||
console.log('--', t.data.t);
|
|
||||||
|
|
||||||
$app.bar_cpu.setOption(
|
$app.bar_cpu.setOption(
|
||||||
{
|
{series: [{data: $app.bar_cpu_sys}, {data: $app.bar_cpu_user}]}
|
||||||
// xAxis: {data: 1},
|
);
|
||||||
series: [
|
|
||||||
{
|
$app.bar_mem_used.shift();
|
||||||
name: 'cpu-user'
|
$app.bar_mem_used.push({name: tp_format_datetime(tp_utc2local(t.data.t), 'HH:mm:ss'), value: [tp_utc2local(t.data.t) * 1000, Math.round(t.data.m.u / t.data.m.t * 100, 2)]});
|
||||||
, data: $app.bar_cpu_user
|
$app.bar_mem.setOption(
|
||||||
}
|
{series: [{data: $app.bar_mem_used}]}
|
||||||
, {
|
|
||||||
name: 'cpu-sys'
|
|
||||||
, data: $app.bar_cpu_sys
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,13 +54,13 @@ function tp_check_ip(ip) {
|
||||||
// useful functions.
|
// useful functions.
|
||||||
//===================================================
|
//===================================================
|
||||||
|
|
||||||
function digital_precision(num, keep) {
|
function tp_digital_precision(num, keep) {
|
||||||
return Math.round(num * Math.pow(10, keep)) / Math.pow(10, keep);
|
return Math.round(num * Math.pow(10, keep)) / Math.pow(10, keep);
|
||||||
}
|
}
|
||||||
|
|
||||||
function prefixInteger(num, length) {
|
// function prefixInteger(num, length) {
|
||||||
return (num / Math.pow(10, length)).toFixed(length).substr(2);
|
// return (num / Math.pow(10, length)).toFixed(length).substr(2);
|
||||||
}
|
// }
|
||||||
|
|
||||||
function tp_size2str(size, precision) {
|
function tp_size2str(size, precision) {
|
||||||
precision = precision || 0;
|
precision = precision || 0;
|
||||||
|
@ -71,23 +71,23 @@ function tp_size2str(size, precision) {
|
||||||
k = 'B';
|
k = 'B';
|
||||||
}
|
}
|
||||||
else if (size < MB) {
|
else if (size < MB) {
|
||||||
s = digital_precision(size / KB, precision);
|
s = tp_digital_precision(size / KB, precision);
|
||||||
k = 'KB'
|
k = 'KB'
|
||||||
}
|
}
|
||||||
else if (size < GB) {
|
else if (size < GB) {
|
||||||
s = digital_precision(size / MB, precision);
|
s = tp_digital_precision(size / MB, precision);
|
||||||
k = 'MB'
|
k = 'MB'
|
||||||
}
|
}
|
||||||
else if (size < TB) {
|
else if (size < TB) {
|
||||||
s = digital_precision(size / GB, precision);
|
s = tp_digital_precision(size / GB, precision);
|
||||||
k = 'GB'
|
k = 'GB'
|
||||||
}
|
}
|
||||||
else if (size < PB) {
|
else if (size < PB) {
|
||||||
s = digital_precision(size / TB, precision);
|
s = tp_digital_precision(size / TB, precision);
|
||||||
k = 'TB'
|
k = 'TB'
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
s = digital_precision(size / PB, precision);
|
s = tp_digital_precision(size / PB, precision);
|
||||||
k = 'PB'
|
k = 'PB'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,15 +70,13 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="stats stats-bar">
|
<div class="stats stats-bar">
|
||||||
## <div class="stats-name">CPU负载</div>
|
<div class="stats-value" id="bar-cpu" style="height:180px;">
|
||||||
<div class="stats-value" id="bar-cpu" style="height:260px;">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="stats stats-bar">
|
<div class="stats stats-bar">
|
||||||
<div class="stats-name">内存使用</div>
|
<div class="stats-value" id="bar-mem" style="height:180px;">
|
||||||
<div class="stats-value">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,12 +7,15 @@ from app.base.logger import log
|
||||||
from app.base.configs import tp_cfg
|
from app.base.configs import tp_cfg
|
||||||
|
|
||||||
|
|
||||||
class SessionManager(threading.Thread):
|
# class SessionManager(threading.Thread):
|
||||||
|
class SessionManager(object):
|
||||||
|
|
||||||
# SESSION_EXPIRE = 3600 # 60*60 默认超时时间为1小时
|
# SESSION_EXPIRE = 3600 # 60*60 默认超时时间为1小时
|
||||||
_expire = 3600
|
_expire = 3600
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(name='session-manager-thread')
|
# super().__init__(name='session-manager-thread')
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
import builtins
|
import builtins
|
||||||
if '__session_manager__' in builtins.__dict__:
|
if '__session_manager__' in builtins.__dict__:
|
||||||
|
@ -26,31 +29,40 @@ class SessionManager(threading.Thread):
|
||||||
self._stop_flag = False
|
self._stop_flag = False
|
||||||
self._timer_cond = threading.Condition()
|
self._timer_cond = threading.Condition()
|
||||||
|
|
||||||
self.update_default_expire()
|
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
|
self.update_default_expire()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_default_expire(self):
|
def update_default_expire(self):
|
||||||
self._expire = tp_cfg().sys.login.session_timeout * 60
|
self._expire = tp_cfg().sys.login.session_timeout * 60
|
||||||
|
|
||||||
def stop(self):
|
# def stop(self):
|
||||||
self._stop_flag = True
|
# self._stop_flag = True
|
||||||
self._timer_cond.acquire()
|
# self._timer_cond.acquire()
|
||||||
self._timer_cond.notify()
|
# self._timer_cond.notify()
|
||||||
self._timer_cond.release()
|
# self._timer_cond.release()
|
||||||
self.join()
|
# self.join()
|
||||||
log.v('{} stopped.\n'.format(self.name))
|
# log.v('{} stopped.\n'.format(self.name))
|
||||||
|
|
||||||
def run(self):
|
# def run(self):
|
||||||
while True:
|
# while True:
|
||||||
self._timer_cond.acquire()
|
# self._timer_cond.acquire()
|
||||||
# 每隔一分钟醒来检查一次超时的会话
|
# # 每隔一分钟醒来检查一次超时的会话
|
||||||
self._timer_cond.wait(60)
|
# self._timer_cond.wait(60)
|
||||||
self._timer_cond.release()
|
# self._timer_cond.release()
|
||||||
if self._stop_flag:
|
# if self._stop_flag:
|
||||||
break
|
# break
|
||||||
|
#
|
||||||
|
# _now = int(datetime.datetime.utcnow().timestamp())
|
||||||
|
# with self._lock:
|
||||||
|
# _keys = [k for k in self._session_dict]
|
||||||
|
# for k in _keys:
|
||||||
|
# if self._session_dict[k]['e'] == 0:
|
||||||
|
# continue
|
||||||
|
# if _now - self._session_dict[k]['t'] > self._session_dict[k]['e']:
|
||||||
|
# del self._session_dict[k]
|
||||||
|
|
||||||
|
def check_expire(self):
|
||||||
_now = int(datetime.datetime.utcnow().timestamp())
|
_now = int(datetime.datetime.utcnow().timestamp())
|
||||||
with self._lock:
|
with self._lock:
|
||||||
_keys = [k for k in self._session_dict]
|
_keys = [k for k in self._session_dict]
|
||||||
|
|
|
@ -8,24 +8,22 @@ import json
|
||||||
|
|
||||||
from app.base.logger import log
|
from app.base.logger import log
|
||||||
from app.base.utils import tp_timestamp_utc_now
|
from app.base.utils import tp_timestamp_utc_now
|
||||||
from app.base.configs import tp_cfg
|
|
||||||
from app.controller.ws import tp_wss
|
from app.controller.ws import tp_wss
|
||||||
|
from app.base.cron import tp_corn
|
||||||
|
|
||||||
|
|
||||||
class TPSysStatus(threading.Thread):
|
class TPSysStatus(object):
|
||||||
|
_INTERVAL = 5 # seconds
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(name='sys-status-thread')
|
super().__init__()
|
||||||
|
|
||||||
import builtins
|
import builtins
|
||||||
if '__tp_sys_status__' in builtins.__dict__:
|
if '__tp_sys_status__' in builtins.__dict__:
|
||||||
raise RuntimeError('TPSysStatus object exists, you can not create more than one instance.')
|
raise RuntimeError('TPSysStatus object exists, you can not create more than one instance.')
|
||||||
|
|
||||||
# session表,session_id为索引,每个项为一个字典,包括 v(value), t(last access), e(expire seconds)
|
# 实时数据我们在内存中保留最近10分钟的数据,每5秒收集一次,共 10*60/5 = 120 条记录
|
||||||
self._session_dict = dict()
|
self._history = list()
|
||||||
|
|
||||||
self._stop_flag = False
|
|
||||||
self._time_cnt = 0
|
|
||||||
self._interval = 2
|
|
||||||
|
|
||||||
self._disk_read = 0
|
self._disk_read = 0
|
||||||
self._disk_write = 0
|
self._disk_write = 0
|
||||||
|
@ -33,6 +31,19 @@ class TPSysStatus(threading.Thread):
|
||||||
self._net_sent = 0
|
self._net_sent = 0
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
|
t = tp_timestamp_utc_now() - 10 * 60
|
||||||
|
cnt = int((10 * 60 + self._INTERVAL - 1) / self._INTERVAL)
|
||||||
|
for i in range(cnt):
|
||||||
|
val = {
|
||||||
|
't': t,
|
||||||
|
'c': {'u': 0, 's': 0},
|
||||||
|
'm': {'u': 1, 't': 100},
|
||||||
|
'd': {'r': 0, 'w': 0},
|
||||||
|
'n': {'r': 0, 's': 0}
|
||||||
|
}
|
||||||
|
self._history.append(val)
|
||||||
|
t += self._INTERVAL
|
||||||
|
|
||||||
psutil.cpu_times_percent()
|
psutil.cpu_times_percent()
|
||||||
net = psutil.net_io_counters(pernic=False)
|
net = psutil.net_io_counters(pernic=False)
|
||||||
self._net_recv = net.bytes_recv
|
self._net_recv = net.bytes_recv
|
||||||
|
@ -41,25 +52,12 @@ class TPSysStatus(threading.Thread):
|
||||||
self._disk_read = disk.read_bytes
|
self._disk_read = disk.read_bytes
|
||||||
self._disk_write = disk.write_bytes
|
self._disk_write = disk.write_bytes
|
||||||
|
|
||||||
|
tp_corn().add_job('sys_status', self._check_status, first_interval_seconds=self._INTERVAL, interval_seconds=self._INTERVAL)
|
||||||
|
tp_wss().register_get_sys_status_callback(self.get_status)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def stop(self):
|
def _check_status(self):
|
||||||
self._stop_flag = True
|
# time.sleep(self._interval)
|
||||||
self.join()
|
|
||||||
log.v('{} stopped.\n'.format(self.name))
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
while not self._stop_flag:
|
|
||||||
# time.sleep(1)
|
|
||||||
# if self._stop_flag:
|
|
||||||
# break
|
|
||||||
# self._time_cnt += 1
|
|
||||||
# if self._time_cnt < 5:
|
|
||||||
# continue
|
|
||||||
#
|
|
||||||
# self._time_cnt = 0
|
|
||||||
|
|
||||||
time.sleep(self._interval)
|
|
||||||
val = {'t': tp_timestamp_utc_now()}
|
val = {'t': tp_timestamp_utc_now()}
|
||||||
|
|
||||||
cpu = psutil.cpu_times_percent()
|
cpu = psutil.cpu_times_percent()
|
||||||
|
@ -82,7 +80,7 @@ class TPSysStatus(threading.Thread):
|
||||||
_read = 0
|
_read = 0
|
||||||
if _write < 0:
|
if _write < 0:
|
||||||
_write = 0
|
_write = 0
|
||||||
val['d'] = {'r': _read, 'w': _write}
|
val['d'] = {'r': int(_read / self._INTERVAL), 'w': int(_write / self._INTERVAL)}
|
||||||
# print(int(_read / self._interval), int(_write / self._interval))
|
# print(int(_read / self._interval), int(_write / self._interval))
|
||||||
|
|
||||||
net = psutil.net_io_counters(pernic=False)
|
net = psutil.net_io_counters(pernic=False)
|
||||||
|
@ -97,14 +95,16 @@ class TPSysStatus(threading.Thread):
|
||||||
_recv = 0
|
_recv = 0
|
||||||
if _sent < 0:
|
if _sent < 0:
|
||||||
_sent = 0
|
_sent = 0
|
||||||
val['n'] = {'r': _recv, 's': _sent}
|
val['n'] = {'r': int(_recv / self._INTERVAL), 's': int(_sent / self._INTERVAL)}
|
||||||
# print(int(_recv / self._interval), int(_sent / self._interval))
|
# print(int(_recv / self._interval), int(_sent / self._interval))
|
||||||
|
|
||||||
# s = json.dumps(val, separators=(',', ':'))
|
self._history.pop(0)
|
||||||
|
self._history.append(val)
|
||||||
|
|
||||||
tp_wss().send_message('sys_real_status', val)
|
tp_wss().send_message('sys_status', val)
|
||||||
|
|
||||||
# print(s)
|
def get_status(self):
|
||||||
|
return self._history
|
||||||
|
|
||||||
|
|
||||||
def tp_sys_status():
|
def tp_sys_status():
|
||||||
|
|
|
@ -15,7 +15,7 @@ from app.base.configs import tp_cfg
|
||||||
from app.base.db import get_db
|
from app.base.db import get_db
|
||||||
from app.base.logger import log
|
from app.base.logger import log
|
||||||
from app.base.session import tp_session
|
from app.base.session import tp_session
|
||||||
# from app.base.cron import tp_corn
|
from app.base.cron import tp_corn
|
||||||
from app.base.status import tp_sys_status
|
from app.base.status import tp_sys_status
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,6 +84,9 @@ class WebApp:
|
||||||
if not tp_session().init():
|
if not tp_session().init():
|
||||||
log.e('can not initialize session manager.\n')
|
log.e('can not initialize session manager.\n')
|
||||||
return 0
|
return 0
|
||||||
|
if not tp_sys_status().init():
|
||||||
|
log.e('can not initialize system status collector.\n')
|
||||||
|
return 0
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
#
|
#
|
||||||
|
@ -130,25 +133,30 @@ class WebApp:
|
||||||
log.e('can not listen on port {}:{}, make sure it not been used by another application.\n'.format(cfg.common.ip, cfg.common.port))
|
log.e('can not listen on port {}:{}, make sure it not been used by another application.\n'.format(cfg.common.ip, cfg.common.port))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
# 启动定时任务调度器
|
||||||
|
tp_corn().init()
|
||||||
|
tp_corn().start()
|
||||||
# 启动session超时管理
|
# 启动session超时管理
|
||||||
tp_session().start()
|
# tp_session().start()
|
||||||
|
|
||||||
def job():
|
# def job():
|
||||||
log.v('---job--\n')
|
# log.v('---job--\n')
|
||||||
# tp_corn().add_job('test', job, first_interval_seconds=None, interval_seconds=10)
|
# tp_corn().add_job('test', job, first_interval_seconds=None, interval_seconds=10)
|
||||||
# tp_corn().init()
|
# tp_sys_status().init()
|
||||||
# tp_corn().start()
|
# tp_sys_status().start()
|
||||||
tp_sys_status().init()
|
|
||||||
tp_sys_status().start()
|
tp_corn().add_job('session_expire', tp_session().check_expire, first_interval_seconds=None, interval_seconds=60)
|
||||||
|
# tp_corn().add_job('sys_status', tp_sys_status().check_status, first_interval_seconds=5, interval_seconds=5)
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tornado.ioloop.IOLoop.instance().start()
|
tornado.ioloop.IOLoop.instance().start()
|
||||||
except:
|
except:
|
||||||
log.e('\n')
|
log.e('\n')
|
||||||
|
|
||||||
# tp_corn().stop()
|
tp_corn().stop()
|
||||||
tp_sys_status().stop()
|
# tp_sys_status().stop()
|
||||||
tp_session().stop()
|
# tp_session().stop()
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,11 @@ class TPWebSocketServer(object):
|
||||||
if '__tp_websocket_server__' in builtins.__dict__:
|
if '__tp_websocket_server__' in builtins.__dict__:
|
||||||
raise RuntimeError('TPWebSocketServer object exists, you can not create more than one instance.')
|
raise RuntimeError('TPWebSocketServer object exists, you can not create more than one instance.')
|
||||||
|
|
||||||
|
self._cb_get_sys_status = None
|
||||||
|
|
||||||
|
def register_get_sys_status_callback(self, cb):
|
||||||
|
self._cb_get_sys_status = cb
|
||||||
|
|
||||||
def have_callbacker(self, callbacker):
|
def have_callbacker(self, callbacker):
|
||||||
return callbacker in self._clients
|
return callbacker in self._clients
|
||||||
|
|
||||||
|
@ -56,25 +61,24 @@ class TPWebSocketServer(object):
|
||||||
for p in req['params']:
|
for p in req['params']:
|
||||||
if p not in self._clients[callbacker]['subscribe']:
|
if p not in self._clients[callbacker]['subscribe']:
|
||||||
self._clients[callbacker]['subscribe'].append(p)
|
self._clients[callbacker]['subscribe'].append(p)
|
||||||
|
elif req['method'] == 'request':
|
||||||
|
if req['param'] == 'sys_status':
|
||||||
|
if self._cb_get_sys_status is not None:
|
||||||
|
message = self._cb_get_sys_status()
|
||||||
|
msg = {'method': 'request', 'param': 'sys_status', 'data': message}
|
||||||
|
s = json.dumps(msg, separators=(',', ':'))
|
||||||
|
callbacker.write_message(s)
|
||||||
|
|
||||||
def send_message(self, subscribe, message):
|
def send_message(self, subscribe, message):
|
||||||
msg = {'subscribe': subscribe, 'data': message}
|
s = None
|
||||||
s = json.dumps(msg, separators=(',', ':'))
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
for c in self._clients:
|
for c in self._clients:
|
||||||
|
|
||||||
if subscribe in self._clients[c]['subscribe']:
|
if subscribe in self._clients[c]['subscribe']:
|
||||||
|
if s is None:
|
||||||
|
msg = {'method': 'subscribe', 'param': subscribe, 'data': message}
|
||||||
|
s = json.dumps(msg, separators=(',', ':'))
|
||||||
c.write_message(s)
|
c.write_message(s)
|
||||||
|
|
||||||
# def response(self, _id, data):
|
|
||||||
# # print('send to client:', url, data)
|
|
||||||
# for callbacker in self.clients:
|
|
||||||
# if self.clients[callbacker].get_id() == _id:
|
|
||||||
# print('[ws] response', _id, data)
|
|
||||||
# callbacker.write_message(data)
|
|
||||||
# return
|
|
||||||
# print('## [ws] response no client.', _id)
|
|
||||||
|
|
||||||
|
|
||||||
def tp_wss():
|
def tp_wss():
|
||||||
"""
|
"""
|
||||||
|
@ -118,4 +122,3 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
|
||||||
self.write_message(json.dumps(ret))
|
self.write_message(json.dumps(ret))
|
||||||
return
|
return
|
||||||
tp_wss().on_message(self, message)
|
tp_wss().on_message(self, message)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue