openstack 中 log模块分析
1 . 所在模块,一般在openstack/common/log.py,其实最主要的还是调用了python中的logging模块;
入口函数在
def setup(product_name, version='unknown'):
"""Setup logging."""
if CONF.log_config_append:
_load_log_config(CONF.log_config_append)
else:
_setup_logging_from_conf(product_name, version)
sys.excepthook = _create_logging_excepthook(product_name)
如果配置文件中设置了log_config_append,log_config_append 就是logging的配置,形式如下面这样的:
在函数_load_log_config中实现:
def _load_log_config(log_config_append):
try:
logging.config.fileConfig(log_config_append,
disable_existing_loggers=False)
except moves.configparser.Error as exc:
raise LogConfigError(log_config_append, str(exc))
LogConfigError是一个自定义的Exception,也在log.py中;
如果没有设置log_config_append,则通过_setup_logging_from_conf函数来进行log的设置;
508 log_root = getLogger(None).logger
509 for handler in log_root.handlers:
510 log_root.removeHandler(handler)
511
512 if CONF.use_syslog:
513 facility = _find_facility_from_conf()
514 # TODO(bogdando) use the format provided by RFCSysLogHandler
515 # after existing syslog format deprecation in J
516 if CONF.use_syslog_rfc_format:
517 syslog = RFCSysLogHandler(address='/dev/log',
518 facility=facility)
519 else:
520 syslog = logging.handlers.SysLogHandler(address='/dev/log',
521 facility=facility)
522 log_root.addHandler(syslog)
523
524 logpath = _get_log_file_path()
525 if logpath:
526 filelog = logging.handlers.WatchedFileHandler(logpath)
527 log_root.addHandler(filelog)
528
529 if CONF.use_stderr:
530 streamlog = ColorHandler()
531 log_root.addHandler(streamlog)
532
533 elif not logpath:
534 # pass sys.stdout as a positional argument
535 # python2.6 calls the argument strm, in 2.7 it's stream
536 streamlog = logging.StreamHandler(sys.stdout)
537 log_root.addHandler(streamlog)
538
539 if CONF.publish_errors:
540 handler = importutils.import_object(
541 "openstack.common.log_handler.PublishErrorsHandler",
542 logging.ERROR)
543 log_root.addHandler(handler)
544
545 datefmt = CONF.log_date_format
546 for handler in log_root.handlers:
547 # NOTE(alaski): CONF.log_format overrides everything currently. This
548 # should be deprecated in favor of context aware formatting.
549 if CONF.log_format:
550 handler.setFormatter(logging.Formatter(fmt=CONF.log_format,
551 datefmt=datefmt))
552 log_root.info('Deprecated: log_format is now deprecated and will '
553 'be removed in the next release')
554 else:
555 handler.setFormatter(ContextFormatter(project=project,
556 version=version,
557 datefmt=datefmt))
558
559 if CONF.debug:
560 log_root.setLevel(logging.DEBUG)
561 elif CONF.verbose:
562 log_root.setLevel(logging.INFO)
563 else:
564 log_root.setLevel(logging.WARNING)
565
566 for pair in CONF.default_log_levels:
567 mod, _sep, level_name = pair.partition('=')
568 level = logging.getLevelName(level_name)
569 logger = logging.getLogger(mod)
570 logger.setLevel(level)
508~510 行;首先取得root logger,在logging中,有个默认的rootlogger,任何其他的logger都是这个rootlogger的继承,然后将handler清空,logger可以设置handler,handler是负责将传给logger的信息显示出来的,如显示到stdout,输出到文件等等;
512~522 行,是否写系统的syslog,一般linux 是/dev/log, mac是/var/run/syslog
524到527行,_get_log_file_path函数取得log path,实际上就是判断conf中是否有设置conf.log_file和conf.log_dir;
watchedfilehandler是将log信息输出到文件,watched的具体含义是当发现输出到文件有变化(A file is deemed to have changed if its device or inode have changed),当发现文件有变化的时候,
会将之前的文件流关闭,文件会再一次用一个新的文件流打开;这个在使用log rotation机制的时候是有用的。
529到531行,如果设置了conf.stderr,,通过ColorHandler来进行
533到537行,如果没有设置logpath, 那么stream handler(标准输出)加入到root log里面;
539到543行,如果设置了publish_errors,则调用publisherrorhandler
22 class PublishErrorsHandler(logging.Handler):
23 def emit(self, record):
24 if ('openstack.common.notifier.log_notifier' in
25 cfg.CONF.notification_driver):
26 return
27 notifier.api.notify(None, 'error.publisher',
28 'error_notification',
29 notifier.api.ERROR,
30 dict(error=record.getMessage()))
publisherrorhandler重写了emit方法,将log信息用notifier发送出去;
545 到557行对log的格式进行设置的部分;
559 到 564 在DEBUG < INFO < WARNING 之间选择一个,作为rootlogger的log level,其他的log如果没有单独设置level,会默认继承rootLogger的level;DEBUG和VERBOSE可以通过配置文件进行配置;
566,570可以通过CONF./default_log_levels分别针对不同的模块进行不同的level级别的设置;
setup函数基本分析完毕,可以如下使用setup函数;
from higgs.agent.common import config
config.setup_logging(cfg.CONF)
但一般在开始的常用方法为
from openstack.common import log as logging
LOG = logging.getLogger(__name__)
这个时候其实时调用openstack/common/log.py中的ContextAdapter类;
ContextAdapter类继承了BaseLoggerAdapter类继承于logging.LoggerAdapter类;LoggerAdapter的作用主要是
可以允许你在打印日志时,对日志做一些统一的处理,加入一些上下文信息(contextual information),例如在一个网络应用程序里面,你很有可能想在log中包含一些客户端信息
(比如客户端的username,ipaddress等)。
LoggerAdapter的实现方式更像是一个代理或者适配器,实例化一个LoggerAdapter的时候,你需要传递一个Logger实例和一个dict-like object包含你的上下文信息,然后,LoggerAdapter也要info、debug、
error、critical等方法,并且他们的函数签名与Logger本身的签名是一样的,然后在LoggerAdapter所做的事情就类似于下面的片段;
def debug(self, msg, *args, **kwargs):
"""Delegate a debug call to the underlying logger,
after adding contextual information from this adapter instance."""
msg, kwargs =self.process(msg, kwargs)
self.logger.debug(msg, *args, **kwargs)
首先调用process方法对参数进行一定的处理,然后再将处理后的参数传给底层的logger进行调用;
在openstack里面主要是为了在log中加入了一些project、version等信息;
还有一个LazyLogger,延迟加载的logger;
openstack 中 log模块分析的更多相关文章
- 【转】Openstack中oslo_config模块学习
OpenStack的项目貌似越来越多了,在Grizzly版之前,每个项目都得实现一套处理配置文件的代码.在每个项目的源码中基本上都可以找到openstack/common/cfg.py,inipars ...
- Android架构分析之LOG模块
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本:2.3.7_r1 Linux内核版本:android-goldfish-2.6.29 Andro ...
- frp源码剖析-frp中的log模块
前言&引入 一个好的log模块可以帮助我们排错,分析,统计 一般来说log中需要有时间.栈信息(比如说文件名行号等),这些东西一般某些底层log模块已经帮我们做好了.但在业务中还有很多我们需要 ...
- nodejs中相互引用(循环引用)的模块分析
话不多少,直接上源码吧: modA.js: module.exports.test = 'A'; const modB = require('./05_modB'); console.log( 'mo ...
- Openstack中RabbitMQ RPC代码分析
在Openstack中,RPC调用是通过RabbitMQ进行的. 任何一个RPC调用,都有Client/Server两部分,分别在rpcapi.py和manager.py中实现. 这里以nova-sc ...
- 使用Python中的log模块将loss输出到终端与保存到文件
记得之前对深度学习中得loss输出,经常自己会将输出流重新定向到一个文件中, 比如 python main.py > & | tee log.txt 对于caffe这种c++框架而言,用 ...
- 探索 OpenStack 之(14):OpenStack 中 RabbitMQ 的使用
本文是 OpenStack 中的 RabbitMQ 使用研究 两部分中的第一部分,将介绍 RabbitMQ 的基本概念,即 RabbitMQ 是什么.第二部分将介绍其在 OpenStack 中的使用. ...
- Multipath在OpenStack中的faulty device的成因及解决(part 1)
| 版权:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.如有问题,可以邮件:wangxu198709@gmail.com 简介: Multip ...
- 【转】python模块分析之logging日志(四)
[转]python模块分析之logging日志(四) python的logging模块是用来写日志的,是python的标准模块. 系列文章 python模块分析之random(一) python模块分 ...
随机推荐
- 谈谈HttpUrlConnection与DefaultHttpClient一些区别
HttpClient封装的很庞大,很复杂,你必须按照,他封装的思想去使用它,导致它很不灵活. 相比之下,HttpUrlConnection很轻巧,很方便,很灵活. HttpClient对于数据上面的封 ...
- android 内存泄露之jni local reference table overflow (max=512)
在android项目中要实现一个需求 为了性能的要求只能用c代码来实现功能. 这样就牺牲了java跨平台性. 通过加载.so的方式,把用c实现的模块集成到app中. android提供jni层,作为一 ...
- Compound Interest Calculator4.0
Compound Interest Calculator4.0 1.团队协作准备:每个同学在github上完成FORK,COMMENT(学号后三位+姓名),PR,MERGE的过程. 2.你的RP由你的 ...
- python与unicode
Unicode是一种在计算机上使用的字符编码,是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言.跨平台进行文本转换.处理的要求. Uni ...
- SAP本地文件策略(导EXCEL选择拒绝后处理)
导出EXCEL意外选择了拒绝+记住选择,这样的话在本地电脑就导不出文件了,如下图: 解决办法有2个: 1,修改导出文件的本地策略 :Alt+F12 ->选项->安全性->安全设置-& ...
- SQL数据库第一部分
数据库:程序用来存取数据的 ACCESS:自带,比较小,不是很专业 SQL Server:主要用在.NET语言中,比较专业.微软开发 MYSQL:主要用在PHP语言中,比SQL server体积比较小 ...
- perl 正则匹配代码
36 chomp $line; 37 my @vec = split /\t/, $line; 38 my @vec2 = ($vec[1]=~/[a-z]+/g); 39 ...
- return false取消手机移动端的默认设置
想做一个语音界面,当长按语音按钮的时候,总会出现移动端什么复制粘贴菜单.然后在JS中加入return false后就消失了,感觉好神奇哦~
- oracle表分区【转】
摘要:在大量业务数据处理的项目中,可以考虑使用分区表来提高应用系统的性能并方便数据管理,本文详细介绍了分区表的使用. 在大型的企业应用或企业级的数据库应用中,要处理的数据量通常可以达到几十 ...
- 关于linux的磁盘管理
普通的做法就是检索文件的时间,并使用rm进行删除. 另外有一种做法,可以通过检索inode,进一步进行文件的删除. 下面的文章为摘录,帮助了解inode: 文件名 -> inode -> ...