我有一个Flask应用程序,其中包含我根据标准Python记录器编写的日志记录系统。
我希望每个页面视图都有一个唯一的ID,因此我可以跟踪整个过程并检查记录的错误和过早的结束。
我尝试的第一件事就是将唯一ID创建者放入__init__中,用于记录器对象。结果是所有请求都具有相同的视图。我将创建唯一ID的位置移动到某个方法,这改善了这种情况 - 日志中出现了多个ID,所有内容似乎都正常工作。
但是,有时似乎有两个请求使用相同的记录器对象。似乎当一个请求正在运行时,另一个请求启动并运行ID生成方法。然后第一个请求也开始使用新ID ...
22:04:31 - MPvzGNAelE : in content
22:04:31 - MPvzGNAelE : in parse options
22:04:31 - MPvzGNAelE : finished parse options
22:04:31 - MPvzGNAelE : about to query API for user info. user id : 7401173, resource id: 59690
#the following is where the 2nd requests starts
22:04:31 - SbEOjmbFSa : in frame initial
22:04:31 - SbEOjmbFSa : in frame 2 - cleaned IDs are 1114 127059932
22:04:31 - SbEOjmbFSa : in parse options
22:04:31 - SbEOjmbFSa : finished parse options
22:04:31 - SbEOjmbFSa : in frame finishing - for 1114 127059932
#the following is the first request continuing with the new ID
22:04:31 - SbEOjmbFSa : api user info status is success
22:04:31 - SbEOjmbFSa : user_id is 5549565, user name is joe_spryly
22:04:31 - SbEOjmbFSa : config[data_source] is 0
22:04:31 - SbEOjmbFSa : api seems to be working, so going to retrieve items for 59690 7401173
22:04:31 - SbEOjmbFSa : getting items from API for 59690 7401173
这是我的日志对象代码......
class AS_Log(object):
def __init__(self):
self.log=logging.getLogger('aman_log')
logging.basicConfig(filename='amanset_log',level=logging.DEBUG)
def generate_id(self):
from random import choice
import string
chars=string.letters+string.digits
self.log_id=''.join([choice(chars) for i in range(10)])
def format_date(self,timestamp):
return datetime.fromtimestamp(timestamp).strftime('%m-%d-%y %H:%M:%S')
def log_msg(self,message):
self.log.debug('{0} - {1} : {2}'.format(self.format_date(time()),self.log_id,message))
我在烧瓶应用程序中启动日志,如
as=AS_Log()
然后按照
的请求调用generate_id@app.route('/<resource_id>/<user_id>/')
def aman_frame(resource_id,user_id):
as.generate_id()
return amanset_frame(resource_id,user_id)
然后使用amanset_frame函数中的日志。
我有一些想法,这是Flask中的相关应用程序上下文,但我不明白如何使用它来解决这个问题。我是否使用app_context(),若然,怎么做?
答案 0 :(得分:2)
最终,这是因为在多个执行上下文中更改了共享as.log_id
字段(很可能是线程,但如果as
在共享父解释器中,它可能是greenlet甚至是子进程,如同某些uwsgi / mod_wsgi设置)。
request-1 --> mutates log_id --> does ... work ... --> response
request-2 --> mutates log_id --> does ... work ... --> response
修复是为记录器使用正确的thread-local,因此每个执行线程都会创建一个新的记录器。 Werkzeug有LocalProxy,这使得管理也更容易。