Start on adding usage charts

This commit is contained in:
Joseph Schorr 2015-01-28 12:35:01 -05:00
parent a7ab14479e
commit 63cd6ffcc3
9 changed files with 192 additions and 0 deletions

View file

@ -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():

View file

@ -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

View file

@ -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

View 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>

View file

@ -0,0 +1,3 @@
<div class="realtime-line-chart-element">
<div class="chart" style="width: 450px; height: 250px;"></div>
</div>

View file

@ -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

File diff suppressed because one or more lines are too long

3
static/lib/rickshaw.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -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>