Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sa logging minor improvements #808

Merged
merged 6 commits into from
Oct 8, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 129 additions & 51 deletions py4web/server_adapters.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
import os
import sys
import ssl

from ombott.server_adapters import ServerAdapter
Expand All @@ -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):

Expand Down Expand Up @@ -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):
Expand All @@ -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):
Expand All @@ -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)

Expand All @@ -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
Expand Down Expand Up @@ -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 = (
Expand All @@ -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,
Expand All @@ -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/
Expand All @@ -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

Expand Down Expand Up @@ -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.
Expand All @@ -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:
Expand All @@ -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:

Expand All @@ -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)

"""