slf4j 日志监控

news/2024/9/17 16:03:54

问题描述

监控系统

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

日志,是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;}@Overridepublic String getName() {return this.logger.getName();}@Overridepublic boolean isTraceEnabled() {return this.logger.isTraceEnabled();}@Overridepublic void trace(String msg) {this.logger.trace(msg);}@Overridepublic void trace(String format, Object arg) {this.logger.trace(format, arg);}@Overridepublic void trace(String format, Object arg1, Object arg2) {this.logger.trace(format, arg1, arg2);}@Overridepublic void trace(String format, Object... arguments) {this.logger.trace(format, arguments);}@Overridepublic void trace(String msg, Throwable t) {this.logger.trace(msg, t);}@Overridepublic boolean isTraceEnabled(Marker marker) {return this.logger.isTraceEnabled(marker);}@Overridepublic void trace(Marker marker, String msg) {this.logger.trace(marker, msg);}@Overridepublic void trace(Marker marker, String format, Object arg) {this.logger.trace(marker, format, arg);}@Overridepublic void trace(Marker marker, String format, Object arg1, Object arg2) {this.logger.trace(marker, format, arg1, arg2);}@Overridepublic void trace(Marker marker, String format, Object... argArray) {this.logger.trace(marker, format, argArray);}@Overridepublic void trace(Marker marker, String msg, Throwable t) {this.logger.trace(marker, msg, t);}@Overridepublic boolean isDebugEnabled() {return this.logger.isDebugEnabled();}@Overridepublic void debug(String msg) {this.logger.debug(msg);}@Overridepublic void debug(String format, Object arg) {this.logger.debug(format, arg);}@Overridepublic void debug(String format, Object arg1, Object arg2) {this.logger.debug(format, arg1, arg2);}@Overridepublic void debug(String format, Object... arguments) {this.logger.debug(format, arguments);}@Overridepublic void debug(String msg, Throwable t) {this.logger.debug(msg, t);}@Overridepublic boolean isDebugEnabled(Marker marker) {return this.logger.isDebugEnabled(marker);}@Overridepublic void debug(Marker marker, String msg) {this.logger.debug(marker, msg);}@Overridepublic void debug(Marker marker, String format, Object arg) {this.logger.debug(marker, format, arg);}@Overridepublic void debug(Marker marker, String format, Object arg1, Object arg2) {this.logger.debug(marker, format, arg1, arg2);}@Overridepublic void debug(Marker marker, String format, Object... arguments) {this.logger.debug(marker, format, arguments);}@Overridepublic void debug(Marker marker, String msg, Throwable t) {this.logger.debug(marker, msg, t);}@Overridepublic boolean isInfoEnabled() {return this.logger.isInfoEnabled();}@Overridepublic void info(String msg) {this.logger.info(msg);}@Overridepublic void info(String format, Object arg) {this.logger.info(format, arg);}@Overridepublic void info(String format, Object arg1, Object arg2) {this.logger.info(format, arg1, arg2);}@Overridepublic void info(String format, Object... arguments) {this.logger.info(format, arguments);}@Overridepublic void info(String msg, Throwable t) {this.logger.info(msg, t);}@Overridepublic boolean isInfoEnabled(Marker marker) {return this.logger.isInfoEnabled(marker);}@Overridepublic void info(Marker marker, String msg) {this.logger.info(marker, msg);}@Overridepublic void info(Marker marker, String format, Object arg) {this.logger.info(marker, format, arg);}@Overridepublic void info(Marker marker, String format, Object arg1, Object arg2) {this.logger.info(marker, format, arg1, arg2);}@Overridepublic void info(Marker marker, String format, Object... arguments) {this.logger.info(marker, format, arguments);}@Overridepublic void info(Marker marker, String msg, Throwable t) {this.logger.info(marker, msg, t);}@Overridepublic boolean isWarnEnabled() {return this.logger.isWarnEnabled();}@Overridepublic void warn(String msg) {this.logger.warn(msg);}@Overridepublic void warn(String format, Object arg) {this.logger.warn(format, arg);}@Overridepublic void warn(String format, Object... arguments) {this.logger.warn(format, arguments);}@Overridepublic void warn(String format, Object arg1, Object arg2) {this.logger.warn(format, arg1, arg2);}@Overridepublic void warn(String msg, Throwable t) {this.logger.warn(msg, t);}@Overridepublic boolean isWarnEnabled(Marker marker) {return this.logger.isWarnEnabled(marker);}@Overridepublic void warn(Marker marker, String msg) {this.logger.warn(marker, msg);}@Overridepublic void warn(Marker marker, String format, Object arg) {this.logger.warn(marker, format, arg);}@Overridepublic void warn(Marker marker, String format, Object arg1, Object arg2) {this.logger.warn(marker, format, arg1, arg2);}@Overridepublic void warn(Marker marker, String format, Object... arguments) {this.logger.warn(marker, format, arguments);}@Overridepublic void warn(Marker marker, String msg, Throwable t) {this.logger.warn(marker, msg, t);}@Overridepublic boolean isErrorEnabled() {return this.logger.isErrorEnabled();}@Overridepublic void error(String msg) {this.logger.error(msg);}@Overridepublic void error(String format, Object arg) {this.logger.error(format, arg);}@Overridepublic void error(String format, Object arg1, Object arg2) {this.logger.error(format, arg1, arg2);}@Overridepublic void error(String format, Object... arguments) {this.logger.error(format, arguments);}@Overridepublic void error(String msg, Throwable t) {this.logger.error(msg, t);}@Overridepublic boolean isErrorEnabled(Marker marker) {return this.logger.isErrorEnabled(marker);}@Overridepublic void error(Marker marker, String msg) {this.logger.error(marker, msg);}@Overridepublic void error(Marker marker, String format, Object arg) {this.logger.error(marker, format, arg);}@Overridepublic void error(Marker marker, String format, Object arg1, Object arg2) {this.logger.error(marker, format, arg1, arg2);}@Overridepublic void error(Marker marker, String format, Object... arguments) {this.logger.error(marker, format, arguments);}@Overridepublic void error(Marker marker, String msg, Throwable t) {this.logger.error(marker, msg, t);}
}

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

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

