demo shows how to write a non-uniform configuration format of the log

One, background

Logback large number of projects in the use of the diary, with some items using the log confusion, the format is not uniform, most people do not understand the configuration file, configuration error, and now need to develop a unified, less logging component configuration, easy to use.

Second, the design ideas

0 arranged as far as possible, no logback.xml

Log format unified, easy to follow log analysis system

Only two log level, one normal log, a log is abnormal

Provide log4j, jcl, logback, commons-log bridge and other programs and compatible version of the program

Grapes thread, JSON formatted output, map format, array format, the request response parameters (for time consuming) log output convenient method, etc.

Support redis, db, http automatically switch configurations * *

New log type (logger)

api using flow structure, similar to StringBuffer

Third, outline design

1, zero-configuration

Research Code

java
static LoggerContext lc;
    static {
        lc = (LoggerContext) LoggerFactory.getILoggerFactory();
        // 对应配置中的appender
        ConsoleAppender ca = new ConsoleAppender();
        ca.setContext(lc);
        ca.setName("console");
        // 格式
        PatternLayoutEncoder pl = new PatternLayoutEncoder();
        pl.setContext(lc);
        pl.setPattern("%d{MMddHHmmss.SSS} [%thread] %-5level %logger{36} - %msg%n");
        pl.start();
        ca.setEncoder(pl);
        ca.start();
        // 对应配置中的logger
        ch.qos.logback.classic.Logger rootLogger = lc.getLogger("com.test");
        rootLogger.addAppender(ca);}

The above code is equivalent to the following xml


                    %d{MMddHHmmss.SSS} [%thread] %-5level %logger{36} - %msg%n

It can be free to the contents of the configuration file is written in code form, the theory may have been achieved 0 configuration.

2, output path

Fixing the logs to convention, the relative path log / xxx.yyyy-MM-dd-HH.log, where xxx is the logger name

3, log format

格式固定:
MMddHHmmss.SSS||id||【交易名子步骤】||context ||[level][线程号]
例:
150000.311||N-XrUTQzIc1531897200311||【CiTeeFilterci拦截器】||ci拦截器 请求的完整参数为:{"merchantId":["0012444"],"userId":["13112341232"]} ||[INFO][http-8091-7]

Core code fixed format, intercepting a request to the log, assembled according to the format, and the main method to inherit ThrowableProxyConverter achieved MessageConverter log intercept and modify the desired format, for example, the id and the like into the local variables used therein, the core It is the use of the MDC

4, the base logger

All logs are the default output here logger name: when the service system initialization, define the Logger and appender, namely the Logger to root log

5, custom logger

Provided addLogger methods, parameters packageName package name, for example: com.test will lose if the name parameter is not set, the default name for the package name last name name behind a character, decided the name of the log file path log path to a non-losing non-essential. whether the output to the input additivity root log

6, a special log

Special log component configuration, for example: redis Default Default HTTP ERROR ERROR ERROR Kafka DB Connection Pool Default Default Default ERROR ERROR schedul Spring default ERROR

7, abnormal, log processing line feed

Providing a print format exception exception stack offers a new line of code formatted print ideas: Inheritance ThrowableProxyConverter, obtain exception stack, the fixed format text is inserted in front of every line

8, ordinary log api (VirgoLog)

method The method described
setUniqKey(id) Set current thread id, you can set when the thread starts, without setting back
updateStep(trade, step) Updated information about the current step of id
log(msg, param) Normal log record, MSG substitution rule, replace the ordinary {}, if you want to replace the service log api format, using the `` replacement
logErr(msg, e) Exception log records
log( trade, step, msg, param) Record ordinary log, this method will automatically update the id, trade, step, not recommended
logErr(trade, step, msg, e) Exception log records
log(cid, trade, step, msg, param) Record ordinary log, this method will automatically update the id, trade, step, not recommended
logErr(cid, trade, step, msg, e) Exception log records
debug(msg, param) Record debug-level logging is not recommended

Business logging api (VirgoLog)

Usually when the diary, if a class does not have time to toString method, the data will not be printed out correctly, this time to provide an alternative method, the object directly replaced json print, ideas for the core code

MessageFormatter {} is a process based Alternatively, re-write type, i.e., little change support also supports `{}, and determines json or replaced toString

api follows

method The method described
begin(msg) Record start
end(msg) Recording is complete, it will print in this thread to begin now on a time-consuming
logJson(json, format) Json log recording format, format indicates whether the line feed
logMap(map, format) Formatting log records map
logCollection(list, format) Formatting log record set
logArray(array, format) An array of records formatted log
logObjct(obj, format) Object formatting log records

System api (LoggerHelper)

method The method described
getLogger() Acquisition logger, for the diary
getLogger(name) Get logger by name
addLogger () Reference Custom Logger, if the logger has been created, it is no longer created, generally do not use, unless you want to customize the log name, etc.
consoleOpen() Open the console log, the default configuration console log when the system starts
commonOpen(name, level) The default components are error level, this method can change the log level, for example redis http, etc.

9, special formatting

map: i.e. into json, then format

collection: ditto

array: also ibid.

object: ditto

10, issue

  • Desensitization password, encryption method it is necessary to separate extraction
  • Print switch provides parent thread

11, maven dependence

                    com.cdc.ecliptic            virgo            1.5_1.6-SNAPSHOT

12、demo

public static void main(String[] args) throws InterruptedException {

        // 启动
        VirgoLancher.start("hahaha", "com.cdc.virgo", "D:/test/hahah.log");
        LoggerHelper.commonOpen("hahaha", LogLevel.DEBUG);
        Logger logger1 = LoggerFactory.getLogger("druid");
//        VirgoLancher.commonStart("abc", "com.cdc.virgo");
        // 打开控制台
        LoggerHelper.consoleOpen();
        // 设置cid
        VirgoLog.setUniqKey(null);
        // 设置步骤名和交易名
        VirgoLog.updateStep("adfa", "saf");
        // 获取Logger
        VirgoLog logger = VirgoLog.getLogger();

        // 打开debug级别(只有在开发阶段可以打开)
//        logger.changeLevel(LogLevel.DEBUG);
        // 记录换行
        logger.log("a");

        logger1.info("dddddddddd");
        logger1.error("dddddddddd");

//        logger1.info("sfdasfaf" +
//                "\nafafdasfd" +
//                "\nasfdasf");
        logger.log("sfdasfaf" +
                "\nafafdasfd" +
                "\nasfdasf");

//        logger1.info("b");
        // 正常日志
//        logger.log("我只有一行");
        Map map = new HashMap();
        map.put("asdf", "1");
        map.put("asdf2", "2");
        map.put("asdf3", "13");
        map.put("asdf4", "14");
        map.put("asdf5", "15");
        map.put("asdf6", "16");
//        // 异常日志也支持格式化
//        logger.logErr("我错了:{},你没错:~~", new Exception("asdfsaflk"), "啊", map);
//        logger.log("----------------------------------------------");
//        // {}替换普通对象,调用toString()  ~~把对象转换为json并且格式化输出 ``把对象转换为json不格式化输出
        logger.log("你好{},你是谁~~``,sd~xx {}", map, map, map, "tttt");
        VirgoLog.updateStep("saf2");
//        // 把对象转换为json输出
//        logger.logJson(map, false);
//        // 更新步骤名和交易名
//        VirgoLog.updateStep("bbbbb", "ccccc");
//        // 耗时日志打印
        logger.begin("处理内容");
        logger.begin("处理第二个");
        logger.begin("处理第三个");
        Thread.sleep(3000L);
        logger.end();
        Thread.sleep(1000L);
        logger.end();
        VirgoLog.updateStep("saf3");
        logger.end();
//        // 记录debug日志,一般调试用
//        logger.logDebug("jajajajaja");

//        List l = new ArrayList();
//        B b = new B();
//        try {
//            b.b();
//        } catch (Exception e) {
//            logger.logErr("woqu", e);
//        }
    }

Author: Pengfei

Source: CreditEase Institute of Technology

Guess you like

Origin yq.aliyun.com/articles/709429