记录下常用的一些东西,每次用总是查文档有点小麻烦。 py2.7

日志应该是生产应用的重要生命线,谁都不应该掉以轻心

有益原则

级别分离

日志系统通常有下面几种级别,看情况是使用

  • FATAL - 导致程序退出的严重系统级错误,不可恢复,当错误发生时,系统管理员需要立即介入,谨慎使用。
  • ERROR - 运行时异常以及预期之外的错误,也需要立即处理,但紧急程度低于FATAL,当错误发生时,影响了程序的正确执行。需要注意的是这两种级别属于服务自己的错误,需要管理员介入,用户输入出错不属于此分类。
  • WARN - 预期之外的运行时状况,表示系统可能出现问题。对于那些目前还不是错误,然而不及时处理也会变成错误的情况,也可以记为WARN,如磁盘过低。
  • INFO - 有意义的事件信息,记录程序正常的运行状态,比如收到请求,成功执行。通过查看INFO,可以快速定位WARN,ERROR, FATAL。INFO不宜过多,通常情况下不超过TRACE的10%。
  • DEBUG - 与程序运行时的流程相关的详细信息以及当前变量状态。
  • TRACE - 更详细的跟踪信息。DEBUG和TRACE这两种规范由项目组自己定义,通过该种日志,可以查看某一个操作每一步的执行过程,可以准确定位是何种操作,何种参数,何种顺序导致了某种错误的发生

单独目录

日志最好放到单独的日志目录,例如 /var/logs/ 下,按照应用分成不同的目录,或者是文件。日志不要放在应用目录下,那样不利于自动化部署和应用升级,备份等。

日志分类

诊断日志,统计日志,审计日志等等,不同用途等日志存储到不同的文件中,方面后面的查询,分析。

日志格式

不管是web日志,还是应用日志,最好有一个比较统一的格式(例如时间格式),方面日志的查询,入库,和分析。还有一些应用统一使用json的日志格式,也挺好的。

不好的做法

  • 日志中含有用户敏感信息
  • 线上程序中使用 print
  • 生产环境使用 debug 级别日志 ��

日志切分

日志可以按照每天,每周或者是文件的大小,切分之后压缩。一方面容易按时间回溯,另一方面可以减少磁盘空间,对于很久之前的日志,可以传输到远程服务器,或者是删除。

Python 日志

好习惯

  • root级别的设置: 日志格式, 有利于标准化
  • class 中设置logger self.logger = logging.getLogger(type(self).__name__)
  • 模块,文件中设置 logger logger = logging.getLogger(__name__)
  • 使用JSON YAML等格式来配置logging,感觉比使用代码或者 ini格式看起来更方面
  • 错误日志是比较特殊的日志,因为它需要更多的信息,例如错误产生的上下文,还有错误堆栈等信息。可以通过 python logging context pypi 关键词google一些信息,或者自己设计一个 logging handler 来实现。

实际问题

  • 简单的小应用中,单个日志文件,同时还要打印控制台
import logging

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
                    datefmt='%m-%d %H:%M',
                    filename='/temp/myapp.log',
                    filemode='w')
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
# add the handler to the root logger
logging.getLogger('').addHandler(console)
  • 记录 Exception 的trace 信息(很有用哦)
try:
    open('/path/to/does/not/exist', 'rb')
except (SystemExit, KeyboardInterrupt):
    raise
except Exception, e:
    logger.error('Failed to open file', exc_info=True)
  • ini 格式例子

这里用了第三方的一个handler,ConcurrentRotatingFileHandler, 实现多进程安全

[loggers]
keys=root

[handlers]
keys=stream, rotatingFile, errorFile

[formatters]
keys=form01

[logger_root]
level=DEBUG
handlers=stream, rotatingFile, errorFile

[handler_stream]
class=StreamHandler
level=NOTSET
formatter=form01
args=(sys.stdout,)

[handler_errorFile]
class=FileHandler
level=ERROR
formatter=form01
args=('./logs/portal.log', 'a')

[handler_rotatingFile]
level=INFO
formatter=form01
class=handlers.ConcurrentRotatingFileHandler
args=('./logs/portal.log','a',50240000, 10)

[formatter_form01]
format=%(asctime)s %(name)s %(levelname)s %(message)s
datefmt=
class=logging.Formatter

引用

import logging
import logging.config
import cloghandler
logging.config.fileConfig(join(BASE_DIR, "conf/log.conf"))

logger = logging.getLogger(__name__)

默认会使用 root 这个logger,如果名称匹配就使用对应的logger。 一个logger也可以指定多个 handdler, 用来处理不同的日志级别等。

  • JSON格式 例子

配置

{
    "version": 1,
    "disable_existing_loggers": false,
    "formatters": {
        "simple": {
            "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
        }
    },

    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "level": "DEBUG",
            "formatter": "simple",
            "stream": "ext://sys.stdout"
        },

        "info_file_handler": {
            "class": "logging.handlers.RotatingFileHandler",
            "level": "INFO",
            "formatter": "simple",
            "filename": "info.log",
            "maxBytes": 10485760,
            "backupCount": 20,
            "encoding": "utf8"
        },

        "error_file_handler": {
            "class": "logging.handlers.RotatingFileHandler",
            "level": "ERROR",
            "formatter": "simple",
            "filename": "errors.log",
            "maxBytes": 10485760,
            "backupCount": 20,
            "encoding": "utf8"
        }
    },

    "loggers": {
        "my_module": {
            "level": "ERROR",
            "handlers": ["console"],
            "propagate": "no"
        }
    },

    "root": {
        "level": "INFO",
        "handlers": ["console", "info_file_handler", "error_file_handler"]
    }
}

