拓展Log4j基本尝试.md
来源:互联网 发布:mac下安装启动盘 编辑:程序博客网 时间:2024/06/02 02:01
上周老大让我拓展下apache的log4j,让其可以把日志内容当做事件,发送到消息队列当中,然后有专门的事件处理来订阅消息,同时事件处理程序和socket关联在一块。客户端通过socket请求日志信息,请求参数构成规则,来决定是否通过socket连接发送日志到客户端。
现在我们把焦点放在“如何在打印日志的时候发消息”,至于事件处理程序暂且不表。
这是一条基本日志信息:
2017-09-05 22:59:00 DEBUG [org.apache.activemq.util.ThreadPoolUtils] Forcing shutdown of ExecutorService: java.util.concurr
我最开始的想法是,将日志内容分为分为4部分:日期,级别,所属类,日志内容。用这4个内容作为规则判断。创建一个Log类:
public class Log implements Serializable{ protected Date date;//log日期 protected Level level;//log的级别 protected String clazz;//log所属的类全称 protected Object message;//log的内容
那么如何在打印日志的时候,获取到日志的这4个部分呢?我说一下我的思考过程。最开始打算包装Logger,在日志打印的最外层发送log事件;后来又尝试从打印的日志结果截取log对象发送;这些想法都比较蠢,没有从根本解决问题。昨天了解了log4j的执行流程,还有配置文件的规则和作用,找到了一种非常简单有效的实现方式,直达问题的本质。
一.简单的包装Logger类,在最外层发送log事件
public class NewLogger extends Logger { private Logger logger; public NewLogger(Logger logger){ super(logger.getName()); this.logger = logger; } public static NewLogger getNewLogger(Class clazz){ Logger log = getLogger(clazz); //TODO 可能还要检查NewLogger对象是否存在,存在就获取 return new NewLogger(log); } @Override public void trace(Object message) { logger.trace(message); sendLogEvent("TRACE", message); } @Override public void debug(Object message){ logger.debug(message); sendLogEvent("DEBUG", message); } @Override public void info(Object message) { logger.info(message); sendLogEvent("INFO", message); } @Override public void warn(Object message) { logger.warn(message); sendLogEvent("WARN", message); } @Override public void error(Object message) { logger.error(message); sendLogEvent("ERROR", message); } @Override public void fatal(Object message) { logger.fatal(message); sendLogEvent("FATAL", message); } /** * 载入发事件的动作 * */ protected void sendLogEvent(String level, Object message) { String className = logger.getName(); Level level_ = Level.toLevel(level); Log log = new Log(new Date(),level_,className,message); //发送事件 //sendEvent(log); }
这是最基本的思路,但是有明显的缺陷。第一,用NewLog构建的对象才能发消息,其他如框架,组件,库等使用Logger,或LoggerFactory的地方任然无法发送事件;第二NewLog是使用Logger对象完成日志的处理,Logger对象可以保证唯一性,同一个class多次构建Logger对象(Logger.getLogger(this.getClass());),也只会生成一个Logger对象,但是NewLogger还需要自己做校验,比较麻烦;第三,时间不准,上面的处理中是打印log之后,new了一个date对象作为时间,虽然有毫秒级的误差,但是终究不是正确的。
二、监听控制台Appender,得到一行行日志信息,将其格式化
看一下log4j.properties配置
log4j.rootLogger=debug, logFile, stdoutlog4j.appender.logFile=org.apache.log4j.DailyRollingFileAppender log4j.appender.logFile.DatePattern='.'yyyy-MM-dd log4j.appender.logFile.File=C://log/spring.log log4j.appender.logFile.layout=org.apache.log4j.PatternLayout log4j.appender.logFile.layout.ConversionPattern=%d - %m%n log4j.appender.logFile.Append=truelog4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p [%c] %m%n
我们获取stdout的Appender,监听它的输出,从管道中读出来
public void getLogInfo(){ Logger root = LogManager.getRootLogger(); if(root==null) return ; // 获取子记录器的输出源 Appender appender = root.getAppender("stdout"); // 定义一个未连接的输入流管道 PipedReader reader = new PipedReader(); // 定义一个已连接的输出流管理,并连接到reader Writer writer = null; try { writer = new PipedWriter(reader); } catch (IOException e) { e.printStackTrace(); } // 设置 appender 输出流 ((WriterAppender) appender).setWriter(writer); Scanner scanner = new Scanner(reader); while ( scanner.hasNextLine()) { try { //睡眠 Thread.sleep(100); String line = scanner.nextLine(); System.out.println("[+]================"+line); //TODO 格式化line得到Log对象 ; } catch (Exception ex) { //异常信息不作处理 } }}
这是一种本末倒置的做法,强烈不推荐。
这篇文章就到这里,下篇我会将一种聪明的做法。
- 拓展Log4j基本尝试.md
- 拓展log4j——在写日志时加入自己的逻辑.md
- Git 基本操作1.md
- MongoDB 基本操作尝试
- CoordinatorLayout+AppBarLayout+Toolbar简单玩法,MD的behavior简单尝试
- Log4j源码分析及配置拓展
- MD
- MD..
- md
- MD
- (MD)
- MD
- Log4j基本使用方法
- Log4j的基本应用
- Log4j基本使用方法
- log4j基本使用方法
- Log4j基本使用方法
- Log4j基本使用方法
- 单链表归并排序java
- Python + Splinter 实现自动化登录第一步中遇到的问题
- SQL语句优化技巧
- UEditor完整配置项
- 百家讲坛 王立群读史记之汉武帝
- 拓展Log4j基本尝试.md
- git 命令小记
- JavaScript中九九乘法表制作
- 数据库——区分date、datetime、time、timestamp的用法
- 数据仓库技术
- 数据库数据分表例子
- 动态规划 01背包问题
- UEditor定制工具栏图标
- 如何让网页设计看起来高大上?