slf4j 日志监控

 阅读约 27 分钟

问题描述

监控系统

新系统起步,旨在监控原有系统的各种问题。主要的一部分,就是监视原有系统的日志。

日志,是Java企业级应用开发必不可少的一部分,市场上有诸多日志框架。我们选用slf4j

日志有以下级别:

TRACE, DEBUG, INFO, WARN, ERROR

我们期待,当系统运行时打印了WARNERROR级别的日志时,向我们的服务器推送消息。使得我们可以分析日志,构造更完整的系统。

实现

思考

日志问题与之前的Hibernate映射问题不同。

Hibernate映射问题是默认用这个类,然后我们可以利用Spring Boot为我们提供的配置,当去映射名称的时候调用我这个类。

我们的日志是这么写的:

private static final Logger logger = LoggerFactory.getLogger(xxxx.class);

对象都是从LoggerFactory那创建出来的,我们根本没办法从配置中下手。

自定义日志

新建日志类YunzhiLogger,去实现org.slf4j.Logger接口。

clipboard.png

这是Logger接口的源码,一共有61个方法,我们一一去实现是不现实的,根据面向对象大法,我们应该去找一个合适的父类去继承,然后重写不符合我们要求的方法。

package org.slf4j;

public interface Logger {

    final public String ROOT_LOGGER_NAME = "ROOT";

    public String getName();

    public boolean isTraceEnabled();

    public void trace(String msg);

    public void trace(String format, Object arg);

    public void trace(String format, Object arg1, Object arg2);

    public void trace(String format, Object... arguments);

    public void trace(String msg, Throwable t);

    public boolean isTraceEnabled(Marker marker);

    public void trace(Marker marker, String msg);

    public void trace(Marker marker, String format, Object arg);

    public void trace(Marker marker, String format, Object arg1, Object arg2);

    public void trace(Marker marker, String format, Object... argArray);

    public void trace(Marker marker, String msg, Throwable t);

    public boolean isDebugEnabled();

    public void debug(String msg);

    public void debug(String format, Object arg);

    public void debug(String format, Object arg1, Object arg2);

    public void debug(String format, Object... arguments);

    public void debug(String msg, Throwable t);

    public boolean isDebugEnabled(Marker marker);

    public void debug(Marker marker, String msg);

    public void debug(Marker marker, String format, Object arg);

    public void debug(Marker marker, String format, Object arg1, Object arg2);

    public void debug(Marker marker, String format, Object... arguments);

    public void debug(Marker marker, String msg, Throwable t);

    public boolean isInfoEnabled();

    public void info(String msg);

    public void info(String format, Object arg);

    public void info(String format, Object arg1, Object arg2);

    public void info(String format, Object... arguments);

    public void info(String msg, Throwable t);

    public boolean isInfoEnabled(Marker marker);

    public void info(Marker marker, String msg);

    public void info(Marker marker, String format, Object arg);

    public void info(Marker marker, String format, Object arg1, Object arg2);

    public void info(Marker marker, String format, Object... arguments);

    public void info(Marker marker, String msg, Throwable t);

    public boolean isWarnEnabled();

    public void warn(String msg);

    public void warn(String format, Object arg);

    public void warn(String format, Object... arguments);

    public void warn(String format, Object arg1, Object arg2);

    public void warn(String msg, Throwable t);

    public boolean isWarnEnabled(Marker marker);

    public void warn(Marker marker, String msg);

    public void warn(Marker marker, String format, Object arg);

    public void warn(Marker marker, String format, Object arg1, Object arg2);

    public void warn(Marker marker, String format, Object... arguments);

    public void warn(Marker marker, String msg, Throwable t);

    public boolean isErrorEnabled();

    public void error(String msg);

    public void error(String format, Object arg);

    public void error(String format, Object arg1, Object arg2);

    public void error(String format, Object... arguments);

    public void error(String msg, Throwable t);

    public boolean isErrorEnabled(Marker marker);

    public void error(Marker marker, String msg);

    public void error(Marker marker, String format, Object arg);

    public void error(Marker marker, String format, Object arg1, Object arg2);

    public void error(Marker marker, String format, Object... arguments);

    public void error(Marker marker, String msg, Throwable t);
}

找父类

粗略地阅读了一下LoggerFactorygetLogger的源代码。

clipboard.png

里面有很多的条件,先根据条件获取ILoggerFactory,该接口一共有三个实现类,实现类中再去定义不同的getLogger方法,不同的工厂获取出来的日志对象是不同的。

