openstack中的日志由oslo_log统一实现,延续了openstack一贯的封装大法,以十分友好的方式将接口提供给各个组件使用。
context中的TLS
在oslo_context
库的context.log
入口定义了一个TLS线程变量
_request_store = threading.local()
凡是引入该context的都会首先初始化这样一个变量
oslo_context库提供一个接口供调用方更新自己的context oslo_context/context.log#RequestContext
def update_store(self):
"""Store the context in the current thread."""
_request_store.context = self
同时提供这样一个接口获取当前的context实例
def get_current():
"""Return this thread's current context
If no context is set, returns None
"""
return getattr(_request_store, 'context', None)
初始化log
oslo_log/log.py
提供了一个外部接口setup
def setup(conf, product_name, version='unknown'):
"""Setup logging for the current application."""
if conf.log_config_append:
_load_log_config(conf.log_config_append)
else:
_setup_logging_from_conf(conf, product_name, version)
sys.excepthook = _create_logging_excepthook(product_name)
该方法配合oslo_conf库非常优雅的实现了让调用方初始化log。
调用方只需要在配置文件中配置相关的参数,然后在程序启动的时候,调用下该方法,后续就只需调用相应的日志等级方法打印日志self.log.info("xxxx")
下面来说下内部做了哪些初始化
进入setup
中的_setup_logging_from_conf
方法
def _setup_logging_from_conf(conf, project, version):
log_root = getLogger(None).logger
# Remove all handlers
for handler in list(log_root.handlers):
log_root.removeHandler(handler)
logpath = _get_log_file_path(conf)
if logpath:
# On Windows, in-use files cannot be moved or deleted.
if conf.watch_log_file and platform.system() == 'Linux':
from oslo_log import watchers
file_handler = watchers.FastWatchedFileHandler
filelog = file_handler(logpath)
elif conf.log_rotation_type.lower() == "interval":
file_handler = logging.handlers.TimedRotatingFileHandler
when = conf.log_rotate_interval_type.lower()
interval_type = LOG_ROTATE_INTERVAL_MAPPING[when]
# When weekday is configured, "when" has to be a value between
# 'w0'-'w6' (w0 for Monday, w1 for Tuesday, and so on)'
if interval_type == 'w':
interval_type = interval_type + str(conf.log_rotate_interval)
filelog = file_handler(logpath,
when=interval_type,
interval=conf.log_rotate_interval,
backupCount=conf.max_logfile_count)
elif conf.log_rotation_type.lower() == "size":
file_handler = logging.handlers.RotatingFileHandler
maxBytes = conf.max_logfile_size_mb * units.Mi
filelog &#