我有一个想要添加日志记录的网络应用程序(但我觉得这更普遍适用)。大多数 HTTP 请求不需要记录,但某些操作会导致生成外部调用,这些都应该记录下来。
单个传入的 HTTP 请求可以启动 0 个或多个后端请求,我想记录这些后端请求的来源,以便可以追溯到原始调用。
我天真的方法是在整个调用链中添加一个“客户端 ID”,如下所示:
def do_something_log_worthy(client_id, parameters):
logger.info("{source}: caused something to be done".format(client_id))
# something
def generic_intermediate_func_1(client_id, parameters):
if unusual_case(parameters):
do_something_log_worthy(client_id, parameters)
# ... some more levels generic wrappers
def http_request(client_id, request):
# Here I get the actual client ID
generic_intermediate_func_N(client_id, "foo", "bar")
虽然这可行,但我想避免client_id
在整个调用链中添加。由于大多数函数/方法与客户端逻辑无关,因此在那里添加传递参数感觉不对。
另一种方法是使用全局变量来保存“最近的客户端”,但全局变量几乎总是一个不好的选择,尤其是在使用多线程和/或异步代码(我正在使用)时。
有没有解决这个问题的pythonic方法?理想情况下,我想要类似的东西
logger.info("{source}: foobar".format(
call_stack.nearest_frame_decorated_with(some_decorater).get_variable_value("client_id")
)) # all entry-points are decorated with @app.route('/path/to/foo')
但这感觉就像访问“私人”数据。有没有办法以干净的方式完成此任务?
如果有帮助:网络应用程序是用Sanic编写的,这是一个基于 asyncio 的网络框架。记录是使用标准的 python 记录器工具完成的。