logging - 使用 python 日志记录内存使用情况统计信息

  显示原文与译文双语对照的内容
59 0

我在一个项目中使用 python 模块的日志来显示消息。我有自己的项目,它使用一个通用存储库中的模块,因这里我不想更改代码中的任何日志。

但是,内存使用似乎是我的程序中的一个问题,所以我想记录每个日志语句中的内存使用情况。

YYYY-MM-DD HH:MM:SS,mmm NAME LEVEL MemTotal:#M,Swap:#M MESSAGE

是否有直接的方法使用日志记录模块进行这里操作?

我想走的方法是使用一个过滤器来添加上下文信息( cf 。http://docs.python.org/howto/logging-cookbook.html#filters-contextual of ),但似乎没有一种方法可以以将这里筛选器添加到所有的级别和记录器的所有实例。文档建议将过滤器添加到处理程序而不是记录器,因为否则它不会在外部模块中使用过滤器。以最明显的方式来做( 创建处理程序,添加筛选器,然后将处理程序附加到 root 记录器) 却给了我意想不到的行为。我完全没有输出,也没有错误消息,或者者( 。第一次使用basicConfig时) 得到了正确的行为,除了它给出错误信息。我怀疑最后一个案例中,我得到两个处理程序,它的中一个正常工作,另一个错误。

到目前为止,我已经经提出了以下解决方案,我认为这不是很优雅的( 感谢 https://stackoverflow.com/a/938800/819110 ) 。最糟糕的是,我必须手工从记录器中提取处理程序,并将过滤器添加到它中。我似乎无法将过滤器添加到配置文件中,这将更加方便。然而,这种方法似乎是( 在Linux上)的工作,尽管我怀疑应该有更直接的方法来执行这里操作。

import logging
import external_module
class MemuseFilter(logging.Filter):
 def filter(self, record):
""" This function overrides logging.Filter, adds memuse as a field
""" 
 record.memuse = self.str_mem()
 return True
 # Following code from https://stackoverflow.com/a/938800/819110: 
 _proc_status = '/proc/%d/status' % os.getpid()
 _scale = {'kB': 1024.0, 'mB': 1024.0*1024.0,
 'KB': 1024.0, 'MB': 1024.0*1024.0}
 def _VmB(self,VmKey):
"""Private.
"""
 # get pseudo file/proc/<pid>/status
 try:
 t = open(self._proc_status)
 v = t.read()
 t.close()
 except:
 return 0.0 # non-Linux?
 # get VmKey line e.g. 'VmRSS: 9999 kBn.. .'
 i = v.index(VmKey)
 v = v[i:].split(None, 3) # whitespace
 if len(v) <3:
 return 0.0 # invalid format?
 # convert Vm value to bytes
 return float(v[1]) * self._scale[v[2]]
 def memory(self,since=0.0):
"""Return memory usage in bytes.
"""
 return self._VmB('VmSize:') - since
 def swapsize(self,since=0.0):
"""Return swap size in bytes.
"""
 return self._VmB('VmSwap:') - since
 def byte_to_mb(self,byte):
"""return size in MB (being lazy)
"""
 return byte/(1024*1024)
 def str_mem(self):
"""Return a string with the total memuse and swap size in MB
"""
 return"MemTotal:%.0fM,Swap:%.0fM"%(
 self.byte_to_mb(self.memory()),self.byte_to_mb(self.swapsize()) )
if __name__ == '_main__':
 logging.config.fileConfig('logging.conf') # Get basic config
 log = logging.getLogger('') # Get root logger
 f = MemuseFilter() # Create filter
 log.handlers[0].addFilter(f) # The ugly part:adding filter to handler
 log.warning("Foo")
 function_from_module_using_logging()

external_module 读取类似于以下内容的内容:

log = logging.getLogger(__name__)
def function_from_module_using_logging():
 log.warning("Bar")

logging.conf 就像这样:

[loggers]
keys=root
[handlers]
keys=fileHandler
[formatters]
keys=memuseFormatter
[logger_root]
level=DEBUG
handlers=fileHandler
[handler_fileHandler]
class=FileHandler
level=DEBUG
formatter=memuseFormatter
args=('some.log','w')
[formatter_memuseFormatter]
format=%(asctime)-15s %(name)-5s %(levelname)-8s %(memuse)-22s %(message)s
datefmt=

更好的解决方案是最受欢迎的 !

编辑:引用了错误的问题。

时间:原作者:0个回答

59 2

如果使用 python 2.7或者更高版本,那么可以使用 dictConfig() 插件,它支持配置中的过滤器。如果使用早期版本的python,可以使用 logutils 项目来提供功能。如果你不希望 logutils的外部依赖,你可以将 dictConfig() 内容从那里复制到你自己的代码( 如 Django 所做的/) 中。

原作者:
...