Start on adding usage charts
This commit is contained in:
parent
a7ab14479e
commit
63cd6ffcc3
9 changed files with 192 additions and 0 deletions
|
@ -4,13 +4,46 @@ import json
|
|||
from flask import request, Blueprint, abort, Response
|
||||
from flask.ext.login import current_user
|
||||
from auth.auth import require_session_login
|
||||
from endpoints.common import route_show_if
|
||||
from app import userevents
|
||||
from auth.permissions import SuperUserPermission
|
||||
|
||||
import features
|
||||
import psutil
|
||||
import time
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
realtime = Blueprint('realtime', __name__)
|
||||
|
||||
|
||||
@realtime.route("/ps")
|
||||
@route_show_if(features.SUPER_USERS)
|
||||
@require_session_login
|
||||
def ps():
|
||||
if not SuperUserPermission().can():
|
||||
abort(403)
|
||||
|
||||
def generator():
|
||||
while True:
|
||||
data = {
|
||||
'count': {
|
||||
'cpu': psutil.cpu_percent(interval=1, percpu=True),
|
||||
'virtual_mem': psutil.virtual_memory(),
|
||||
'swap_mem': psutil.swap_memory(),
|
||||
'connections': len(psutil.net_connections()),
|
||||
'processes': len(psutil.pids()),
|
||||
'network': psutil.net_io_counters()
|
||||
}
|
||||
}
|
||||
json_string = json.dumps(data)
|
||||
yield 'data: %s\n\n' % json_string
|
||||
time.sleep(0.25)
|
||||
|
||||
return Response(generator(), mimetype="text/event-stream")
|
||||
|
||||
|
||||
|
||||
@realtime.route("/user/")
|
||||
@require_session_login
|
||||
def index():
|
||||
|
|
|
@ -41,3 +41,4 @@ git+https://github.com/DevTable/anunidecode.git
|
|||
git+https://github.com/DevTable/avatar-generator.git
|
||||
git+https://github.com/DevTable/pygithub.git
|
||||
gipc
|
||||
psutil
|
||||
|
|
|
@ -37,6 +37,7 @@ marisa-trie==0.7
|
|||
mixpanel-py==3.2.1
|
||||
paramiko==1.15.2
|
||||
peewee==2.4.5
|
||||
psutil==2.2.0
|
||||
psycopg2==2.5.4
|
||||
py-bcrypt==0.4
|
||||
pycrypto==2.6.1
|
||||
|
|
24
static/directives/ps-usage-graph.html
Normal file
24
static/directives/ps-usage-graph.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
<div class="ps-usage-graph-element">
|
||||
CPU:
|
||||
<div class="realtime-line-chart" data="data.count.cpu" counter="counter"
|
||||
label-template="CPU #{x} %"></div>
|
||||
|
||||
Process Count:
|
||||
<div class="realtime-line-chart" data="data.count.processes" counter="counter"
|
||||
label-template="Process Count"></div>
|
||||
|
||||
Virtual Memory:
|
||||
<div class="realtime-line-chart" data="data.count.virtual_mem[2]" counter="counter"
|
||||
label-template="Virtual Memory %"></div>
|
||||
|
||||
Swap Memory:
|
||||
<div class="realtime-line-chart" data="data.count.swap_mem[3]" counter="counter"
|
||||
label-template="Swap Memory %"></div>
|
||||
|
||||
Network Connections:
|
||||
<div class="realtime-line-chart" data="data.count.connections" counter="counter"
|
||||
label-template="Network Connection Count"></div>
|
||||
|
||||
Network Usage:
|
||||
<div class="realtime-line-chart" data="data.count.network" labels="['Bytes In', 'Bytes Out']" counter="counter"></div>
|
||||
</div>
|
3
static/directives/realtime-line-chart.html
Normal file
3
static/directives/realtime-line-chart.html
Normal file
|
@ -0,0 +1,3 @@
|
|||
<div class="realtime-line-chart-element">
|
||||
<div class="chart" style="width: 450px; height: 250px;"></div>
|
||||
</div>
|
123
static/js/app.js
123
static/js/app.js
|
@ -6522,6 +6522,129 @@ quayApp.directive('locationView', function () {
|
|||
});
|
||||
|
||||
|
||||
quayApp.directive('realtimeLineChart', function () {
|
||||
var directiveDefinitionObject = {
|
||||
priority: 0,
|
||||
templateUrl: '/static/directives/realtime-line-chart.html',
|
||||
replace: false,
|
||||
transclude: false,
|
||||
restrict: 'C',
|
||||
scope: {
|
||||
'data': '=data',
|
||||
'labels': '=labels',
|
||||
'counter': '=counter',
|
||||
'labelTemplate': '@labelTemplate'
|
||||
},
|
||||
controller: function($scope, $element) {
|
||||
var graph = null;
|
||||
var hoverDetail = null;
|
||||
var series = [];
|
||||
var counter = 0;
|
||||
var palette = new Rickshaw.Color.Palette( { scheme: 'spectrum14' } );
|
||||
|
||||
var setupGraph = function() {
|
||||
graph = new Rickshaw.Graph({
|
||||
element: $element.find('.chart')[0],
|
||||
renderer: 'line',
|
||||
series: series,
|
||||
min: 'auto',
|
||||
padding: {
|
||||
'top': 0.1,
|
||||
'left': 0.01,
|
||||
'right': 0.01,
|
||||
'bottom': 0.1
|
||||
}
|
||||
});
|
||||
|
||||
hoverDetail = new Rickshaw.Graph.HoverDetail({
|
||||
graph: graph,
|
||||
xFormatter: function(x) {
|
||||
return x.toString();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var refresh = function(data) {
|
||||
if (!data) { return; }
|
||||
if (!graph) {
|
||||
setupGraph();
|
||||
}
|
||||
|
||||
if (typeof data == 'number') {
|
||||
data = [data];
|
||||
}
|
||||
|
||||
if ($scope.labels) {
|
||||
data = data.slice(0, $scope.labels.length);
|
||||
}
|
||||
|
||||
if (series.length == 0){
|
||||
for (var i = 0; i < data.length; ++i) {
|
||||
var title = $scope.labels ? $scope.labels[i] : $scope.labelTemplate.replace('{x}', i + 1);
|
||||
series.push({
|
||||
'color': palette.color(),
|
||||
'data': [],
|
||||
'name': title
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
counter++;
|
||||
|
||||
for (var i = 0; i < data.length; ++i) {
|
||||
var arr = series[i].data;
|
||||
arr.push({
|
||||
'x': counter,
|
||||
'y': data[i]
|
||||
})
|
||||
|
||||
if (arr.length > 10) {
|
||||
series[i].data = arr.slice(arr.length - 10, arr.length);
|
||||
}
|
||||
}
|
||||
|
||||
graph.render();
|
||||
};
|
||||
|
||||
$scope.$watch('counter', function(counter) {
|
||||
refresh($scope.data_raw);
|
||||
});
|
||||
|
||||
$scope.$watch('data', function(data) {
|
||||
$scope.data_raw = data;
|
||||
});
|
||||
}
|
||||
};
|
||||
return directiveDefinitionObject;
|
||||
});
|
||||
|
||||
|
||||
quayApp.directive('psUsageGraph', function () {
|
||||
var directiveDefinitionObject = {
|
||||
priority: 0,
|
||||
templateUrl: '/static/directives/ps-usage-graph.html',
|
||||
replace: false,
|
||||
transclude: false,
|
||||
restrict: 'C',
|
||||
scope: {
|
||||
},
|
||||
controller: function($scope, $element) {
|
||||
$scope.counter = -1;
|
||||
$scope.data = null;
|
||||
|
||||
var source = new EventSource('/realtime/ps');
|
||||
source.onmessage = function(e) {
|
||||
$scope.$apply(function() {
|
||||
$scope.counter++;
|
||||
$scope.data = JSON.parse(e.data);
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
return directiveDefinitionObject;
|
||||
});
|
||||
|
||||
|
||||
quayApp.directive('avatar', function () {
|
||||
var directiveDefinitionObject = {
|
||||
priority: 0,
|
||||
|
|
1
static/lib/rickshaw.min.css
vendored
Normal file
1
static/lib/rickshaw.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
3
static/lib/rickshaw.min.js
vendored
Normal file
3
static/lib/rickshaw.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,7 @@
|
|||
<div class="container" quay-show="Features.SUPER_USERS && showInterface">
|
||||
|
||||
<div class="ps-usage-graph"></div>
|
||||
|
||||
<div class="alert alert-info">
|
||||
This panel provides administrator access to <strong>super users of this installation of the registry</strong>. Super users can be managed in the configuration for this installation.
|
||||
</div>
|
||||
|
|
Reference in a new issue