ZeroNet/plugins/Sidebar/ConsolePlugin.py

102 lines
3.3 KiB
Python

import re
import logging
from Plugin import PluginManager
from Config import config
from Debug import Debug
from util import SafeRe
from util.Flag import flag
class WsLogStreamer(logging.StreamHandler):
def __init__(self, stream_id, ui_websocket, filter):
self.stream_id = stream_id
self.ui_websocket = ui_websocket
if filter:
if not SafeRe.isSafePattern(filter):
raise Exception("Not a safe prex pattern")
self.filter_re = re.compile(".*" + filter)
else:
self.filter_re = None
return super(WsLogStreamer, self).__init__()
def emit(self, record):
if self.ui_websocket.ws.closed:
self.stop()
return
line = self.format(record)
if self.filter_re and not self.filter_re.match(line):
return False
self.ui_websocket.cmd("logLineAdd", {"stream_id": self.stream_id, "lines": [line]})
def stop(self):
logging.getLogger('').removeHandler(self)
@PluginManager.registerTo("UiWebsocket")
class UiWebsocketPlugin(object):
def __init__(self, *args, **kwargs):
self.log_streamers = {}
return super(UiWebsocketPlugin, self).__init__(*args, **kwargs)
@flag.no_multiuser
@flag.admin
def actionConsoleLogRead(self, to, filter=None, read_size=32 * 1024, limit=500):
log_file_path = "%s/debug.log" % config.log_dir
log_file = open(log_file_path, encoding="utf-8")
log_file.seek(0, 2)
end_pos = log_file.tell()
log_file.seek(max(0, end_pos - read_size))
if log_file.tell() != 0:
log_file.readline() # Partial line junk
pos_start = log_file.tell()
lines = []
if filter:
assert SafeRe.isSafePattern(filter)
filter_re = re.compile(".*" + filter)
last_match = False
for line in log_file:
if not line.startswith("[") and last_match: # Multi-line log entry
lines.append(line.replace(" ", " "))
continue
if filter and not filter_re.match(line):
last_match = False
continue
last_match = True
lines.append(line)
num_found = len(lines)
lines = lines[-limit:]
return {"lines": lines, "pos_end": log_file.tell(), "pos_start": pos_start, "num_found": num_found}
def addLogStreamer(self, stream_id, filter=None):
logger = WsLogStreamer(stream_id, self, filter)
logger.setFormatter(logging.Formatter('[%(asctime)s] %(levelname)-8s %(name)s %(message)s'))
logger.setLevel(logging.getLevelName("DEBUG"))
logging.getLogger('').addHandler(logger)
return logger
@flag.no_multiuser
@flag.admin
def actionConsoleLogStream(self, to, filter=None):
stream_id = to
self.log_streamers[stream_id] = self.addLogStreamer(stream_id, filter)
self.response(to, {"stream_id": stream_id})
@flag.no_multiuser
@flag.admin
def actionConsoleLogStreamRemove(self, to, stream_id):
try:
self.log_streamers[stream_id].stop()
del self.log_streamers[stream_id]
return "ok"
except Exception as err:
return {"error": Debug.formatException(err)}