From 028b68b38a5e9b04c3107076953e6095bdbff507 Mon Sep 17 00:00:00 2001 From: Rohit Karajgi Date: Wed, 24 Jul 2013 05:43:23 -0700 Subject: [PATCH] Add logger for websockify Replace print() statement logging with python logging Addresses issue #87 --- websockify/log.py | 23 ++++++++++++++++++++ websockify/websocket.py | 41 +++++++++++++++++++----------------- websockify/websocketproxy.py | 14 ++++++++---- 3 files changed, 55 insertions(+), 23 deletions(-) create mode 100644 websockify/log.py diff --git a/websockify/log.py b/websockify/log.py new file mode 100644 index 0000000..aad2c80 --- /dev/null +++ b/websockify/log.py @@ -0,0 +1,23 @@ +''' +Logging control and utilities +Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3) +''' + +import logging +import sys + + +def _add_default_handler(logger): + handler = logging.StreamHandler(sys.stdout) + handler.setFormatter(logging.Formatter( + '%(asctime)s %(levelname)s %(name)s %(message)s')) + logger.addHandler(handler) + + +def get_logger(name="websockify"): + rootlogger = logging.getLogger(name) + if rootlogger.level == logging.NOTSET: + rootlogger.setLevel(logging.WARN) + if not rootlogger.handlers: + _add_default_handler(rootlogger) + return rootlogger diff --git a/websockify/websocket.py b/websockify/websocket.py index d37fa71..4e8d8ed 100644 --- a/websockify/websocket.py +++ b/websockify/websocket.py @@ -20,6 +20,10 @@ import os, sys, time, errno, signal, socket, traceback, select import array, struct from base64 import b64encode, b64decode +from websockify import log + +LOG = log.get_logger() + # Imports that vary by python version # python 3.0 differences @@ -58,7 +62,7 @@ for mod, msg in [('numpy', 'HyBi protocol will be slower'), globals()[mod] = __import__(mod) except ImportError: globals()[mod] = None - print("WARNING: no '%s' module, %s" % (mod, msg)) + LOG.warning("no '%s' module, %s" % (mod, msg)) if multiprocessing and sys.platform == 'win32': # make sockets pickle-able/inheritable import multiprocessing.reduction @@ -133,25 +137,25 @@ Sec-WebSocket-Accept: %s\r raise Exception("Module 'resource' required to daemonize") # Show configuration - print("WebSocket server settings:") - print(" - Listen on %s:%s" % ( + LOG.info("WebSocket server settings:") + LOG.info(" - Listen on %s:%s" % ( self.listen_host, self.listen_port)) - print(" - Flash security policy server") + LOG.info(" - Flash security policy server") if self.web: - print(" - Web server. Web root: %s" % self.web) + LOG.info(" - Web server. Web root: %s" % self.web) if ssl: if os.path.exists(self.cert): - print(" - SSL/TLS support") + LOG.info(" - SSL/TLS support") if self.ssl_only: - print(" - Deny non-SSL/TLS connections") + LOG.info(" - Deny non-SSL/TLS connections") else: - print(" - No SSL/TLS support (no cert file)") + LOG.info(" - No SSL/TLS support (no cert file)") else: - print(" - No SSL/TLS support (no 'ssl' module)") + LOG.info(" - No SSL/TLS support (no 'ssl' module)") if self.daemon: - print(" - Backgrounding (daemon)") + LOG.info(" - Backgrounding (daemon)") if self.record: - print(" - Recording to '%s.*'" % self.record) + LOG.info(" - Recording to '%s.*'" % self.record) # # WebSocketServer static methods @@ -357,14 +361,14 @@ Sec-WebSocket-Accept: %s\r f['payload'] = WebSocketServer.unmask(buf, f['hlen'], f['length']) else: - print("Unmasked frame: %s" % repr(buf)) + LOG.info("Unmasked frame: %s" % repr(buf)) f['payload'] = buf[(f['hlen'] + f['masked'] * 4):full_len] if base64 and f['opcode'] in [1, 2]: try: f['payload'] = b64decode(f['payload']) except: - print("Exception while b64decoding buffer: %s" % + LOG.error("Exception while b64decoding buffer: %s" % repr(buf)) raise @@ -390,7 +394,7 @@ Sec-WebSocket-Accept: %s\r def msg(self, msg): """ Output message with handler_id prefix. """ if not self.daemon: - print("% 3d: %s" % (self.handler_id, msg)) + LOG.info("% 3d: %s" % (self.handler_id, msg)) def vmsg(self, msg): """ Same as msg() but only if verbose. """ @@ -571,7 +575,6 @@ Sec-WebSocket-Accept: %s\r stype = "" ready = select.select([sock], [], [], 3)[0] - if not ready: raise self.EClose("ignoring socket not ready") # Peek, but do not read the data so that we have a opportunity @@ -840,17 +843,17 @@ Sec-WebSocket-Accept: %s\r except KeyboardInterrupt: _, exc, _ = sys.exc_info() - print("In KeyboardInterrupt") + LOG.warning("In KeyboardInterrupt") pass except SystemExit: _, exc, _ = sys.exc_info() - print("In SystemExit") + LOG.warning("In SystemExit") break except Exception: _, exc, _ = sys.exc_info() - self.msg("handler exception: %s" % str(exc)) + LOG.error("handler exception: %s" % str(exc)) if self.verbose: - self.msg(traceback.format_exc()) + LOG.error(traceback.format_exc()) finally: if startsock: diff --git a/websockify/websocketproxy.py b/websockify/websocketproxy.py index 1154d92..7742209 100755 --- a/websockify/websocketproxy.py +++ b/websockify/websocketproxy.py @@ -20,6 +20,12 @@ except: from cgi import parse_qs from urlparse import urlparse +from websockify import log + + +LOG = log.get_logger() + + class WebSocketProxy(websocket.WebSocketServer): """ Proxy traffic to and from a WebSockets client to a normal TCP @@ -86,7 +92,7 @@ Traffic Legend: websocket.WebSocketServer.__init__(self, *args, **kwargs) def run_wrap_cmd(self): - print("Starting '%s'" % " ".join(self.wrap_cmd)) + LOG.info("Starting '%s'" % " ".join(self.wrap_cmd)) self.wrap_times.append(time.time()) self.wrap_times.pop(0) self.cmd = subprocess.Popen( @@ -116,7 +122,7 @@ Traffic Legend: if self.ssl_target: msg += " (using SSL)" - print(msg + "\n") + LOG.info(msg + "\n") if self.wrap_cmd: self.run_wrap_cmd() @@ -142,7 +148,7 @@ Traffic Legend: if (now - avg) < 10: # 3 times in the last 10 seconds if self.spawn_message: - print("Command respawning too fast") + LOG.warning("Command respawning too fast") self.spawn_message = False else: self.run_wrap_cmd() @@ -183,7 +189,7 @@ Traffic Legend: connect=True, use_ssl=self.ssl_target, unix_socket=self.unix_target) if self.verbose and not self.daemon: - print(self.traffic_legend) + LOG.info(self.traffic_legend) # Start proxying try: