实习成长:logback收集项目日志,实现日志告警机器人
实际上Appender可能是logback框架中最重要的组件之一,虽然Logger是记录日志的接口,但是如果一个Logger没有关联到任何Appender的话,那么这个Logger就无法记录任何信息。此外虽然logback提供了很多扩展点,但是在应用中,我们可能很少会扩展filter,很少扩展layout和encoder,但是我们扩展Appender的机会却是很多的
老规矩,首先上图,看一下Appender的大图景,这里要说明的是,实现Appender接口有2个base类,一个是AppenderBase,另一个是UnsynchronizedAppenderBase,这2个类非常接近,80%以上的代码都是相同的。如果我们自己要自定义Appender的话,只要写一个类继承自这2个base类就好
首先是有一个Appender接口,然后如上文所说,UnsynchronizedAppenderBase类实现了这个接口,但是它本身是一个抽象类,需要继承它才能得到真正的实现类。Appender接口继承了FilterAttachable接口,而UnsynchronizedAppenderBase类持有一个FilterAttachableImpl类,委托这个类来实现FilterAttachable接口里定义的方法
然后OutputStreamAppender是继承自UnsynchronizedAppenderBase的Appender实现类,虽然它已经不是抽象类了,但是实际也是不能直接使用的,它的实现类就是最常见的ConsoleAppender和FileAppender
只要自己使用过logback的朋友都知道,appender元素下面还需要配置encoder元素,这里的Encoder接口就是对应这个encoder元素的,因为其实Appender组件还不是最终实际记录日志信息的组件,它要委托encoder组件来完成LoggingEvent的格式化和记录
介绍完了大体的结构,我们接下来就看看,从Appender接口的doAppend()方法,是怎么一步步地最终记录日志的
首先是UnsynchronizedAppenderBase里面的doAppend()方法,它主要是记录了Status状态,然后检查Appender上的Filter是否满足过滤条件,最后再调用实现子类的appender()方法。很眼熟是吗,这里用到了一个设计模式——模板方法
Java代码 收藏代码
public void doAppend(E eventObject) { // WARNING: The guard check MUST be the first statement in the // doAppend() method. // prevent re-entry. if (Boolean.TRUE.equals(guard.get())) { return; } try { guard.set(Boolean.TRUE); if (!this.started) { if (statusRepeatCount++ < ALLOWED_REPEATS) { addStatus(new WarnStatus( "Attempted to append to non started appender [" + name + "].", this)); } return; } if (getFilterChainDecision(eventObject) == FilterReply.DENY) { return; } // ok, we now invoke derived class' implementation of append this.append(eventObject); } catch (Exception e) { if (exceptionCount++ < ALLOWED_REPEATS) { addError("Appender [" + name + "] failed to append.", e); } } finally { guard.set(Boolean.FALSE); } } abstract protected void append(E eventObject);
上面的代码非常简单,就不用说了,我们就直接看看实现类的append()方法是怎么实现的,这里我们选择OutputStreamAppender实现类
Java代码 收藏代码
@Override protected void append(E eventObject) { if (!isStarted()) { return; } subAppend(eventObject); }
首先检查一下这个Appender是否已经启动,如果没启动就直接返回,如果已经启动,则又进入一个subAppend()方法
Java代码 收藏代码
/** * Actual writing occurs here. * <p> * Most subclasses of <code>WriterAppender</code> will need to override this * method. * * @since 0.9.0 */ protected void subAppend(E event) { if (!isStarted()) { return; } try { // this step avoids LBCLASSIC-139 if (event instanceof DeferredProcessingAware) { ((DeferredProcessingAware) event).prepareForDeferredProcessing(); } // the synchronization prevents the OutputStream from being closed while we // are writing. It also prevents multiple thread from entering the same // converter. Converters assume that they are in a synchronized block. synchronized (lock) { writeOut(event); } } catch (IOException ioe) { // as soon as an exception occurs, move to non-started state // and add a single ErrorStatus to the SM. this.started = false; addStatus(new ErrorStatus("IO failure in appender", this, ioe)); } }
这个方法居然什么事也不干。。做了一些检查以后,又进入writeOut()方法。。。
Java代码 收藏代码
protected void writeOut(E event) throws IOException { this.encoder.doEncode(event); }
writeOut()方法委托配置给它的Encoder组件来记录
Java代码 收藏代码
public void doEncode(E event) throws IOException { String txt = layout.doLayout(event); outputStream.write(convertToBytes(txt)); outputStream.flush(); }
到这里,终于完了。Encoder组件又委托其Layout组件来将LoggingEvent进行格式化,返回一个String,然后通过OutputStream.write()方法,把格式化之后的日志信息写到目的地
耐心看到这里的朋友,可能已经有点被绕晕了,怎么Appender需要这么麻烦吗?其实我们这里说的只是ConsoleAppender的doAppend()全流程,并不是所有Appender都这么复杂的,当然也有一些更复杂的。。
下面看一个简单的Appender,就是我自己写的MyAppender
Java代码 收藏代码
public class MyAppender extends AppenderBase<LoggingEvent> { @Override protected void append(LoggingEvent eventObject) { System.out.println(eventObject.getMessage()); } }
好吧,非常简单是不是,如果把这个Appender配置到logback.xml中,那么当Logger.info()调用的时候,就会先走进AppenderBase类的doAppend()方法里,进行Filter校验等等,然后进入MyAppender的append()方法,不做其他的操作,直接把message给打印到Console上。当然,由于这个类是极度简化的,没有Encoder和Layout,也就没办法控制输出日志的时间,也没有办法对%thread等标记进行解析处理了。但是这个类可能可以很清晰地表达出,Appender组件是怎么工作的:由AppenderBase类来调用Filter链,然后由Appender实现类来委托Encoder解析LoggingEvent,再输出到目的地
实习成长:logback收集项目日志,实现日志告警机器人相关推荐
- 启动项目无法打印日志处理及logback简单使用
一.启动项目无法打印日志处理 运行maven web项目是提示如下代码 WARN No appenders could be found for logger 处理 在resources 目录下创建l ...
- golang练手项目日志收集项目(二)
项目介绍:日志收集项目 主要功能:收集日志并且可视化查询日志 开发环境 :windos+idea 项目描述:收集日志并且在可视化页面中查询日志信息 主要技术:etcd+kafka+ElasticSea ...
- Day3-T31项目 异常处理与日志——2021-11-02
Day3-T31项目 异常处理与日志 2021-10-30 按道理来说应该是在10月30号完成第三天的笔记,但是因为个人原因,要去学校办理实习的相关证书和表格耽误了,拖到现在补交.嘿嘿~ 起始站 Da ...
- springboot项目输入打印日志文件到本地
springboot项目输入打印日志文件到本地 pom.xml中添加jar包: <dependency><groupId>ch.qos.logback</groupId& ...
- Logback 配置文件这么写,日志 TPS 提高 10 倍
点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 作者 | 何甜甜在吗 来源 | juejin.im/post/5d4d61326fb9a06 ...
- Spring Boot(十)Logback和Log4j2集成与日志发展史
一.简介 Java知名的日志有很多,比如:JUL.Log4j.JCL.SLF4J.Logback.Log4j2,那么这些日志框架之间有着怎样的关系?诞生的原因又是解决什么问题?下面一起来看. 1.1 ...
- 收集、分析线上日志数据实战——ELK
本文来自网易云社区 作者:田躲躲 用户行为统计(User Behavior Statistics, UBS)一直是互联网产品中必不可少的环节,也俗称埋点.对于产品经理,运营人员来说,埋点当然是越多,覆 ...
- 项目中统一日志文件配置
1.统一日志处理的目的: 将日志记录在文件中,方便运维和开发做错误排查 文件日志需要做滚动输出(输出到更多的日志文件中),避免单日志体积过大,拖垮服务器 可以方便的在开发环境和生产环境等环境中切换输出 ...
- 系统集成项目需求调研日志
最近正在负责一个套产品的实施工作,虽然我们的产品在功能上已经覆盖的相对比较完善了,但是在某些地方还是不能满足个别客户个性化的需求,因此得对这种具有个性化需求的客户展开额外的需求调研工作.我们的产品实施 ...
- java常用日志框架日志门面及实现 SLF4J 、Jboss-logging 、JCL、Log4j、Logback、Log4j2、JUL,springboot集成 log4j、log4j2
java常用日志框架日志门面SLF4J .Jboss-logging .JCL.Log4j及实现 Logback.Log4j2.JUL,springboot集成 log4j.log4j2 .logba ...
最新文章
- linux 内核编译详解
- Vivado无法双击打开xpr工程文件的解决办法
- 数据结构与算法 / 红黑树
- 眺望全真互联时代!TVP音视频技术闭门会闪耀上海
- c语言sizeof和strlen哪个大,C语言的sizeof和strlen区别与联系
- 任务状态段TSS和TSS描述符
- LeetCode: Single Number I II
- 中文信息处理——使用结巴分词系统
- 智能手机之新手篇[转]
- 51单片机开发工具安装
- FANUC系统开发API(FOCAS2)pc应用开发,机加工领域
- 高校校园网建设方案【含网络拓扑图+拓扑结构图+配置命令】(详细版)
- 计算机在环境工程专业中的应用,计算机在环境科学与工程方向的应用.pdf
- 小提琴机器人拉法_手工小提琴价格,小提琴左手持琴姿势和肩托的使用
- Apple 等六大生态系统的崛起
- 计算机平面设计评分标准,竞赛各专业评分标准.DOC
- 【光学】Matlab模拟几何光学中的球差、彗差、像散、场曲四种像差
- 回收站清空的文件怎么恢复?学会这2招,简单又实用
- 三菱mode bus tcp通讯_泰州三菱MR-J4
- C语言图形库EasyX安装及基本使用
热门文章
- 计算机管理 窗口中找到 guest 用户,Guest 来宾用户不见了??
- Javascript特效:图片切换
- python中match用法_python re.match()用法相关示例
- FFmpeg学习(10)—— ffmpeg最全的命令参数
- 小目标到大目标一网打尽!阿里提出首个轻骨干重Neck的轻量级目标检测器GiraffeDet...
- ICCV 2021|“白嫖”性能的MixMo,一种新的数据增强or模型融合方法
- CNN已老,GNN来了:重磅论文讲述深度学习的因果推理(附资源)
- 如何使用git把本地代码上传(更新)到github上
- 字符串格式连接sqlserver数据库的字段概念解释
- spring boot 2.0.3+spring cloud (Finchley)1、搭建服务注册和发现组件Eureka 以及构建高可用Eureka Server集群...