因为对日志框架不是很了解,如果我们随便找一个类继承,那slf4j的判断就失去意义了,所以此种方法行不通。

装饰器模式

我们想到了装饰器模式。

将一个对象进行装饰,完善其方法。

先将Logger中的方法都实现掉,然后定义私有变量logger,定义有参构造函数。

clipboard.png

定义loggerYunzhiLogger对该日志对象进行装饰。

private static final Logger logger = new YunzhiLogger(LoggerFactory.getLogger(xxxx.class));

借此,也理解了装饰器模式的应用场景。原来就想,装饰器实现的功能用继承不就能实现吗?为什么还要去装饰对象呢?直接继承父类然后调用super上的方法再加新功能不和这一样吗?

现在也明白了,有时候,我们找不到合适的父类(因为创造出的日志对象是根据不同条件new不同的类创造出来的),然后我们又想去给这个对象添加方法,没办法,只能修饰对象了。

或者有时候,找到父类,但是父类是final,没法继承,才用的装饰器模式。

装饰方法

首先,调用原logger方法进行默认实现。

package com.mengyunzhi.measurement.log;

import org.slf4j.Logger;
import org.slf4j.Marker;

/**
 * @author zhangxishuo on 2018/11/15
 */
public class YunzhiLogger implements Logger {

    private Logger logger;

    public YunzhiLogger(Logger logger) {
        this.logger = logger;
    }

    @Override
    public String getName() {
        return this.logger.getName();
    }

    @Override
    public boolean isTraceEnabled() {
        return this.logger.isTraceEnabled();
    }

    @Override
    public void trace(String msg) {
        this.logger.trace(msg);
    }

    @Override
    public void trace(String format, Object arg) {
        this.logger.trace(format, arg);
    }

    @Override
    public void trace(String format, Object arg1, Object arg2) {
        this.logger.trace(format, arg1, arg2);
    }

    @Override
    public void trace(String format, Object... arguments) {
        this.logger.trace(format, arguments);
    }

    @Override
    public void trace(String msg, Throwable t) {
        this.logger.trace(msg, t);
    }

    @Override
    public boolean isTraceEnabled(Marker marker) {
        return this.logger.isTraceEnabled(marker);
    }

    @Override
    public void trace(Marker marker, String msg) {
        this.logger.trace(marker, msg);
    }

    @Override
    public void trace(Marker marker, String format, Object arg) {
        this.logger.trace(marker, format, arg);
    }

    @Override
    public void trace(Marker marker, String format, Object arg1, Object arg2) {
        this.logger.trace(marker, format, arg1, arg2);
    }

    @Override
    public void trace(Marker marker, String format, Object... argArray) {
        this.logger.trace(marker, format, argArray);
    }

    @Override
    public void trace(Marker marker, String msg, Throwable t) {
        this.logger.trace(marker, msg, t);
    }

    @Override
    public boolean isDebugEnabled() {
        return this.logger.isDebugEnabled();
    }

    @Override
    public void debug(String msg) {
        this.logger.debug(msg);
    }

    @Override
    public void debug(String format, Object arg) {
        this.logger.debug(format, arg);
    }

    @Override
    public void debug(String format, Object arg1, Object arg2) {
        this.logger.debug(format, arg1, arg2);
    }

    @Override
    public void debug(String format, Object... arguments) {
        this.logger.debug(format, arguments);
    }

    @Override
    public void debug(String msg, Throwable t) {
        this.logger.debug(msg, t);
    }

    @Override
    public boolean isDebugEnabled(Marker marker) {
        return this.logger.isDebugEnabled(marker);
    }

    @Override
    public void debug(Marker marker, String msg) {
        this.logger.debug(marker, msg);
    }

    @Override
    public void debug(Marker marker, String format, Object arg) {
        this.logger.debug(marker, format, arg);
    }

    @Override
    public void debug(Marker marker, String format, Object arg1, Object arg2) {
        this.logger.debug(marker, format, arg1, arg2);
    }

    @Override
    public void debug(Marker marker, String format, Object... arguments) {
        this.logger.debug(marker, format, arguments);
    }

    @Override
    public void debug(Marker marker, String msg, Throwable t) {
        this.logger.debug(marker, msg, t);
    }

    @Override
    public boolean isInfoEnabled() {
        return this.logger.isInfoEnabled();
    }

    @Override
    public void info(String msg) {
        this.logger.info(msg);
    }

    @Override
    public void info(String format, Object arg) {
        this.logger.info(format, arg);
    }

