【发布时间】:2013-12-13 16:56:51
【问题描述】:
我的主管希望我解决“日志中的并发问题”,他的意思是我们生成的日志文件在不同文件的开头/结尾有混合时间戳。那就是:
-
第一个日志文件末尾有:
[03/Dec/2013:13:55:19]--------------------- [03/Dec/2013:13:55:20]--------------------- [03/Dec/2013:13:55:20]--------------------- -
第二个文件开始于:
[03/Dec/2013:13:40:16]--------------------- [03/Dec/2013:13:40:16]--------------------- [03/Dec/2013:13:40:23]---------------------
我们使用旋转文件处理程序,第二个文件应该有从第一个文件结束时开始的时间戳,但它没有。如何在文件轮换期间使时间戳以正确的顺序刷新到日志中?
"Logger" 类,只使用 Python 日志模块:
class logger:
def __init__(self, logger_name='prod'):
self.error_logger = logging.getLogger(logger_name+'_error')
def error(self, msg='', level='error'):
if msg:
getattr(self.error_logger,level)(msg)
def log(self, msg='', level='info'):
if msg:
getattr(self.error_logger,level)(msg)
日志格式:
class our_formatter(logging.Formatter):
def find_topmost_stack_frame(self):
i = 0
stack = []
while True:
try:
fr = sys._getframe(i)
if fr.f_code.co_name == '__call__':
break
stack.append(fr)
except:
break
i += 1
return "%s:%s" % (stack[-4].f_code.co_filename, stack[-4].f_lineno)
def format(self, record):
try:
if record.done:
return record.msg
except:
record.done = False
rtime = time.strftime("%d/%b/%Y:%H:%M:%S", time.localtime(record.created))
from tools.user_management import user_pack
email = user_pack().get_email()
if record.levelno > 20:
if email:
record.msg = '[%s][user:%s][%s] {%s} %s' % ( rtime, email, record.levelname, self.find_topmost_stack_frame(),
record.msg)
else:
record.msg = '[%s][%s] {%s} %s' % ( rtime, record.levelname, self.find_topmost_stack_frame(), record.msg)
else:
if email:
record.msg = '[%s][user:%s][%s] %s' % ( rtime, email, record.levelname, record.msg)
else:
record.msg = '[%s][%s] %s' % ( rtime, record.levelname, record.msg)
record.done = True
return logging.Formatter.format(self, record)
最后是记录器的配置:
log = cherrypy.log
log.error_file = None
maxBytes = getattr(log, "rot_maxBytes", 10000000)
backupCount = getattr(log, "rot_backupCount", 1000)
fname = getattr(log, "rot_error_file", "logs/error.log")
logger = logging.getLogger()
logger.setLevel(0)
# Make a new RotatingFileHandler for the error log.
h = logging.handlers.RotatingFileHandler(fname, 'a', maxBytes, backupCount)
h.setFormatter(rest_formatter())
log.error_log.addHandler(h)
# set up custom ReST logger
logger = logging.getLogger("rest_error")
logger.addHandler(h)
# set up our custom logger
ha = logging.handlers.RotatingFileHandler(fname, 'a', maxBytes, backupCount)
ha.setFormatter(our_formatter())
logger = logging.getLogger("prod_error")
logger.addHandler(ha)
应用程序是多线程的,但是内置的日志记录应该是线程安全的(我今天正在阅读它的某些部分代码,它肯定使用了一些锁)。
问题只是在一个文件的开头和前一个文件的结尾之间(而不是在中间),所以我认为这是记录器保留文件空间的一些情况,但是我知道它仍然应该保持正确的顺序,因为每个指定的文件处理程序应该只有一个记录器实例。
我们有很多日志记录。很多我的意思是每秒通常有 10 多个日志。
【问题讨论】:
-
我们需要查看您的一些代码,才能开始了解如何解决您的问题。
-
如何设置日志。是否有多个进程/线程?
-
为什么不同的处理程序写入同一个文件?
-
@J.F.Sebastian 我认为这是因为我们不想拥有太多类型的日志文件。无论如何-cherrypy 本身几乎没有将任何内容记录到日志文件中(只有启动/重新启动序列)。还有rest_error——初始化后我还没有看到它在任何地方使用过。
-
@J.F.Sebastian - 更正,我刚刚检查过,实际上也使用了其余的记录器。但是,有时仅在来自 rest_logger 的日志中会出现那些排序不正确的时间戳的问题。不知道是不是cherrypy线程在接收请求时分派导致的某种问题。
标签: python logging timestamp cherrypy