dashboard的CPU负载和内存用量展示可用了。
							parent
							
								
									145e3a0d5c
								
							
						
					
					
						commit
						5b8f882f61
					
				| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
"use strict";
 | 
			
		||||
 | 
			
		||||
$app.on_init = function (cb_stack) {
 | 
			
		||||
    $app.MAX_OVERLOAD_DATA = 20;
 | 
			
		||||
    $app.MAX_OVERLOAD_DATA = 10 * 60 / 5;
 | 
			
		||||
    $app.dom = {
 | 
			
		||||
        count_user: $('#count-user')
 | 
			
		||||
        , count_host: $('#count-host')
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ $app.on_init = function (cb_stack) {
 | 
			
		|||
    // refresh basic info every 1m.
 | 
			
		||||
    $app.load_basic_info();
 | 
			
		||||
    // refresh overload info every 5m.
 | 
			
		||||
    $app.load_overload_info();
 | 
			
		||||
    //$app.load_overload_info();
 | 
			
		||||
 | 
			
		||||
    $app.ws = null;
 | 
			
		||||
    $app.init_ws();
 | 
			
		||||
| 
						 | 
				
			
			@ -42,50 +42,40 @@ $app.load_basic_info = function () {
 | 
			
		|||
    setTimeout($app.load_basic_info, 60 * 1000);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
$app.load_overload_info = function () {
 | 
			
		||||
$app.init_sys_status_info = function (data) {
 | 
			
		||||
    var i = 0;
 | 
			
		||||
    // var bar_x = [];
 | 
			
		||||
    // for (i = 0; i < $app.MAX_OVERLOAD_DATA; i++) {
 | 
			
		||||
    //     bar_x.push(i);
 | 
			
		||||
    // }
 | 
			
		||||
    // var t = (Math.floor(Date.now() / 1000) - $app.MAX_OVERLOAD_DATA - 1) * 1000;
 | 
			
		||||
    console.log(data);
 | 
			
		||||
 | 
			
		||||
    var now = Math.floor(Date.now() / 1000);
 | 
			
		||||
    console.log('now', now);
 | 
			
		||||
    //=====================================
 | 
			
		||||
    // CPU
 | 
			
		||||
    //=====================================
 | 
			
		||||
 | 
			
		||||
    $app.bar_cpu_user = [];
 | 
			
		||||
    $app.bar_cpu_sys = [];
 | 
			
		||||
    var t = tp_local2utc(now - $app.MAX_OVERLOAD_DATA - 1);
 | 
			
		||||
    console.log(t);
 | 
			
		||||
    for (i = 0; i < $app.MAX_OVERLOAD_DATA; i++) {
 | 
			
		||||
        var x = t + i;
 | 
			
		||||
        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([
 | 
			
		||||
            {
 | 
			
		||||
                name: x.toString()
 | 
			
		||||
                , value: [tp_format_datetime(tp_utc2local(x)), 0]
 | 
			
		||||
            }
 | 
			
		||||
        ]);
 | 
			
		||||
    for (i = 0; i < data.length; i++) {
 | 
			
		||||
        // var x = t + i * 1000;
 | 
			
		||||
        $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]});
 | 
			
		||||
        $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('--', $app.bar_cpu_data);
 | 
			
		||||
 | 
			
		||||
    var clr_user = '#e2524c';
 | 
			
		||||
    var clr_user_area = '#f7827a';
 | 
			
		||||
    var clr_sys = '#558c5a';
 | 
			
		||||
    var clr_sys_area = '#3dc34a';
 | 
			
		||||
 | 
			
		||||
    $app.bar_cpu = echarts.init(document.getElementById('bar-cpu'));
 | 
			
		||||
    $app.bar_cpu.setOption({
 | 
			
		||||
        title: {
 | 
			
		||||
            // show: false
 | 
			
		||||
            text: 'CPU负载'
 | 
			
		||||
            , top: 0
 | 
			
		||||
            , left: 50
 | 
			
		||||
            , textStyle: {
 | 
			
		||||
                color: 'rgba(0,0,0,0.5)'
 | 
			
		||||
                , fontSize: 14
 | 
			
		||||
            text: 'CPU负载',
 | 
			
		||||
            top: 0,
 | 
			
		||||
            textStyle: {
 | 
			
		||||
                color: 'rgba(0,0,0,0.5)',
 | 
			
		||||
                fontSize: 14
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        color: [clr_sys, clr_user],
 | 
			
		||||
        grid: {
 | 
			
		||||
            show: true
 | 
			
		||||
            , left: 30
 | 
			
		||||
| 
						 | 
				
			
			@ -94,54 +84,151 @@ $app.load_overload_info = function () {
 | 
			
		|||
            , bottom: 20
 | 
			
		||||
        },
 | 
			
		||||
        tooltip: {
 | 
			
		||||
            trigger: 'axis'
 | 
			
		||||
            , formatter: function (params) {
 | 
			
		||||
                console.log(params);
 | 
			
		||||
                //params = params[0];
 | 
			
		||||
                var t = parseInt(params[0].name);
 | 
			
		||||
                return tp_format_datetime(tp_utc2local(t), 'HH:mm:ss') + '<br/>' + params[0].value[1] + '%, ' + params[1].value[1] + '%';
 | 
			
		||||
            }
 | 
			
		||||
            , axisPointer: {
 | 
			
		||||
            trigger: 'axis',
 | 
			
		||||
            formatter: function (params) {
 | 
			
		||||
                return params[0].name + '<br/>'+ params[1].seriesName + ': ' + params[1].value[1] + '%<br/>' + params[0].seriesName + ': ' + params[0].value[1] + '%';
 | 
			
		||||
            },
 | 
			
		||||
            axisPointer: {
 | 
			
		||||
                animation: false
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        // legend: {
 | 
			
		||||
        //     // show: false
 | 
			
		||||
        // },
 | 
			
		||||
        xAxis: {
 | 
			
		||||
            type: 'time'
 | 
			
		||||
            , boundaryGap: false
 | 
			
		||||
            , axisLine: {show: false}
 | 
			
		||||
        legend: {
 | 
			
		||||
            right: 20,
 | 
			
		||||
            data: [
 | 
			
		||||
                {name: '系统', icon: 'rect'},
 | 
			
		||||
                {name: '用户', icon: 'rect'}
 | 
			
		||||
            ]
 | 
			
		||||
        },
 | 
			
		||||
        xAxis: {
 | 
			
		||||
            type: 'time',
 | 
			
		||||
            boundaryGap: false,
 | 
			
		||||
            splitNumber: 10,
 | 
			
		||||
            axisLine: {show: false}
 | 
			
		||||
        },
 | 
			
		||||
        // yAxis: {type: 'value', min: 'dataMin', axisLine: {show: false}, splitLine: {show: false}},
 | 
			
		||||
        yAxis: {
 | 
			
		||||
            type: 'value'
 | 
			
		||||
            , axisLine: {
 | 
			
		||||
                show: false
 | 
			
		||||
            }
 | 
			
		||||
            , min: 0
 | 
			
		||||
            , max: 100
 | 
			
		||||
            , boundaryGap: [0, '50%']
 | 
			
		||||
            type: 'value',
 | 
			
		||||
            axisLine: {show: false},
 | 
			
		||||
            min: 0,
 | 
			
		||||
            max: 100,
 | 
			
		||||
            containLabel: true
 | 
			
		||||
 | 
			
		||||
        },
 | 
			
		||||
        series: [
 | 
			
		||||
            {
 | 
			
		||||
                name: 'cpu-sys'
 | 
			
		||||
                , type: 'line'
 | 
			
		||||
                , smooth: true
 | 
			
		||||
                , symbol: 'none'
 | 
			
		||||
                , stack: 'a'
 | 
			
		||||
                , showSymbol: false
 | 
			
		||||
                , 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_sys
 | 
			
		||||
                        }, {
 | 
			
		||||
                            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
 | 
			
		||||
            }
 | 
			
		||||
            , {
 | 
			
		||||
                name: 'cpu-user'
 | 
			
		||||
                , type: 'line'
 | 
			
		||||
                , smooth: true
 | 
			
		||||
                , symbol: 'none'
 | 
			
		||||
                , stack: 'a'
 | 
			
		||||
                , showSymbol: false
 | 
			
		||||
                , 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.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) {
 | 
			
		||||
        // console.log('[ws] ws-on-close', e);
 | 
			
		||||
| 
						 | 
				
			
			@ -164,36 +252,28 @@ $app.init_ws = function () {
 | 
			
		|||
    };
 | 
			
		||||
    $app.ws.onmessage = function (e) {
 | 
			
		||||
        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.push({
 | 
			
		||||
                'name': t.data.t.toString(),
 | 
			
		||||
                'value': [tp_format_datetime(tp_utc2local(t.data.t)), t.data.c.u]
 | 
			
		||||
            });
 | 
			
		||||
            $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]});
 | 
			
		||||
            $app.bar_cpu_sys.shift();
 | 
			
		||||
            $app.bar_cpu_sys.push({
 | 
			
		||||
                '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_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]});
 | 
			
		||||
            $app.bar_cpu.setOption(
 | 
			
		||||
                {
 | 
			
		||||
                    // xAxis: {data: 1},
 | 
			
		||||
                    series: [
 | 
			
		||||
                        {
 | 
			
		||||
                            name: 'cpu-user'
 | 
			
		||||
                            , data: $app.bar_cpu_user
 | 
			
		||||
                        }
 | 
			
		||||
                        , {
 | 
			
		||||
                            name: 'cpu-sys'
 | 
			
		||||
                            , data: $app.bar_cpu_sys
 | 
			
		||||
                        }
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
                {series: [{data: $app.bar_cpu_sys}, {data: $app.bar_cpu_user}]}
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            $app.bar_mem_used.shift();
 | 
			
		||||
            $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)]});
 | 
			
		||||
            $app.bar_mem.setOption(
 | 
			
		||||
                {series: [{data: $app.bar_mem_used}]}
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,13 +54,13 @@ function tp_check_ip(ip) {
 | 
			
		|||
// 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function prefixInteger(num, length) {
 | 
			
		||||
    return (num / Math.pow(10, length)).toFixed(length).substr(2);
 | 
			
		||||
}
 | 
			
		||||
// function prefixInteger(num, length) {
 | 
			
		||||
//     return (num / Math.pow(10, length)).toFixed(length).substr(2);
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
function tp_size2str(size, precision) {
 | 
			
		||||
    precision = precision || 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -71,23 +71,23 @@ function tp_size2str(size, precision) {
 | 
			
		|||
        k = 'B';
 | 
			
		||||
    }
 | 
			
		||||
    else if (size < MB) {
 | 
			
		||||
        s = digital_precision(size / KB, precision);
 | 
			
		||||
        s = tp_digital_precision(size / KB, precision);
 | 
			
		||||
        k = 'KB'
 | 
			
		||||
    }
 | 
			
		||||
    else if (size < GB) {
 | 
			
		||||
        s = digital_precision(size / MB, precision);
 | 
			
		||||
        s = tp_digital_precision(size / MB, precision);
 | 
			
		||||
        k = 'MB'
 | 
			
		||||
    }
 | 
			
		||||
    else if (size < TB) {
 | 
			
		||||
        s = digital_precision(size / GB, precision);
 | 
			
		||||
        s = tp_digital_precision(size / GB, precision);
 | 
			
		||||
        k = 'GB'
 | 
			
		||||
    }
 | 
			
		||||
    else if (size < PB) {
 | 
			
		||||
        s = digital_precision(size / TB, precision);
 | 
			
		||||
        s = tp_digital_precision(size / TB, precision);
 | 
			
		||||
        k = 'TB'
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        s = digital_precision(size / PB, precision);
 | 
			
		||||
        s = tp_digital_precision(size / PB, precision);
 | 
			
		||||
        k = 'PB'
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -70,15 +70,13 @@
 | 
			
		|||
    <div class="row">
 | 
			
		||||
        <div class="col-sm-6">
 | 
			
		||||
            <div class="stats stats-bar">
 | 
			
		||||
##                 <div class="stats-name">CPU负载</div>
 | 
			
		||||
                <div class="stats-value" id="bar-cpu" style="height:260px;">
 | 
			
		||||
                <div class="stats-value" id="bar-cpu" style="height:180px;">
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-sm-6">
 | 
			
		||||
            <div class="stats stats-bar">
 | 
			
		||||
                <div class="stats-name">内存使用</div>
 | 
			
		||||
                <div class="stats-value">
 | 
			
		||||
                <div class="stats-value" id="bar-mem" style="height:180px;">
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,12 +7,15 @@ from app.base.logger import log
 | 
			
		|||
from app.base.configs import tp_cfg
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SessionManager(threading.Thread):
 | 
			
		||||
# class SessionManager(threading.Thread):
 | 
			
		||||
class SessionManager(object):
 | 
			
		||||
 | 
			
		||||
    # SESSION_EXPIRE = 3600  # 60*60  默认超时时间为1小时
 | 
			
		||||
    _expire = 3600
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__(name='session-manager-thread')
 | 
			
		||||
        # super().__init__(name='session-manager-thread')
 | 
			
		||||
        super().__init__()
 | 
			
		||||
 | 
			
		||||
        import builtins
 | 
			
		||||
        if '__session_manager__' in builtins.__dict__:
 | 
			
		||||
| 
						 | 
				
			
			@ -26,39 +29,48 @@ class SessionManager(threading.Thread):
 | 
			
		|||
        self._stop_flag = False
 | 
			
		||||
        self._timer_cond = threading.Condition()
 | 
			
		||||
 | 
			
		||||
        self.update_default_expire()
 | 
			
		||||
 | 
			
		||||
    def init(self):
 | 
			
		||||
        self.update_default_expire()
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def update_default_expire(self):
 | 
			
		||||
        self._expire = tp_cfg().sys.login.session_timeout * 60
 | 
			
		||||
 | 
			
		||||
    def stop(self):
 | 
			
		||||
        self._stop_flag = True
 | 
			
		||||
        self._timer_cond.acquire()
 | 
			
		||||
        self._timer_cond.notify()
 | 
			
		||||
        self._timer_cond.release()
 | 
			
		||||
        self.join()
 | 
			
		||||
        log.v('{} stopped.\n'.format(self.name))
 | 
			
		||||
    # def stop(self):
 | 
			
		||||
    #     self._stop_flag = True
 | 
			
		||||
    #     self._timer_cond.acquire()
 | 
			
		||||
    #     self._timer_cond.notify()
 | 
			
		||||
    #     self._timer_cond.release()
 | 
			
		||||
    #     self.join()
 | 
			
		||||
    #     log.v('{} stopped.\n'.format(self.name))
 | 
			
		||||
 | 
			
		||||
    def run(self):
 | 
			
		||||
        while True:
 | 
			
		||||
            self._timer_cond.acquire()
 | 
			
		||||
            # 每隔一分钟醒来检查一次超时的会话
 | 
			
		||||
            self._timer_cond.wait(60)
 | 
			
		||||
            self._timer_cond.release()
 | 
			
		||||
            if self._stop_flag:
 | 
			
		||||
                break
 | 
			
		||||
    # def run(self):
 | 
			
		||||
    #     while True:
 | 
			
		||||
    #         self._timer_cond.acquire()
 | 
			
		||||
    #         # 每隔一分钟醒来检查一次超时的会话
 | 
			
		||||
    #         self._timer_cond.wait(60)
 | 
			
		||||
    #         self._timer_cond.release()
 | 
			
		||||
    #         if self._stop_flag:
 | 
			
		||||
    #             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]
 | 
			
		||||
 | 
			
		||||
            _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())
 | 
			
		||||
        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 set(self, s_id, value, expire=None):
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,24 +8,22 @@ import json
 | 
			
		|||
 | 
			
		||||
from app.base.logger import log
 | 
			
		||||
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.base.cron import tp_corn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TPSysStatus(threading.Thread):
 | 
			
		||||
class TPSysStatus(object):
 | 
			
		||||
    _INTERVAL = 5  # seconds
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__(name='sys-status-thread')
 | 
			
		||||
        super().__init__()
 | 
			
		||||
 | 
			
		||||
        import builtins
 | 
			
		||||
        if '__tp_sys_status__' in builtins.__dict__:
 | 
			
		||||
            raise RuntimeError('TPSysStatus object exists, you can not create more than one instance.')
 | 
			
		||||
 | 
			
		||||
        # session表,session_id为索引,每个项为一个字典,包括 v(value), t(last access), e(expire seconds)
 | 
			
		||||
        self._session_dict = dict()
 | 
			
		||||
 | 
			
		||||
        self._stop_flag = False
 | 
			
		||||
        self._time_cnt = 0
 | 
			
		||||
        self._interval = 2
 | 
			
		||||
        # 实时数据我们在内存中保留最近10分钟的数据,每5秒收集一次,共 10*60/5 = 120 条记录
 | 
			
		||||
        self._history = list()
 | 
			
		||||
 | 
			
		||||
        self._disk_read = 0
 | 
			
		||||
        self._disk_write = 0
 | 
			
		||||
| 
						 | 
				
			
			@ -33,6 +31,19 @@ class TPSysStatus(threading.Thread):
 | 
			
		|||
        self._net_sent = 0
 | 
			
		||||
 | 
			
		||||
    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()
 | 
			
		||||
        net = psutil.net_io_counters(pernic=False)
 | 
			
		||||
        self._net_recv = net.bytes_recv
 | 
			
		||||
| 
						 | 
				
			
			@ -41,70 +52,59 @@ class TPSysStatus(threading.Thread):
 | 
			
		|||
        self._disk_read = disk.read_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
 | 
			
		||||
 | 
			
		||||
    def stop(self):
 | 
			
		||||
        self._stop_flag = True
 | 
			
		||||
        self.join()
 | 
			
		||||
        log.v('{} stopped.\n'.format(self.name))
 | 
			
		||||
    def _check_status(self):
 | 
			
		||||
        # time.sleep(self._interval)
 | 
			
		||||
        val = {'t': tp_timestamp_utc_now()}
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
        cpu = psutil.cpu_times_percent()
 | 
			
		||||
        # print(int(cpu.user * 100), int(cpu.system * 100))
 | 
			
		||||
        val['c'] = {'u': cpu.user, 's': cpu.system}
 | 
			
		||||
        #
 | 
			
		||||
        mem = psutil.virtual_memory()
 | 
			
		||||
        val['m'] = {'u': mem.used, 't': mem.total}
 | 
			
		||||
        # print(mem.total, mem.used, int(mem.used * 100 / mem.total))
 | 
			
		||||
 | 
			
		||||
            time.sleep(self._interval)
 | 
			
		||||
            val = {'t': tp_timestamp_utc_now()}
 | 
			
		||||
        disk = psutil.disk_io_counters(perdisk=False)
 | 
			
		||||
        # val['d'] = {'r': disk.read_byes, 'w': disk.write_bytes}
 | 
			
		||||
        # print(disk.read_bytes, disk.write_bytes)
 | 
			
		||||
        _read = disk.read_bytes - self._disk_read
 | 
			
		||||
        _write = disk.write_bytes - self._disk_write
 | 
			
		||||
        self._disk_read = disk.read_bytes
 | 
			
		||||
        self._disk_write = disk.write_bytes
 | 
			
		||||
 | 
			
		||||
            cpu = psutil.cpu_times_percent()
 | 
			
		||||
            # print(int(cpu.user * 100), int(cpu.system * 100))
 | 
			
		||||
            val['c'] = {'u': cpu.user, 's': cpu.system}
 | 
			
		||||
            #
 | 
			
		||||
            mem = psutil.virtual_memory()
 | 
			
		||||
            val['m'] = {'u': mem.used, 't': mem.total}
 | 
			
		||||
            # print(mem.total, mem.used, int(mem.used * 100 / mem.total))
 | 
			
		||||
        if _read < 0:
 | 
			
		||||
            _read = 0
 | 
			
		||||
        if _write < 0:
 | 
			
		||||
            _write = 0
 | 
			
		||||
        val['d'] = {'r': int(_read / self._INTERVAL), 'w': int(_write / self._INTERVAL)}
 | 
			
		||||
        # print(int(_read / self._interval), int(_write / self._interval))
 | 
			
		||||
 | 
			
		||||
            disk = psutil.disk_io_counters(perdisk=False)
 | 
			
		||||
            # val['d'] = {'r': disk.read_byes, 'w': disk.write_bytes}
 | 
			
		||||
            # print(disk.read_bytes, disk.write_bytes)
 | 
			
		||||
            _read = disk.read_bytes - self._disk_read
 | 
			
		||||
            _write = disk.write_bytes - self._disk_write
 | 
			
		||||
            self._disk_read = disk.read_bytes
 | 
			
		||||
            self._disk_write = disk.write_bytes
 | 
			
		||||
        net = psutil.net_io_counters(pernic=False)
 | 
			
		||||
        _recv = net.bytes_recv - self._net_recv
 | 
			
		||||
        _sent = net.bytes_sent - self._net_sent
 | 
			
		||||
        self._net_recv = net.bytes_recv
 | 
			
		||||
        self._net_sent = net.bytes_sent
 | 
			
		||||
 | 
			
		||||
            if _read < 0:
 | 
			
		||||
                _read = 0
 | 
			
		||||
            if _write < 0:
 | 
			
		||||
                _write = 0
 | 
			
		||||
            val['d'] = {'r': _read, 'w': _write}
 | 
			
		||||
            # print(int(_read / self._interval), int(_write / self._interval))
 | 
			
		||||
        # On some systems such as Linux, on a very busy or long-lived system, the numbers
 | 
			
		||||
        # returned by the kernel may overflow and wrap (restart from zero)
 | 
			
		||||
        if _recv < 0:
 | 
			
		||||
            _recv = 0
 | 
			
		||||
        if _sent < 0:
 | 
			
		||||
            _sent = 0
 | 
			
		||||
        val['n'] = {'r': int(_recv / self._INTERVAL), 's': int(_sent / self._INTERVAL)}
 | 
			
		||||
        # print(int(_recv / self._interval), int(_sent / self._interval))
 | 
			
		||||
 | 
			
		||||
            net = psutil.net_io_counters(pernic=False)
 | 
			
		||||
            _recv = net.bytes_recv - self._net_recv
 | 
			
		||||
            _sent = net.bytes_sent - self._net_sent
 | 
			
		||||
            self._net_recv = net.bytes_recv
 | 
			
		||||
            self._net_sent = net.bytes_sent
 | 
			
		||||
        self._history.pop(0)
 | 
			
		||||
        self._history.append(val)
 | 
			
		||||
 | 
			
		||||
            # On some systems such as Linux, on a very busy or long-lived system, the numbers
 | 
			
		||||
            # returned by the kernel may overflow and wrap (restart from zero)
 | 
			
		||||
            if _recv < 0:
 | 
			
		||||
                _recv = 0
 | 
			
		||||
            if _sent < 0:
 | 
			
		||||
                _sent = 0
 | 
			
		||||
            val['n'] = {'r': _recv, 's': _sent}
 | 
			
		||||
            # print(int(_recv / self._interval), int(_sent / self._interval))
 | 
			
		||||
        tp_wss().send_message('sys_status', val)
 | 
			
		||||
 | 
			
		||||
            # s = json.dumps(val, separators=(',', ':'))
 | 
			
		||||
 | 
			
		||||
            tp_wss().send_message('sys_real_status', val)
 | 
			
		||||
 | 
			
		||||
            # print(s)
 | 
			
		||||
    def get_status(self):
 | 
			
		||||
        return self._history
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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.logger import log
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -84,6 +84,9 @@ class WebApp:
 | 
			
		|||
        if not tp_session().init():
 | 
			
		||||
            log.e('can not initialize session manager.\n')
 | 
			
		||||
            return 0
 | 
			
		||||
        if not tp_sys_status().init():
 | 
			
		||||
            log.e('can not initialize system status collector.\n')
 | 
			
		||||
            return 0
 | 
			
		||||
 | 
			
		||||
        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))
 | 
			
		||||
            return 0
 | 
			
		||||
 | 
			
		||||
        # 启动定时任务调度器
 | 
			
		||||
        tp_corn().init()
 | 
			
		||||
        tp_corn().start()
 | 
			
		||||
        # 启动session超时管理
 | 
			
		||||
        tp_session().start()
 | 
			
		||||
        # tp_session().start()
 | 
			
		||||
 | 
			
		||||
        def job():
 | 
			
		||||
            log.v('---job--\n')
 | 
			
		||||
        # def job():
 | 
			
		||||
        #     log.v('---job--\n')
 | 
			
		||||
        # tp_corn().add_job('test', job, first_interval_seconds=None, interval_seconds=10)
 | 
			
		||||
        # tp_corn().init()
 | 
			
		||||
        # tp_corn().start()
 | 
			
		||||
        tp_sys_status().init()
 | 
			
		||||
        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:
 | 
			
		||||
            tornado.ioloop.IOLoop.instance().start()
 | 
			
		||||
        except:
 | 
			
		||||
            log.e('\n')
 | 
			
		||||
 | 
			
		||||
        # tp_corn().stop()
 | 
			
		||||
        tp_sys_status().stop()
 | 
			
		||||
        tp_session().stop()
 | 
			
		||||
        tp_corn().stop()
 | 
			
		||||
        # tp_sys_status().stop()
 | 
			
		||||
        # tp_session().stop()
 | 
			
		||||
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,11 @@ class TPWebSocketServer(object):
 | 
			
		|||
        if '__tp_websocket_server__' in builtins.__dict__:
 | 
			
		||||
            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):
 | 
			
		||||
        return callbacker in self._clients
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -56,25 +61,24 @@ class TPWebSocketServer(object):
 | 
			
		|||
            for p in req['params']:
 | 
			
		||||
                if p not in self._clients[callbacker]['subscribe']:
 | 
			
		||||
                    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):
 | 
			
		||||
        msg = {'subscribe': subscribe, 'data': message}
 | 
			
		||||
        s = json.dumps(msg, separators=(',', ':'))
 | 
			
		||||
        s = None
 | 
			
		||||
        with self._lock:
 | 
			
		||||
            for c in self._clients:
 | 
			
		||||
 | 
			
		||||
                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)
 | 
			
		||||
 | 
			
		||||
    # 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():
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -118,4 +122,3 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
 | 
			
		|||
            self.write_message(json.dumps(ret))
 | 
			
		||||
            return
 | 
			
		||||
        tp_wss().on_message(self, message)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue