基于log4j的消息流的实现之一消息获取
需求:
目前的程序中都是基于log4j来实现日志的管理,想要获取日志中的一部分消息,展示给用户。
约束:
由于程序中除了自己开发的代码,还会有层层依赖的第三方jar中的日志输出。需要展示给用户的消息,也有部分包括在第三方的包中。不可能去修改第三方jar来获得消息,所以只能从Log4j本身的消息入手,获取log4j的消息来进行处理。
方案:
第一步,增加新的logger
1 log4j.rootLogger=INFO, console 2 3 log4j.appender.console=org.apache.log4j.ConsoleAppender 4 log4j.appender.console.layout=org.apache.log4j.PatternLayout 5 log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-20c %X{key} %x - %m%n 6 7 log4j.logger.hermes=INFO, hermes 8 log4j.appender.hermes=org.apache.log4j.ConsoleAppender 9 log4j.appender.hermes.layout=org.apache.log4j.PatternLayout 10 log4j.appender.hermes.layout.ConversionPattern=%X{key} %x %m%n 11 12 log4j.logger.org.apache.flink.yarn=INFO, hermes
如上,第1行定义了一个全局的logger,这个没有疑义,所有的日志都会输出到这个logger。
关键是第7行,又定义了一个叫hermes的logger,它有一个同名的appender叫hermes,简化了他的layout,只是拿出必须的输出日志即可。注意这里有一个%X{key}的配置项,这里是为了拿到MDC的值,好区分这条消息是哪个session打印出来的。
第12行也很关键,将包org.apache.flink.yarn的日志都按照hermes是标准输出,这里是包名,当然也可以指定到具体的类名。
如此这样,对于包org.apache.flink.yarn中的日志,会打印两份,一份是以console的形式输出,一份是以hermes的形式输出。
当然,我们不希望在日志中见到两行实质上一样的内容,这就是第二步要做到事情。
第二步:截取消息
这里有两个方案:一个方案是自定义appender,获取消息;一个方案是获取指定的logger,获取消息。
方案1:自定义appender
1 import org.apache.log4j.AppenderSkeleton; 2 import org.apache.log4j.LogManager; 3 import org.apache.log4j.spi.LoggingEvent; 4 import org.slf4j.Logger; 5 import org.slf4j.LoggerFactory; 6 7 public class AdapterAppender extends AppenderSkeleton { 8 @Override 9 protected void append(LoggingEvent loggingEvent) { 10 String message = this.layout.format(loggingEvent); 11 System.out.println("<<<<<<<<<<***********"+message+"***********>>>>>>>>>>"); 12 } 13 14 @Override 15 public void close() { 16 17 } 18 19 @Override 20 public boolean requiresLayout() { 21 return true; 22 } 23 }
自定义appender还是很简单的,只要继承AppenderSkeleton即可。其中的append方法就可以拿到日志消息,标准化之后就可以拿来用了。
当然,上面log4j的配置也就需要改下了:
log4j.appender.hermes=cn.123.flink.log.AdapterAppender
方案2:获取logger来获取消息
1 import java.io.IOException; 2 import java.io.PipedReader; 3 import java.io.PipedWriter; 4 import java.io.Writer; 5 import java.util.Scanner; 6 7 import org.apache.log4j.*; 8 9 public class LogAppender extends Thread{ 10 11 private PipedReader reader; 12 13 public LogAppender(String appenderName) { 14 try { 15 Logger root = Logger.getLogger(appenderName); 16 // 获取子记录器的输出源 17 Appender appender = root.getAppender(appenderName); 18 // 定义一个未连接的输入流管道 19 reader = new PipedReader(); 20 // 定义一个已连接的输出流管理,并连接到reader 21 Writer writer = new PipedWriter(reader); 22 // 设置 appender 输出流 23 ((WriterAppender) appender).setWriter(writer); 24 }catch (IOException ioe){ 25 ioe.printStackTrace(); 26 } 27 } 28 29 @Override 30 public void run() { 31 // 不间断地扫描输入流 32 Scanner scanner = new Scanner(reader); 33 // 将扫描到的字符流显示在指定的JLabel上 34 while (scanner.hasNextLine()) { 35 try { 36 String line = scanner.nextLine(); 37 System.out.println("*****************************"+line); 38 //睡眠 39 Thread.sleep(100); 40 } catch (Exception ex) { 41 System.out.println("Exception from LogAppender:"+ex.getMessage()); 42 } 43 } 44 } 45 }
对比上面的日志的配置,13行的构造函数就可以传入hermes来获取hermes这个logger。
参考了下面的文档:
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/NDC.html
https://logging.apache.org/log4j/2.x/manual/thread-context.html
http://yshjava.iteye.com/blog/1325036
https://stackoverflow.com/questions/2763740/log4j-log-output-of-a-specific-class-to-a-specific-appender
https://stackoverflow.com/questions/5549838/get-live-log4j-messages
https://sysgears.com/articles/how-to-redirect-stdout-and-stderr-writing-to-a-log4j-appender/
转载于:https://www.cnblogs.com/029zz010buct/p/9449097.html
基于log4j的消息流的实现之一消息获取相关推荐
- Storm概念学习系列之Stream消息流 和 Stream Grouping 消息流组
不多说,直接上干货! Stream消息流是Storm中最关键的抽象,是一个没有边界的Tuple序列. Stream Grouping 消息流组是用来定义一个流如何分配到Tuple到Bolt. Stre ...
- [蓝牙] 6、基于nRF51822的蓝牙心率计工程消息流Log分析(详细)
开机初始化Log Log编号 函数名 所在文件名 1 000001: main ..\main.c 2 000002: timers_init ..\main.c 3 000003: gpiote ...
- 腾讯基于 Flink 的实时流计算平台演进之路
原文地址:https://www.infoq.cn/article/TjDeQDJQpKZ*NpG71pRW 大家好,我是来自腾讯大数据团队的杨华(vinoyang),很高兴能够参加这次北京的 QCo ...
- 基于docker微服务架构_使用基于微服务的流架构更好地进行大规模的复杂事件处理(第1部分)...
基于docker微服务架构 基于微服务的流架构与开源规则引擎相结合,使实时业务规则变得容易 这篇文章旨在详细介绍我将OSS业务规则引擎与Kafka风格的现代流消息传递系统集成在一起的项目. 该项目的目 ...
- 使用基于微服务的流架构更好地进行大规模的复杂事件处理(第1部分)
基于微服务的流架构与开源规则引擎相结合,使实时业务规则变得容易 这篇文章旨在详细说明我将OSS业务规则引擎与Kafka风格的现代流消息传递系统集成在一起的项目. 该项目的目标(即众所周知的复杂事件处理 ...
- 使用gRPC的.NET Core 3.0双向消息流
目录 介绍 软件描述 服务器基础结构(GrpcServerHelper) 客户基础设施(GrpcClientHelper) GrpcServer和GrpcClient 运行示例 结论 下载源码 - 2 ...
- 基于上下文的业务流建模法(二)
一.背景 上一篇文章说到了我提出了一种新的建模方法,并对建模方法的大概内容做了阐述,本次我将继续对这个建模方法做进一步的说明,并提供一个小小的案例来熟悉一下建模套路.下一篇文章将通过其他案例来展示这种 ...
- tcp实时传输kafka数据_将物联网数据和MQTT消息流式传输到Apache Kafka
Apache Kafka是一个实时流媒体平台,在大型和小型组织中得到广泛采用.Kafka的分布式微服务架构和发布/订阅协议使其成为在企业系统和应用程序之间移动实时数据的理想选择.据一些人称,超过三分之 ...
- 《新程序员》杂志|李鹏辉谈开源云原生消息流系统
本文出自<新程序员·云原生和全面数字化实践>. 作者李鹏辉,Apache Pulsar PMC 成员,StreamNative 首席工程师.责编 CSDN 唐小引. 随着业务与环境的变化, ...
最新文章
- Python爬虫之破解百度翻译--requests案例详解(一)
- 2013汇总计算 广联达gcl_完整工程量计算书分享:广联达+EXCEL计算表+电子+工程模板等赠送...
- CTF--misc 零宽度字符隐写
- linux查代替命令,Linux下查/删/替 命令(转)
- java牛客排序算法题_《剑指offer》面试题28:字符串的排列(牛客网版本) java...
- Vue 开发中常见报错与处理
- mysql jsp分页技术_一个非常简单的分页技术MYSQL JSP 利用了mysql的LIMIT参数
- 06-JavaScript的流控制语句
- rabbitmq多个消费者同时接收_提升RabbitMQ消费速度的一些实践
- 安装SQLServer2008后Windows防火墙上的端口开放
- 从完美KL距离推导VAE
- C语言malloc函数详解
- win7计算机打印机共享权限设置,win7共享打印机(没有权限访问)
- 小米组织变革:新设三大部门,推进“手机X AIOT”战略落地
- ofbiz UOM Conversion Relationship Not Found [单位转化关系没有找到] 问题解决:
- use of undeclared identifier ‘CV_HAAR_DO_ROUGH_SEARCH‘
- 路由器NAT 类型检测实现
- 【微信小程序】-- 全局配置 -- window - 下拉刷新 上拉触底(十六)
- java数字签名(签名生成,用证书验证签名)
- python超声成像仿真_超声合成孔径成像
热门文章
- 民生证券手机网上开户流程
- 【uoj207】 共价大爷游长沙
- C# html转mht
- Quote Form OnLoad Implement Add Leftnav, count Activities
- ASP.NET MVC+LINQ开发一个图书销售站点(6):创建数据层
- Linux---单例模式
- icmp协议_CCNA - Part7:网络层 - ICMP 应该是你最熟悉的协议了
- Field userManageService in com....
- 失眠,很困但是睡不着怎么办?
- 早上起床后喝的第一杯水最好选择白开水