Log feed is displayed in the Browser

pull/18/head
= 2017-08-24 11:43:23 +02:00
parent 88b9879726
commit e5d58c807d
3 changed files with 242 additions and 14 deletions

View File

@ -1,11 +1,92 @@
#!/usr/bin/env python3.5
from flask import Flask, render_template
from flask import Flask, render_template, Response
import json
from time import time as now
from time import sleep
app = Flask(__name__)
FIELDNAME = {
'time': 'Time',
'level': 'Level',
'source': 'Source',
'name': 'Name',
'message': 'Message'
}
FIELDNAME_ORDER = [ 'time', 'level', 'source', 'name', 'message' ]
class LogRow():
def __init__(self, feed='', time='', level='level', src='source', name='name', message='wonderful meesage'):
# Parse feed message
# Assign potential supplied values
self.time = time if time != '' else now()
self.level = level
self.source = src
self.name = name
self.message = message
def get_head_row(self):
to_ret = []
for fn in FIELDNAME_ORDER:
to_ret.append(FIELDNAME[fn])
return to_ret
def get_row(self):
to_ret = {}
#Number to keep them sorted (jsonify sort keys)
to_ret[1] = self.time
to_ret[2] = self.level
to_ret[3] = self.source
to_ret[4] = self.name
to_ret[5] = self.message
return to_ret
class EventMessage():
def __init__(self, msg):
self.feed = None
self.isLog = EventMessage.is_log(msg)
#get type of message: log or feed, then create
if self.isLog:
self.feed = msg
#FIXME do parser
self.feed = LogRow(feed=msg).get_row()
else:
self.feed = {feed.name: feed.data}
def is_log(msg):
return True
def to_json(self):
if self.isLog:
to_ret = { 'log': self.feed, 'chart': "" }
else:
to_ret = { 'log': "", 'chart': self.feed }
return 'data: {}\n\n'.format(json.dumps(to_ret))
@app.route("/")
def index():
return render_template('index.html')
@app.route("/_logs")
def logs():
return Response(event_stream(), mimetype="text/event-stream")
@app.route("/_get_log_head")
def getLogHead():
return json.dumps(LogRow().get_head_row())
def event_stream():
#for msg in pubsub:
for i in range(3):
msg = now()
sleep(0.3)
print('sending', EventMessage(msg).to_json())
yield EventMessage(msg).to_json()
if __name__ == '__main__':
app.run(host='localhost', port=8000, debug=True)

150
static/js/index.js Normal file
View File

@ -0,0 +1,150 @@
var updateInterval = 30; // 30ms
var numPoint = 10;
var emptyArray = [];
for(i=0; i<numPoint; i++) {
emptyArray.push(0);
}
var data = { 'undefined': { label: 'undefined', data: [] } };
var curMax = { 'undefined': [] };
var optionsGraph = {
series: {
shadowSize: 0 ,
lines: { fill: true, fillColor: { colors: [ { opacity: 1 }, { opacity: 0.1 } ] }}
},
yaxis: { min: 0, max: 20 },
xaxis: { ticks: [[0, 0], [1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6], [7, 7], [8, 8], [9, 9], [10, 10]] },
grid: {
tickColor: "#dddddd",
borderWidth: 0
},
legend: {
show: true,
position: "nw"
}
};
$(document).ready(function () {
createHead(function() {
if (!!window.EventSource) {
var source = new EventSource(urlForLogs);
source.onopen = function(){
//console.log('connection is opened. '+source.readyState);
};
source.onerror = function(){
//console.log('error: '+source.readyState);
};
source.onmessage = function(event) {
var json = jQuery.parseJSON( event.data );
updateLogTable(json.log);
//updateChartData(json.chart);
};
} else {
console.log("No event source");
}
});
});
//var plot = $.plot("#placeholder", [ [] ], optionsGraph);
//updateChart()
function updateChart() {
plot.setData(data);
plot.getOptions().yaxes[0].max = curMax[dataset];
plot.setupGrid();
plot.draw();
setTimeout(update, updateInterval);
}
function updateChartData(feed) {
if (feed.length == 0)
return;
for (feedName in feed) {
console.log(feedName.name);
if (data[feedName.name] === undefined) {
data[feedName.name] = {};
}
data[feedName.name].data = slide(data[feedName.name].data, feedName.data)
}
}
function updateLogTable(log) {
if (log.length == 0)
return;
// Create new row
tableBody = document.getElementById('table_log_body');
createRow(tableBody, log);
// Remove old row
var logSel = document.getElementById("log_select");
if (tableBody.rows.length > logSel.options[logSel.options.selectedIndex].value){
while (tableBody.rows.length != logSel.options[logSel.options.selectedIndex].value){
tableBody.deleteRow(0);
}
}
}
function slide(orig, newData) {
var slided = orig;
slided.slice(newData.length);
slided.concat(newData);
return slided
}
function createRow(tableBody, log) {
var tr = document.createElement('TR');
var action = document.createElement('TD');
for (var key in log) {
if (log.hasOwnProperty(key)) {
var td = document.createElement('TD');
td.appendChild(document.createTextNode(log[key]));
tr.appendChild(td);
}
}
// level
if( log.level == "INFO" ){
tr.className = "info";
}
else if ( log.level == "WARNING" ){
tr.className = "warning";
}
else if ( log.level == "CRITICAL"){
tr.className = "danger"
}
// action
action.appendChild(document.createTextNode("ACTION"));
tr.appendChild(action);
tableBody.appendChild(tr);
}
function createHead(callback) {
if (document.getElementById('table_log_head').childNodes.length > 1)
return
$.getJSON( urlForHead, function( data ) {
var tr = document.createElement('TR');
for (head of data) {
var th = document.createElement('TH');
th.appendChild(document.createTextNode(head));
tr.appendChild(th);
}
var action = document.createElement('TH');
action.appendChild(document.createTextNode("Actions"));
tr.appendChild(action);
document.getElementById('table_log_head').appendChild(tr);
callback();
});
}

View File

@ -78,20 +78,9 @@
<div class="row">
<div class="col-lg-12">
<table class="table table-bordered table-hover table-striped" id="table_log">
<thead>
<tr>
<th>Time</th>
<th>Channel</th>
<th>Level</th>
<th>Script Name</th>
<th>Source</th>
<th>Date</th>
<th>Paste name</th>
<th>Message</th>
<th>Actions</th>
</tr>
<thead id="table_log_head">
</thead>
<tbody id="tab_body">
<tbody id="table_log_body">
</tbody>
</table>
</div>
@ -113,8 +102,16 @@
<!-- jQuery -->
<script src="{{ url_for('static', filename='js/jquery.min.js') }}"></script>
<!-- jQuery flot -->
<script src="{{ url_for('static', filename='js/jquery.flot.js') }}"></script>
<!-- Bootstrap Core JavaScript -->
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
<!-- Index -->
<script>
var urlForLogs = "{{ url_for('logs') }}";
var urlForHead = "{{ url_for('getLogHead') }}";
</script>
<script src="{{ url_for('static', filename='js/index.js') }}"></script>
</body>