    @Override
    public void info(String format, Object arg1, Object arg2) {
        this.logger.info(format, arg1, arg2);
    }

    @Override
    public void info(String format, Object... arguments) {
        this.logger.info(format, arguments);
    }

    @Override
    public void info(String msg, Throwable t) {
        this.logger.info(msg, t);
    }

    @Override
    public boolean isInfoEnabled(Marker marker) {
        return this.logger.isInfoEnabled(marker);
    }

    @Override
    public void info(Marker marker, String msg) {
        this.logger.info(marker, msg);
    }

    @Override
    public void info(Marker marker, String format, Object arg) {
        this.logger.info(marker, format, arg);
    }

    @Override
    public void info(Marker marker, String format, Object arg1, Object arg2) {
        this.logger.info(marker, format, arg1, arg2);
    }

    @Override
    public void info(Marker marker, String format, Object... arguments) {
        this.logger.info(marker, format, arguments);
    }

    @Override
    public void info(Marker marker, String msg, Throwable t) {
        this.logger.info(marker, msg, t);
    }

    @Override
    public boolean isWarnEnabled() {
        return this.logger.isWarnEnabled();
    }

    @Override
    public void warn(String msg) {
        this.logger.warn(msg);
    }

    @Override
    public void warn(String format, Object arg) {
        this.logger.warn(format, arg);
    }

    @Override
    public void warn(String format, Object... arguments) {
        this.logger.warn(format, arguments);
    }

    @Override
    public void warn(String format, Object arg1, Object arg2) {
        this.logger.warn(format, arg1, arg2);
    }

    @Override
    public void warn(String msg, Throwable t) {
        this.logger.warn(msg, t);
    }

    @Override
    public boolean isWarnEnabled(Marker marker) {
        return this.logger.isWarnEnabled(marker);
    }

    @Override
    public void warn(Marker marker, String msg) {
        this.logger.warn(marker, msg);
    }

    @Override
    public void warn(Marker marker, String format, Object arg) {
        this.logger.warn(marker, format, arg);
    }

    @Override
    public void warn(Marker marker, String format, Object arg1, Object arg2) {
        this.logger.warn(marker, format, arg1, arg2);
    }

    @Override
    public void warn(Marker marker, String format, Object... arguments) {
        this.logger.warn(marker, format, arguments);
    }

    @Override
    public void warn(Marker marker, String msg, Throwable t) {
        this.logger.warn(marker, msg, t);
    }

    @Override
    public boolean isErrorEnabled() {
        return this.logger.isErrorEnabled();
    }

    @Override
    public void error(String msg) {
        this.logger.error(msg);
    }

    @Override
    public void error(String format, Object arg) {
        this.logger.error(format, arg);
    }

    @Override
    public void error(String format, Object arg1, Object arg2) {
        this.logger.error(format, arg1, arg2);
    }

    @Override
    public void error(String format, Object... arguments) {
        this.logger.error(format, arguments);
    }

    @Override
    public void error(String msg, Throwable t) {
        this.logger.error(msg, t);
    }

    @Override
    public boolean isErrorEnabled(Marker marker) {
        return this.logger.isErrorEnabled(marker);
    }

    @Override
    public void error(Marker marker, String msg) {
        this.logger.error(marker, msg);
    }

    @Override
    public void error(Marker marker, String format, Object arg) {
        this.logger.error(marker, format, arg);
    }

    @Override
    public void error(Marker marker, String format, Object arg1, Object arg2) {
        this.logger.error(marker, format, arg1, arg2);
    }

    @Override
    public void error(Marker marker, String format, Object... arguments) {
        this.logger.error(marker, format, arguments);
    }

    @Override
    public void error(Marker marker, String msg, Throwable t) {
        this.logger.error(marker, msg, t);
    }
}

这是我为装饰器添加的默认实现,如有错误,欢迎批评指正。

然后就可以在相应的方法中添加我们的逻辑,如在error的方法中向我们的日志监控服务推送消息。

总结

  1. 通过对slf4j源码的学习大致学习了日志框架slf4j的运行原理。
  2. 通过找接口与父类理解了装饰器模式的应用场景。
  3. 本文只是实现了基本的功能,因为error方法与warn方法有很多重载的方法,所以我们期待可以实现对该日志类中所有名为errorwarn的方法进行切面处理。
阅读 830更新于 2018-12-06
推荐阅读
梦想开始的地方
用户专栏

浅梦辄止,书墨未浓。昔日云智,光阴如梭。

27 人关注
110 篇文章
专栏主页
目录