mirror of https://github.com/MISP/misp-dashboard
Log feed is displayed in the Browser
parent
88b9879726
commit
e5d58c807d
83
server.py
83
server.py
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
|
@ -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>
|
||||
|
||||
|
|
Loading…
Reference in New Issue