#!/usr/bin/python
# -*- coding:utf-8 -*-

# 1、日志默认的输出等级为：warning级别及以上的
# 2、想修改日志的默认输出等级？通过logging.basicConfig(level="INFO")----info需要用大写
# 3、想知道日志是什么时候打印出来的，以及其他参数？通过logging.basicConfig(format=console_fmt)
# 4、如果要同时添加这2个参数，需要写在一行代码中，logging.basicConfig(level="INFO",format=console_fmt)
# %(name)s：名字
# %(levelname)s：日志级别
# %(asctime)s：打印时间，年月日时分秒
# %(message)s：日志中的信息
# %(lineno)d：报错日志在代码中第几行
# %(filename)s：文件名
# %(thread)d：进程id
# %(levelname)s：错误等级名称
# '%(asctime)s - %(filename)s[line:%(lineno)d] %(thread)d- %(levelname)s: %(message)s'
import logging
import time

import colorlog
import os
from logging.handlers import TimedRotatingFileHandler
from datetime import datetime

log_colors_config = {
    # 终端输出日志颜色配置
    'DEBUG': 'white',
    'INFO': 'green',
    'WARNING': 'yellow',
    'ERROR': 'red',
    'CRITICAL': 'bold_red',
}

default_formats = {
    # 终端输出格式
    'console_format': '%(log_color)s%(asctime)s-id%(thread)d-%(filename)s[line:%(lineno)d]-%(levelname)s-[日志信息]: %(message)s',
    # 日志输出格式
    'log_format': '%(asctime)s-id %(thread)d-%(filename)s[line:%(lineno)d]-%(levelname)s-[日志信息]: %(message)s'
}


class TimeLoggerRolloverHandler(TimedRotatingFileHandler):
    def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False):
        super(TimeLoggerRolloverHandler, self).__init__(filename, when, interval, backupCount, encoding, delay, utc)

    def doRollover(self):
        """
        """
        if self.stream:
            self.stream.close()
            self.stream = None
        currentTime = int(time.time())
        dstNow = time.localtime(currentTime)[-1]
        log_type = 'all' if self.level == 20 else 'warning'

        index = self.baseFilename.rfind("\\") if self.baseFilename.find('\\') > 0 else self.baseFilename.rfind("/")

        self.baseFilename = "%s%s-%s.log" % (
            self.baseFilename[:index + 1], datetime.now().strftime('%Y-%m-%d'), log_type)

        if not self.delay:
            self.stream = self._open()
        newRolloverAt = self.computeRollover(currentTime)
        while newRolloverAt <= currentTime:
            newRolloverAt = newRolloverAt + self.interval
        if (self.when == 'MIDNIGHT' or self.when.startswith('W')) and not self.utc:
            dstAtRollover = time.localtime(newRolloverAt)[-1]
            if dstNow != dstAtRollover:
                if not dstNow:
                    addend = -3600
                else:
                    addend = 3600
                newRolloverAt += addend
        self.rolloverAt = newRolloverAt


