我有一个Web应用程序,我想添加日志记录(但我觉得这更普遍适用)。大多数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的Web框架。使用标准的python记录器工具完成日志记录。
答案 0 :(得分:0)
可能不是你需要的,但是从以前的工作中我记得中间件添加请求uuid和响应uuid来记录api调用。
您可以编写中间件,在链的开头为您的请求添加唯一ID,然后传递请求,就像sanic一样,路由到端点函数/方法。
我记得曾经看过的弹性搜索日志:
requests-2018-01-01 node
{
"timestamp": "Sun Jan 01 16:13:39 SAST 2018",
"payload": "{'user_id':'abcdef', 'action': 'calculate_balance'}
"request_id": "03cfd743661f07975fa2f1220c5194cbaff48451",
"status": 500
}
响应-2018年1月1日
{
"timestamp": "Sun Jan 01 16:13:39 SAST 2018",
"message": "Internal Server Error"
"request_id": "03cfd743661f07975fa2f1220c5194cbaff48451",
"response_id": "3330b4373640f9e4604991e73c7e86bfd8da2dc3",
"status": 500
}
它可以轻松查看日志,因为您可以按内部日志,请求日志,响应日志等中的请求ID进行搜索。
希望有帮助吗?