问题描述

监控系统

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

日志,是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接口。

这是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的源代码。

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

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

装饰器模式

我们想到了装饰器模式。

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

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

定义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的方法进行切面处理。

slf4j 日志监控相关推荐

  1. SpringBoot入门建站全系列(二十八)整合Kafka做日志监控

    SpringBoot入门建站全系列(二十八)整合Kafka做日志监控 一.概述 Apache Kafka是一个分布式发布 - 订阅消息系统和一个强大的队列,可以处理大量的数据,并使您能够将消息从一个端 ...

  2. 【详解】 ELK (ElasticStack) 实现日志监控

    目录 ElasticStack 介绍: Demo 实现 说在前面 案例实现流程图 创建Spring Boot 项目 项目部署.运行 Logstash配置 FileBeat配置 ES配置 Kibana配 ...

  3. Java自动日志监控框架auto-log详解

    Java自动日志监控框架auto-log详解 1. 需求概述 2. auto-log简介 2.1 auto-log定义 2.2 auto-log目的 2.3 auto-log特性 2.4 注解说明 2 ...

  4. ELK 搭建 TB 级海量日志监控系统,这个太强了!

    欢迎关注方志朋的博客,回复"666"获面试宝典 作者:非洲羚羊 来源:cnblogs.com/dengbangpang/p/12961593.html 本文主要介绍怎么使用 ELK ...

  5. 简单分析MySQL 一则慢日志监控误报问题

    这篇文章主要介绍了MySQL 一则慢日志监控误报的问题分析与解决,帮助大家更好的理解和使用MySQL,感兴趣的朋友可以了解下 之前因为各种原因,有些报警没有引起重视,最近放假马上排除了一些潜在的人为原 ...

  6. 打造一个TB级微服务日志监控平台

    本文主要介绍怎么使用 ELK Stack 帮助我们打造一个支撑起日产 TB 级的日志监控系统.在企业级的微服务环境中,跑着成百上千个服务都算是比较小的规模了.在生产环境上,日志扮演着很重要的角色,排查 ...

  7. TB级微服务海量日志监控平台

    本文主要介绍怎么使用 ELK Stack 帮助我们打造一个支撑起日产 TB 级的日志监控系统.在企业级的微服务环境中,跑着成百上千个服务都算是比较小的规模了.在生产环境上,日志扮演着很重要的角色,排查 ...

  8. 如何打造一个TB级微服务海量日志监控平台

    前沿技术早知道,弯道超车有希望 积累超车资本,从关注DD开始 来源:性能与架构.图文编辑:xj 本文主要介绍怎么使用 ELK Stack 帮助我们打造一个支撑起日产 TB 级的日志监控系统.在企业级的 ...

  9. 深度学习核心技术精讲100篇(四十八)-TB级的日志监控系统很难?带你使用ELK轻松搭建日志监控系统

    前言 本文主要介绍怎么使用 ELK Stack 帮助我们打造一个支撑起日产 TB 级的日志监控系统.在企业级的微服务环境中,跑着成百上千个服务都算是比较小的规模了.在生产环境上,日志扮演着很重要的角色 ...

最新文章

  1. 互联网协议 — RIP 路由信息协议
  2. Hyper-V 配置网络 (高级篇)
  3. linux系统无法用命令行,无法在Linux操作系统上从命令行启动Kitchen Pentaho作业
  4. chrome默认为浏览器并且设置外部调用默认的启动参数
  5. 你可能不知道的小知识-bug为什么叫bug
  6. python生成相似句子_4种方法计算句子相似度
  7. python csv文件读取行列_使用Numpy读取CSV文件,并进行行列删除的操作方法
  8. oracle 数据导入 mysql_oracle数据库导出和oracle导入数据的二种方法(oracle导入导出数据)...
  9. Instruments-Automation: 通过命令行执行测试用例
  10. Server、Workstation服务无法启动(导致无法访问共享)
  11. Unity3D中背景音乐和相关音效的添加,背景音乐暂停、停止和播放的设置
  12. 为什么计算机二级查成绩显示验证码错误,我明明输入的是正确的验证码,为何电脑总显示验证码错误呢?...
  13. 解方程计算器,一款数学神器APP,有需要的自己收藏!
  14. 工业大数据:中国智造下的“数字新基建”
  15. 【从Java转C#】第八章:委托、lambda、事件
  16. 中移物联ML302开发板上手体验
  17. HackTheBox | Horizontall
  18. airbnb房东_麻烦找房东侵入式监视筛查方法可能是罪魁祸首
  19. 群策CRM解决方案,直击系统集成行业风口
  20. vue双向绑定失效的情况

热门文章

  1. 【FFmpeg】ffmpeg工具源码分析(四):filter(过滤器、滤镜)详解
  2. 【Ubuntu】解决ubuntu系统root用户下Chrome无法启动问题
  3. 【Qt】Qt再学习(十二):QGraphicsItem
  4. Ruby之Tempfile
  5. crontab 备份mysql数据库_crontab定时备份mySQL数据库
  6. 学计算机为什么会突发,为什么电脑会突然自动重启?
  7. Java项目:学生管理系统(java+Springboot+Maven+mybatis+Vue+Mysql)
  8. java中ContentArea_java中TextArea怎么加载指定路径的文本内容
  9. python数组越界_python 整数越界问题详解
  10. listen函数的第二个参数_【图像处理】OpenCV系列十七 --- 几何图像变换函数详解(一)...