记录下常用的一些东西,每次用总是查文档有点小麻烦。 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. OpenShift实战(五):OpenShift容器监控Metrics

    1.创建持久化metric pv卷 [root@master1 pv]# cat metrics.json apiVersion: v1 kind: PersistentVolume metadata ...

  2. R语言-美国枪杀案分析

    案例:该数据集的是一个关于美国2017年犯罪的一个数据集,接下来我们对该数据集进行分析 字段: #### S# :数据编号 #### Location:案件发生城市,州 #### Date:时间 ## ...

  3. [SCOI 2012]滑雪与时间胶囊

    Description a180285非常喜欢滑雪.他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1<=i<=N)和一高度Hi. ...

  4. [HNOI2009]无归岛

    Description Neverland是个神奇的地方,它由一些岛屿环形排列组成,每个岛上都生活着之中与众不同的物种.但是这些物种都有一个共同的生活习性:对于同一个岛上的任意两个生物,他们有且仅有一 ...

  5. TopCoder SRM 559 Div 1 - Problem 900 CircusTents

    传送门:https://284914869.github.io/AEoj/559.html 题目简述: n个实心圆,两两没有交集,在第一个圆上找一个点,使得它到另外一个圆上某个点的最短距离的最小值尽量 ...

  6. 以独立的语句将new对象置入智能指针

    以独立的语句将newed对象置入智能指针: processWidget(std::tr1::share_ptr<Widget>(new Widget) , priority()); 我们在 ...

  7. bzoj4665小w的喜糖 dp+容斥

    4665: 小w的喜糖 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 120  Solved: 72[Submit][Status][Discuss] ...

  8. Python中模块之shutil及zipfile&tarfile的功能介绍

    shutil的功能介绍及其他打包.压缩模块 1. shutil模块的方法 chown 更改指定路径的属组 2. copy 拷贝文件和权限 方法:shutil.copy(src,dst,*,follow ...

  9. Delphi 7连接MySql 5.5.15(转)

    网上有很多关于Delphi连接MySql数据库的文章,在这里,我只记录下自己测试过的方法,以备所需.系统环境:Windows XP SP3软件环境:Delphi 7 .mysql-installer- ...

  10. Linux下解决无法远程连接数据库问题

    起因 今天在ubuntu16.04环境下通过mysql workbench访问远程数据库时,发现无法连接问题,解决思路及方法记录如下,不足之处,请多指教. 问题 通过workbench输入密码访问时报 ...