##############################################################################
# Institute for the Design of Advanced Energy Systems Process Systems
# Engineering Framework (IDAES PSE Framework) Copyright (c) 2018, by the
# software owners: The Regents of the University of California, through
# Lawrence Berkeley National Laboratory, National Technology & Engineering
# Solutions of Sandia, LLC, Carnegie Mellon University, West Virginia
# University Research Corporation, et al. All rights reserved.
#
# Please see the files COPYRIGHT.txt and LICENSE.txt for full copyright and
# license information, respectively. Both files are also available online
# at the URL "https://github.com/IDAES/idaes".
##############################################################################
"""
Simple flask log viewer. This is just a very prliminary start on a logging
viewer that can be used along side a jupyter notebook so that you can see what's
going on in your web browser without junking up the jupyter notbook with a bunch
of log messages. This could use a lot of work, but it's something.
"""
from __future__ import division, print_function, absolute_import
__author__ = "John Eslick"
import logging
import time
import datetime
import json
from flask import Flask, request
index_page = """<!DOCTYPE html>
<html>
<body>
<style>
.divformat {
font-family: monospace;
white-space: pre;
font-size: 10pt;
}
</style>
<script>
setTimeout(timeoutFunction, 500);
var update_time_old = "0";
function log_update_listen() {
var log_messages = document.getElementById('log_messages');
log_messages.innerHTML = this.responseText;
setTimeout(timeoutFunction, 500);
}
function update_listen() {
var log_messages = document.getElementById('log_messages');
if (this.responseText != update_time_old){
update_time_old = this.responseText;
var req = new XMLHttpRequest();
var url = window.location.href + "log_entries"
req.addEventListener("load", log_update_listen);
req.open("GET", url);
req.send();
}
else{
setTimeout(timeoutFunction, 500);
}
}
function timeoutFunction() {
var req = new XMLHttpRequest();
var url = window.location.href + "update"
req.addEventListener("load", update_listen);
req.open("GET", url);
req.send();
}
</script>
<div id="log_messages" class="divformat"></div>
</body>
</html>
"""
app = Flask(__name__)
settings = {
"max_display":80,
"max_store":1000,
"format":"%(asctime)s - %(levelname)s - %(name)s - %(message)s",
"datefmt":"%Y-%m-%d %H:%M"}
log_entries = []
last_updated = "0"
[docs]@app.route("/")
def index():
return index_page
[docs]@app.route("/log_entries")
def lines_str():
global log_entries
global settings
fmt = logging.Formatter(fmt=settings["format"], datefmt=settings["datefmt"])
max_display = settings["max_display"]
if len(log_entries) > max_display:
return "\n".join(
[fmt.format(entr) for entr in log_entries[-max_display:]])
else:
return "\n".join(
[fmt.format(entr) for entr in log_entries])
[docs]@app.route("/update")
def get_last_updated():
return last_updated
[docs]@app.route('/settings', methods=['POST', 'GET'])
def set_settings():
global settings
if request.method == 'POST':
try:
settings["max_display"] = int(request.form["max_display"])
except:
pass
try:
settings["max_store"] = int(request.form["max_store"])
except:
pass
try:
settings["format"] = request.form["format"]
except:
pass
try:
settings["datefmt"] = request.form["datefmt"]
except:
pass
return ""
else:
return json.dumps(settings)
[docs]@app.route('/log', methods=['POST'])
def log():
global settings
global last_updated
global log_entries
max_store = settings["max_store"]
d = request.form.to_dict()
# This part may be a bit sketchy but need to convert so repr of record
# attrubutes back without eval and without adding much. Eval for this would
# obviously be a bad idea securty wise. So far this handles
# anything I've run into. The http handler just passed record.__dict__
# apperently using repr? on things like lists, tuples, None, ...
# Really what I should do is impliment the mapLogRecord(record) in an
# HTTPHandler subclass that uses json.
d["created"] = json.loads(d["created"])
d["args"] = "[" + d["args"][1:] # args was a tuple, make it something json
d["args"] = d["args"][:-1] + "]" # can handel
d["args"] = tuple(json.loads(d["args"]))
if d["exc_info"] == "None":
d["exc_info"] = None
if d["exc_text"] == "None":
d["exc_text"] = None
rec = logging.makeLogRecord(d)
log_entries.append(rec)
if len(log_entries) > max_store:
log_entries = log_entries[-max_store:]
last_updated = str(time.clock())
return ""