获取配置

import os
import json
import logging.config

def setup_logging(
    default_path='logging.json',
    default_level=logging.INFO,
    env_key='LOG_CFG'
):
    """Setup logging configuration

    """
    path = default_path
    value = os.getenv(env_key, None)
    if value:
        path = value
    if os.path.exists(path):
        with open(path, 'rt') as f:
            config = json.load(f)
        logging.config.dictConfig(config)
    else:
        logging.basicConfig(level=default_level)
  • 把日志格式化成json的工具

python-json-loggerlogmatic json-logger增加的一些封装

import logging.handlers
from pythonjsonlogger import jsonlogger
import datetime

class JsonFormatter(jsonlogger.JsonFormatter, object):
    def __init__(self,
                 fmt="%(asctime) %(name) %(processName) %(filename)  %(funcName) %(levelname) %(lineno) %(module) %(threadName) %(message)",
                 datefmt="%Y-%m-%dT%H:%M:%SZ%z",
                 style='%',
                 extra={}, *args, **kwargs):
        self._extra = extra
        jsonlogger.JsonFormatter.__init__(self, fmt=fmt, datefmt=datefmt, *args, **kwargs)

    def process_log_record(self, log_record):
        # Enforce the presence of a timestamp
        if "asctime" in log_record:
            log_record["timestamp"] = log_record["asctime"]
        else:
            log_record["timestamp"] = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%fZ%z")

        if self._extra is not None:
            for key, value in self._extra.items():
                log_record[key] = value
        return super(JsonFormatter, self).process_log_record(log_record)

参考

Python logging 模块和使用经验的更多相关文章

  1. python logging模块可能会令人困惑的地方

    python logging模块主要是python提供的通用日志系统,使用的方法其实挺简单的,这块就不多介绍.下面主要会讲到在使用python logging模块的时候,涉及到多个python文件的调 ...

  2. python logging模块使用

    近来再弄一个小项目,已经到收尾阶段了.希望加入写log机制来增加程序出错后的判断分析.尝试使用了python logging模块. #-*- coding:utf-8 -*- import loggi ...

  3. 读懂掌握 Python logging 模块源码 (附带一些 example)

    搜了一下自己的 Blog 一直缺乏一篇 Python logging 模块的深度使用的文章.其实这个模块非常常用,也有非常多的滥用.所以看看源码来详细记录一篇属于 logging 模块的文章. 整个 ...

  4. (转)python logging模块

    python logging模块 原文:http://www.cnblogs.com/dahu-daqing/p/7040764.html 1 logging模块简介 logging模块是Python ...

  5. Python logging 模块学习

    logging example Level When it's used Numeric value DEBUG Detailed information, typically of interest ...

  6. python logging—模块

    python logging模块 python logging提供了标准的日志接口,python logging日志分为5个等级: debug(), info(), warning(), error( ...

  7. Python logging模块无法正常输出日志

    废话少说,先上代码 File:logger.conf [formatters] keys=default [formatter_default] format=%(asctime)s - %(name ...

  8. 0x03 Python logging模块之Formatter格式

    目录 logging模块之Formatter格式 Formater对象 日志输出格式化字符串 LogRecoder对象 时间格式化字符串 logging模块之Formatter格式 在记录日志是,日志 ...

  9. 0x01 Python logging模块

    目录 Python logging 模块 前言 logging模块提供的特性 logging模块的设计过程 logger的继承 logger在逻辑上的继承结构 logging.basicConfig( ...

随机推荐

  1. 学习HTML的第一次课

    1.母板中的标签的含义 1.1< Doctype html/ > 声明文档类型为HTML 1.2< meta charset="UTF-8"/ > 设当前网 ...

  2. 拥抱开源,Office 365开发迎来新时代

    前言 作为全球最大的开放源代码托管平台,Github在上周迎来了它的十岁生日.自从2008年正式上线以来,Github上面汇聚了数以千万计的开发人员和各种项目,它几乎成为了开源的代名词和风向标,各大软 ...

  3. 机器学习基石:14 Regularization

    一.正则化的假设集合 通过从高次多项式的H退回到低次多项式的H来降低模型复杂度, 以降低过拟合的可能性, 如何退回? 通过加约束条件: 如果加了严格的约束条件, 没有必要从H10退回到H2, 直接使用 ...

  4. 百度API-------热力图

    <!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content=& ...

  5. PHPCMS V9 任意文件下载(Windows)

    先来看看PHPCMS V9.6.0的任意下载 还是和上次的注入一样,是个由parse_str() 函数引发的变量覆盖. 位于 /phpv9.6.0/phpcms/modules/content/dow ...

  6. [NOI 2009]变换序列

    Description 题库链接 对于 \(N\) 个整数 \(0, 1, \cdots, N-1\) ,一个变换序列 \(T\) 可以将 \(i\) 变成 \(T_i\) ,其中 \(T_i \in ...

  7. ●BZOJ 4821 [Sdoi2017]相关分析

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4821 题解: 线段树是真的恶心,(也许是我的方法麻烦了一些吧)首先那个式子可以做如下化简: ...

  8. 中断API之setup_irq【转】

    转自:https://blog.csdn.net/tiantao2012/article/details/78957472 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...

  9. Map 探索

    关于Map问题我一直了解的不是很透彻,下面进行比较系统的总结一下. 1.

  10. C语言作业程序设计第一次作业

    1.求圆面积和面积 (1)题目: 输入圆的半径,计算圆的周长和面积 (2)流程图: (3)测试数据及运行结果 测试数据:r=4 运行结果: (4)实验分析 没有遇到问题 2.判断闰年问题 (1)题目: ...