python logging 探究
针对python的日志我们慢慢探究,建议有一定python基础再去探究,小白误入
import logging
root = logging.root
print (root is logging.Logger.root)
r = logging.getLogger()
print (r)
#从这我们发现logging 的日志都是从根出发
输出结果:
True
<RootLogger root (WARNING)>
进程已结束,退出代码0
探究python logging的父子关系 主要关系parnet
import logging
l1 = logging.getLogger('t1')
l2 = logging.getLogger('t2')
print (id(l1),id(l2),l1 is l2 )
l3 = logging.getLogger('t3')
print (id(l3))
print (l1.name,l2.name,l3.name)
root = logging.getLogger() #默认为root为根,层级递增
print (1,root.name,type(root),root.parent)
#从这发现parnet的parnet是root
parnet = logging.getLogger('a')
print (2,parnet.name,type(parnet),parnet.parent.name,parnet.parent is root )
#从这发现child的parnet是parnet
child = logging.getLogger('a.b')
print (3,child.name,type(child),child.parent.name,child.parent is parnet )
输出结果:
2349971106256 2349971308304 False
2349970911392
t1 t2 t3
1 root <class 'logging.RootLogger'> None
2 a <class 'logging.Logger'> root True
3 a.b <class 'logging.Logger'> a True
进程已结束,退出代码0
探究python logging的消息级别
import logging
#消息级别,
logging.basicConfig(level=logging.INFO,format="%(asctime)s %(name)s %(threadName)s [%(message)s]") #自定义消息类型,后续回把输出结果放出
logging.basicConfig(level=logging.INFO) #定义消息类型
logging.basicConfig(filename="D:\syslog.txt",filemode='w') #定义输出到文件,并且为w
logging.info('info msg') #发送 info消息
logging.debug('debug msg') #发送 debug消息
logging.warning('warn msg' ) #发送 warn消息
#可以按住ctrl在pycharm 中查看logging类中查看
#消息级别一共有5种
#ERROR = 40
#WARNING = 30
#WARN = WARNING
#INFO = 20
#DEBUG = 10
#NOTSET = 0
输出结果:
2023-02-22 22:44:57,130 root MainThread [info msg]
2023-02-22 22:44:57,130 root MainThread [warn msg]
其实logging中工作的都是handler,所以我们在收集服务日志中直接定义handler
import logging
handler = logging.FileHandler('D:\syslog.txt','w','utf-8') #定义handler日志文件和日志格式以及权限w
handler.setFormatter(logging.WARNING)#定义handler的消息级别只有告警在这个级别之上才会发送
formatter = logging.Formatter('#%(asctime)s <%s(message)s>#') #定义消息类型,acstime是时间格式,,message 是日志消息
print (logging.root.handlers) #查看一下
输出结果:
1 []
那我们现在定义一个logging-handler,其实在抓取服务日志时可以根据条件判断进行输出不同的日志或者保存为不同的文件
import logging
#根log
logging.basicConfig(level=logging.INFO,format="%(asctime)s %(name)s %(threadName)s [%(message)s]")
print (logging.root.handlers)
mylogger = logging.getLogger(__name__)
mylogger.info("my info ")
#定义处理器
handler = logging.FileHandler('D:\syslog.txt','w','utf-8')
handler.setLevel(logging.WARNING)
#定义格式化器
formatter = logging.Formatter('#%(asctime)s <%(message)s>#')
#为处理器定义格式化器
handler.setFormatter(formatter)
#为日志记录器追加处理器
mylogger.addHandler(handler)
mylogger.propagate = False
mylogger.info( 'my in fo 2 ~~~')
mylogger.warning('my warnning 2 ~~~')
mylogger.propagate = True
mylogger.warning('my warnning 3 ~~~')
输出结果:
2023-02-22 22:45:37,227 __main__ MainThread [my info ]
2023-02-22 22:45:37,227 __main__ MainThread [my warnning 3 ~~~]
[<StreamHandler <stderr> (NOTSET)>]
另一种写法,在logging中有现成的handlers库,TimedRotatingFileHandler
我们看一下输出结果
import logging
from logging.handlers import TimedRotatingFileHandler
import time
logging.basicConfig(level=logging.INFO,format='%(asctime)s %(name)s %(threadName)s [%(message)s]') #定义logging的config
print (logging.root.handlers)
mylogger = logging.getLogger(__name__)
handle = TimedRotatingFileHandler('D:\syslog.txt','s',30) #定义handler的file格式
handle.setLevel(logging.INFO) #定义handler 级别
formatter = logging.Formatter('#%(asctime)s <%(message)s>#') #定义handler 输出消息格式
handle.setFormatter(formatter) #定义handler 级别
mylogger.addHandler(handle)##定义handler的file格式
for i in range(20):
time.sleep(1)
mylogger.info("my message {:3} +++ ".format(i))
mylogger.addHandler(handle)
输出结果:
[<StreamHandler <stderr> (NOTSET)>]
2023-02-22 22:45:57,842 __main__ MainThread [my message 0 +++ ]
2023-02-22 22:45:58,852 __main__ MainThread [my message 1 +++ ]
2023-02-22 22:45:59,856 __main__ MainThread [my message 2 +++ ]
2023-02-22 22:46:00,859 __main__ MainThread [my message 3 +++ ]
2023-02-22 22:46:01,865 __main__ MainThread [my message 4 +++ ]
2023-02-22 22:46:02,877 __main__ MainThread [my message 5 +++ ]
2023-02-22 22:46:03,887 __main__ MainThread [my message 6 +++ ]
2023-02-22 22:46:04,896 __main__ MainThread [my message 7 +++ ]
2023-02-22 22:46:05,898 __main__ MainThread [my message 8 +++ ]
2023-02-22 22:46:06,902 __main__ MainThread [my message 9 +++ ]
2023-02-22 22:46:07,917 __main__ MainThread [my message 10 +++ ]
2023-02-22 22:46:08,924 __main__ MainThread [my message 11 +++ ]
2023-02-22 22:46:09,935 __main__ MainThread [my message 12 +++ ]
2023-02-22 22:46:10,942 __main__ MainThread [my message 13 +++ ]
2023-02-22 22:46:11,956 __main__ MainThread [my message 14 +++ ]
2023-02-22 22:46:12,966 __main__ MainThread [my message 15 +++ ]
2023-02-22 22:46:13,978 __main__ MainThread [my message 16 +++ ]
2023-02-22 22:46:14,993 __main__ MainThread [my message 17 +++ ]
2023-02-22 22:46:16,002 __main__ MainThread [my message 18 +++ ]
2023-02-22 22:46:17,009 __main__ MainThread [my message 19 +++ ]
进程已结束,退出代码0
这个是logging.Formatter类的解释,所以我们需要自己学习,学会看python源码
"""
Formatter instances are used to convert a LogRecord to text.
Formatters need to know how a LogRecord is constructed. They are
responsible for converting a LogRecord to (usually) a string which can
be interpreted by either a human or an external system. The base Formatter
allows a formatting string to be specified. If none is supplied, the
style-dependent default value, "%(message)s", "{message}", or
"${message}", is used.
The Formatter can be initialized with a format string which makes use of
knowledge of the LogRecord attributes - e.g. the default value mentioned
above makes use of the fact that the user's message and arguments are pre-
formatted into a LogRecord's message attribute. Currently, the useful
attributes in a LogRecord are described by:
%(name)s Name of the logger (logging channel)
%(levelno)s Numeric logging level for the message (DEBUG, INFO,
WARNING, ERROR, CRITICAL)
%(levelname)s Text logging level for the message ("DEBUG", "INFO",
"WARNING", "ERROR", "CRITICAL")
%(pathname)s Full pathname of the source file where the logging
call was issued (if available)
%(filename)s Filename portion of pathname
%(module)s Module (name portion of filename)
%(lineno)d Source line number where the logging call was issued
(if available)
%(funcName)s Function name
%(created)f Time when the LogRecord was created (time.time()
return value)
%(asctime)s Textual time when the LogRecord was created
%(msecs)d Millisecond portion of the creation time
%(relativeCreated)d Time in milliseconds when the LogRecord was created,
relative to the time the logging module was loaded
(typically at application startup time)
%(thread)d Thread ID (if available)
%(threadName)s Thread name (if available)
%(process)d Process ID (if available)
%(message)s The result of record.getMessage(), computed just as
the record is emitted
"""