twisted日志源码分析

twisted日志系统提供了按照日期自动创建日志文件的功能, 不需要启动reactor也可以使用

启动日志示例代码:

  outpath = '/Users/.../log'
    outname = 'server.log'
    if not os.path.exists(outpath) :
        os.mkdir(outpath)
    log.FileLogObserver.timeFormat = '%m-%d %H:%M:%S'
    log_file = logfile.DailyLogFile(outname, outpath)
    log.startLogging(log_file)

log系统初始化(twisted/python/log.py):

logfile = StdioOnnaStick(0, getattr(sys.stdout, "encoding", None)) # 封装sys.stdout
logerr = StdioOnnaStick(1, getattr(sys.stderr, "encoding", None)) # 封装sys.stderr

如何启动日志系统:

def startLogging(file, *a, **kw):
  # 创建观察者,有日志或者说stdout.write操作的时候通知每个observer, file就是DailyLogFile
  flo = FileLogObserver(file) 
  startLoggingWithObserver(flo.emit, *a, **kw) # 开始启动观察者

def startLoggingWithObserver(observer, setStdout=1):
  addObserver(observer) # observe就是flo.emit函数
  msg("Log opened.")
  if setStdout:
      sys.stdout = logfile # 将正常的print打印重定向到logfile对象
      sys.stderr = logerr

从调用print语句开始打印分析日志打印的代码流程:

# print -> stdout.write -> logfile.write

# 所以看下logfile所对应的StdioOnnaStick类中write方法:
  def write(self, data): # 如何到达这步:print -> stdout.write -> logfile.write
      ...
      self.buf = d[-1]
      messages = d[0:-1]
      for message in messages:
          msg(message, printed=1, isError=self.isError) # 调用theLogPublisher.msg

# LogPublisher的msg方法:
  def msg(self, *message, **kw):
    actualEventDict = (context.get(ILogContext) or {}).copy()
    actualEventDict.update(kw)
    actualEventDict['message'] = message
    actualEventDict['time'] = time.time()
    for i in range(len(self.observers) - 1, -1, -1): # 遍历注册的日志观察者
        try:
            # 调用observer函数,就是FileLogObserver.emit()
            self.observers[i](actualEventDict) 
    ...

# FileLogObserver.emit方法:

  def emit(self, eventDict):
    text = textFromEventDict(eventDict)
    if text is None:
        return

    timeStr = self.formatTime(eventDict['time'])
    fmtDict = {'system': eventDict['system'], 'text': text.replace("\n", "\n\t")}
    msgStr = _safeFormat("[%(system)s] %(text)s\n", fmtDict)

    # 调用最开始FileLogObserver()传入的DailyLogFile.write
    util.untilConcludes(self.write, timeStr + " " + msgStr) 
    util.untilConcludes(self.flush)  # Hoorj!
 
# DailyLogFile.write:

  def write(self, data):
    """Write some data to the log file"""
    BaseLogFile.write(self, data)
    self.lastDate = max(self.lastDate, self.toDate())

# BaseLogFile.write:

  def write(self, data):
    if self.shouldRotate(): # 根据日期判断是否需要另起一个log文件:if self.toDate() > self.lastDate
        self.flush()
        self.rotate() # 调用DailyLogFile.rotate()方法新建log文件
    self._file.write(data) # 终于开始写文件了

# DailyLogFile.rotate:

  def rotate(self):
      if not (os.access(self.directory, os.W_OK) and os.access(self.path, os.W_OK)):
          return
      newpath = "%s.%s" % (self.path, self.suffix(self.lastDate))
      if os.path.exists(newpath):
          return
      self._file.close()
      os.rename(self.path, newpath) # 将当前的log文件重命名为带日期的历史log文件
      self._openFile() # 以self.path为路径打开一个新文件准备写入


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值