From 557651b06ee7336079a114bead7d95e3d9648afa Mon Sep 17 00:00:00 2001 From: Alex Bsk Date: Mon, 9 Oct 2023 01:02:08 +0300 Subject: [PATCH] sa logging minor improvements (#808) * sa logging minor improvements * sa, renaming variables * adding except OSError, ValueError to logging_conf * + except LookupError * adding short_names: geventWs, wsgiTh * adding test for log func --- py4web/server_adapters.py | 180 +++++++++++++++++++++++++++----------- 1 file changed, 129 insertions(+), 51 deletions(-) diff --git a/py4web/server_adapters.py b/py4web/server_adapters.py index 1b0953054..2c9370483 100644 --- a/py4web/server_adapters.py +++ b/py4web/server_adapters.py @@ -1,5 +1,6 @@ import logging import os +import sys import ssl from ombott.server_adapters import ServerAdapter @@ -11,11 +12,21 @@ __all__ = [ "gevent", - "geventWebSocketServer", - "wsgirefThreadingServer", + "geventWebSocketServer", "geventWs", # short_name + "wsgirefThreadingServer", "wsgiTh", # short_name "rocketServer", ] + wsservers_list +# ---------------------- utils ----------------------------------------------- + +# export PY4WEB_LOGS=/tmp # export PY4WEB_LOGS= +def get_log_file(): + log_dir = os.environ.get("PY4WEB_LOGS", None) + log_file = os.path.join (log_dir, 'server-py4web.log') if log_dir else None + if log_file: + print(f"log_file: {log_file}") + return log_file + def check_level(level): @@ -44,26 +55,53 @@ def check_level(level): ) -def logging_conf(level, log_file="server-py4web.log"): - - # export PY4WEB_LOGS=/tmp # set log_file directory - - log_dir = os.environ.get("PY4WEB_LOGS", None) +def logging_conf(level=logging.WARN, logger_name=__name__, test_log = False): - log_param = { - "format":"%(threadName)s | %(message)s", - "level":check_level(level), - } + log_file = get_log_file() + log_to = dict() - if log_dir: - h = logging.FileHandler( - os.path.join( log_dir, log_file), + if log_file: + if sys.version_info >= (3, 9): + log_to["filename" ] = log_file + log_to["filemode" ] = "w" + log_to["encoding"] = "utf-8" + else: + h = logging.FileHandler( + log_file, mode = "w", encoding = "utf-8" ) - log_param.update( {"handlers": [h]} ) + log_to.update( {"handlers": [h]} ) + + short_msg = "%(message)s > %(threadName)s > %(asctime)s.%(msecs)03d" + #long_msg = short_msg + " > %(funcName)s > %(filename)s:%(lineno)d > %(levelname)s" + + time_msg = '%H:%M:%S' + #date_time_msg = '%Y-%m-%d %H:%M:%S' + + try: + logging.basicConfig( + format=short_msg, + datefmt=time_msg, + level=check_level(level), + **log_to, + ) + except ( OSError, LookupError, KeyError, ValueError ) as ex: + print(f"{ex}, {__file__}") + print(f'cannot open {log_file}') + logging.basicConfig( format="%(message)s", level=check_level(level),) - logging.basicConfig(**log_param) + if logger_name is None: + return None + + log = logging.getLogger("SA:" + logger_name) + log.propagate = True + + if test_log: + for func in (log.debug, log.info, log.warn, log.error, log.critical, ) : + func('func: ' + func.__name__ ) + + return log def get_workers(opts, default=10): @@ -72,12 +110,12 @@ def get_workers(opts, default=10): except KeyError: return default +# ---------------------- servers ----------------------------------------------- def gevent(): - # gevent version 22.10.2 + # gevent version 23.9.1 import threading - from gevent import local, pywsgi # pip install gevent if not isinstance(threading.local(), local.local): @@ -90,23 +128,14 @@ def gevent(): # ./py4web.py run apps -s gevent --watch=off --host=192.168.1.161 --port=8443 --ssl_cert=server.pem -L 0 class GeventServer(ServerAdapter): - def run(self, handler): + def run(self, app_handler): + logger = "default" - logger = "default" # not None - from gevent doc if not self.quiet: - - logger = logging.getLogger("gevent") - log_dir = os.environ.get("PY4WEB_LOGS", None) - fh = ( - logging.FileHandler(None) - if not log_dir - else ( - logging.FileHandler(os.path.join(log_dir, "server-py4web.log")) - ) + logger = logging_conf( + self.options["logging_level"], "gevent", ) - logger.setLevel(check_level(self.options["logging_level"])) - logger.addHandler(fh) - logger.addHandler(logging.StreamHandler()) + #logger.addHandler(logging.StreamHandler()) certfile = self.options.get("certfile", None) @@ -124,7 +153,7 @@ def run(self, handler): server = pywsgi.WSGIServer( (self.host, self.port), - handler, + app_handler, log=logger, error_log=logger, **ssl_args @@ -153,14 +182,14 @@ def geventWebSocketServer(): # -sSv https://192.168.1.161:9000/ class GeventWebSocketServer(ServerAdapter): - def run(self, handler): - logger = "default" # not None !! from gevent doc + def run(self, app_handler): + logger = "default" + if not self.quiet: - logging_conf( - self.options["logging_level"], + logger = logging_conf( + self.options["logging_level"], "gevent-ws", ) - logger = logging.getLogger("gevent-ws") - + certfile = self.options.get("certfile", None) ssl_args = ( @@ -174,7 +203,7 @@ def run(self, handler): server = pywsgi.WSGIServer( (self.host, self.port), - handler, + app_handler, handler_class=WebSocketHandler, log=logger, error_log=logger, @@ -184,7 +213,7 @@ def run(self, handler): server.serve_forever() return GeventWebSocketServer - +geventWs=geventWebSocketServer def wsgirefThreadingServer(): # https://www.electricmonk.nl/log/2016/02/15/multithreaded-dev-web-server-for-the-python-bottle-web-framework/ @@ -195,14 +224,14 @@ def wsgirefThreadingServer(): from wsgiref.simple_server import WSGIRequestHandler, WSGIServer, make_server class WSGIRefThreadingServer(ServerAdapter): - def run(self, app): + def run(self, app_handler): - if not self.quiet: + self.log = None - logging_conf( - self.options["logging_level"], + if not self.quiet: + self.log = logging_conf( + self.options["logging_level"], "wsgiref", ) - self.log = logging.getLogger("WSGIRef") self_run = self # used in internal classes to access options and logger @@ -277,7 +306,7 @@ def log_message(self, format, *args): ) self_run.log.info(msg) - handler_cls = self.options.get("handler_class", LogHandler) + #handler_cls = self.options.get("handler_class", LogHandler) server_cls = Server if ":" in self.host: # Fix wsgiref for IPv6 addresses. @@ -288,11 +317,11 @@ class ServerClass(Server): server_cls = ServerClass - srv = make_server(self.host, self.port, app, server_cls, handler_cls) + srv = make_server(self.host, self.port, app_handler, server_cls, LogHandler ) # handler_cls) srv.serve_forever() return WSGIRefThreadingServer - +wsgiTh=wsgirefThreadingServer def rocketServer(): try: @@ -301,7 +330,7 @@ def rocketServer(): from .rocket3 import Rocket3 as Rocket class RocketServer(ServerAdapter): - def run(self, app): + def run(self, app_handler): if not self.quiet: @@ -323,7 +352,56 @@ def run(self, app): else (self.host, self.port) ) - server = Rocket(interface, "wsgi", dict(wsgi_app=app)) + server = Rocket(interface, "wsgi", dict(wsgi_app=app_handler)) server.start() return RocketServer + + +""" +# how to write to server-adapters.log from controllers.py +# cp -a _scaffold test-salog + +import sys +import logging +from .common import logger +from .settings import APP_NAME +from threading import Lock + + +_srv_log=None +def log_info(mess, dbg=True, ): + def salog(pat='SA:'): + global _srv_log + if _srv_log and isinstance( _srv_log, logging.Logger ): + return _srv_log + hs= [e for e in logging.root.manager.loggerDict if e.startswith(pat) ] + if len(hs) == 0: + return logger + + sa_lock = Lock() + with sa_lock: + _srv_log = logging.getLogger(hs[0]) + + return _srv_log + + dbg and salog().info(str(mess)) + +log_warn=log_info +log_debug=log_info + +log_warn('0'* 30 + ' ' +APP_NAME) + +@action("index") +@action.uses("index.html", auth, T) +def index(): + + log_warn('7'* 30 + ' ' +APP_NAME) + log_info('9'* 30 + ' ' +APP_NAME) + + user = auth.get_user() + message = T("Hello {first_name}").format(**user) if user else T("Hello") + actions = {"allowed_actions": auth.param.allowed_actions} + return dict(message=message, actions=actions) + +"""