总结

  1. 通过对slf4j源码的学习大致学习了日志框架slf4j的运行原理。
  2. 通过找接口与父类理解了装饰器模式的应用场景。
  3. 本文只是实现了基本的功能,因为error方法与warn方法有很多重载的方法,所以我们期待可以实现对该日志类中所有名为errorwarn的方法进行切面处理。

http://lihuaxi.xjx100.cn/news/236782.html

相关文章

linux 防火墙 -netfilter

2019独角兽企业重金招聘Python工程师标准>>> 关于iptables 什么是iptables? 常见于linx系统下的应用层防火墙工具 firewalld 和netfilter Linux 防火墙-netfilter selinux 临时关闭 setenforce 0selinux 永久关闭 vi /etc/selinux/configcentos7 之前使用 netfilte…

初识以太坊

链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 以太坊(Ethereum)已经成功跻身为密码货币资本市场的第二名,其地位仅次于比特币。在短时间内,以太坊迅…

flask 核心 之 应用上下文 及 请求上下文

Werkzeugs 是 Flask 的底层WSGI库。什么是WSGI? 一段简单的app: def dispath_request(self, request):return Response(Hello World!)def wsgi_app(self, environ, start_response):request Request(environ)response self.dispath_request(request)re…

dva + antd + mockjs 实现用户管理

1.安装dva-cli npm install dva-cli -g 2.创建应用 dva new dvadashboard [dvadashboard为项目名] 3.安装mockjs npm install mockjs --save4.配置mockjs 打开.roadhogrc.mock.js 设置如下const fsrequire(fs); const pathrequire(path); const mockPathpath.join(__dirname/…

什么是EOS?

链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 关于EOS有很多炒作。2017年5月,EOS的创始人丹•拉莫(Dan Larimer)在纽约宣布这一消息时,一幅巨大的巨型屏幕广告在时代广场上…

MySQL基础之 恢复数据和数据库迁移

1、mysql命令或者source命令恢复数据 这两个命令在进行恢复数据的时候要检查是否创建数据库。如果数据库不存在,则恢复失败。 数据库迁移 1、相同版本的mysql数据库之间的迁移。 mysqldump -h host1 -uroot -ppwd --all-databases | mysql -h host2 -uroot -ppw…

eosjs-ecc中文文档

链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载。 eosjs-ecc是eos官方处理密钥和签名的javascript开发包。访问地址:eosjs-ecc中文手册。 eosjs-ecc安装 nodejs环境下,使用N…

聊聊spring cloud gateway的PreserveHostHeaderGatewayFilter

序 本文主要研究下spring cloud gateway的PreserveHostHeaderGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java Configuration ConditionalOnProperty(name…