class HandleLog:
    """
    先创建日志记录器（logging.getLogger），然后再设置日志级别（logger.setLevel），
    接着再创建日志文件，也就是日志保存的地方（logging.FileHandler），然后再设置日志格式（logging.Formatter），
    最后再将日志处理程序记录到记录器（addHandler）
    """

    @staticmethod
    def __init_logfile_handler(log_path):
        """
        创建日志记录器handler，用于收集日志
        :param log_path: 日志文件路径
        :return: 日志记录器
        """
        # 创建一个 handler，用于写入日志文件
        # midnight: 表示日志文件在每天半夜时分滚动
        # interval: 间隔时间单位的个数，指等待多少个 when 的时间后 Logger 会自动重建新闻继续进行日志记录
        # backupCount: 表示日志文件的保留个数，假如为7，则会保留最近的7个日志文件

        logfile_handler = TimeLoggerRolloverHandler(filename=log_path, when="midnight", interval=1, backupCount=20)
        # 写入文件，如果文件超过 10M 大小时，切割日志文件，仅保留3个文件
        # logfile_handler = RotatingFileHandler(filename=log_path, maxBytes=10 * 1024 * 1024, backupCount=3,
        #                                       encoding='utf-8')
        return logfile_handler

    @staticmethod
    def __init_console_handle():
        """创建终端日志记录器handler，用于输出到控制台"""
        console_handle = logging.StreamHandler()
        return console_handle

    @staticmethod
    def __set_handle(__logger, handle, level=logging.INFO):
        """
        设置handler级别并添加到终端logger收集器
        :param handle: 终端日志记录器
        :param level: 日志记录器级别
        """
        handle.setLevel(level=level)
        __logger.addHandler(handle)

    @staticmethod
    def __set_logfile_formatter(file_handler):
        """
        设置日志输出格式-日志文件
        :param file_handler: 日志记录器
        """
        formatter = logging.Formatter(default_formats["log_format"])
        file_handler.setFormatter(formatter)

    @staticmethod
    def __set_console_formatter(console_handle):
        """
        设置输出格式-控制台
        :param console_handle: 终端日志记录器
        :return:
        """
        formatter = colorlog.ColoredFormatter(fmt=default_formats["console_format"], log_colors=log_colors_config)
        console_handle.setFormatter(formatter)

    @staticmethod
    def __close_handler(file_handler):
        """
        关闭handler
        :param file_handler: 日志记录器
        """
        file_handler.close()

    @staticmethod
    def get_logger(log_path='log.log', is_save=True):
        '''
            log_path: 日志文件夹路径
            is_save: 是否保存日志文件，默认保存
        '''
        __logger = logging.getLogger()  # 创建日志记录器
        __logger.setLevel(logging.DEBUG)  # 设置默认日志记录器记录级别
        # 创建终端日志记录器handler，用于输出到控制台
        console_handle = HandleLog.__init_console_handle()
        # 设置显示格式
        HandleLog.__set_console_formatter(console_handle)
        # 设置handler级别并添加到终端logger收集器
        HandleLog.__set_handle(__logger, console_handle)

        if is_save:
            # 保存日志文件
            # cur_path = os.path.dirname(os.path.realpath(__file__))  # 当前项目路径
            # log_path = os.path.join(os.path.dirname(cur_path), log_path)  # log_path为存放日志的路径
            if not os.path.exists(log_path): os.mkdir(log_path)  # 若不存在logs文件夹，则自动创建

            _all_log_path = os.path.join(log_path, datetime.now().strftime('%Y-%m-%d') + "-all" + ".log")  # 收集所有日志信息文件
            _warning_log_path = os.path.join(log_path,
                                             datetime.now().strftime('%Y-%m-%d') + "-warning" + ".log")  # 收集错误日志信息文件
            # 创建日志记录器handler，用于收集日志
            all_logfile_handle = HandleLog.__init_logfile_handler(_all_log_path)
            warning_logfile_handle = HandleLog.__init_logfile_handler(_warning_log_path)
            # 设置显示格式
            HandleLog.__set_logfile_formatter(all_logfile_handle)
            HandleLog.__set_logfile_formatter(warning_logfile_handle)
            # 设置handler级别并添加到终端logger收集器
            HandleLog.__set_handle(__logger, all_logfile_handle)
            HandleLog.__set_handle(__logger, warning_logfile_handle, level=logging.WARNING)

        return __logger


if __name__ == '__main__':
    log = HandleLog.get_logger(os.getcwd() + '_logs')
    i = 0
    while True:
        log.info("这是日志信息")
        log.debug("这是debug信息")
        log.warning("这是警告信息")
        log.error("这是错误日志信息")
        log.critical("这是严重级别信息")
        print(i)
        i = i + 1
        time.sleep(1)
