Logback 整合 RabbitMQ 实现统一日志输出
原文地址:Logback 整合 RabbitMQ 实现统一日志输出
博客地址:http://www.extlight.com
一、前言
公司项目做了集群实现请求分流,由于线上或多或少会出现请求失败或系统异常,为了查看失败请求的日志信息,我们得将所有服务的日志文件都打开来进行问题的定位分析,操作起来非常麻烦。因此,我们开发组决定设计一套日志查看系统来解决上述问题。
二、实现思路
默认的,应用服务日志信息会保存在本地服务器的目录中,为了方便查看日志我们应该把多台服务器日志统一输出到一个日志文件中。
由于项目使用的 Logback 日志框架和 RabbitMQ 消息队列,这两者正好可以进行整合。
因此,我们可以将项目代码中的日志输出到 RabbitMQ 队列中,通过 Logstash 读取队列数据,最后再输出到一个日志文件中。
三、准备环境
测试环境:IP 为 192.168.2.13 的 CentOS 7 系统
3.1 RabbitMQ 配置
首先需要搭建 RabbitMQ 环境,可以参考本站《CentOS 7.2 安装 RabbitMQ》进行搭建。
搭建完成后,登录 RabbitMQ 的管理界面,需要操作如下步骤:
- 创建一个名为 log_queue 的队列
- 创建一个名为 rabbit.log 的交换器(direct 类型)
- 将 log_queue 队列绑定到 rabbit.log 交换机上
操作演示图:

3.2 Logstash 配置文件
本站也有 Logstash 相关的博文,读者可移至 《Logstash 基础入门》 查看。
input {
rabbitmq {
type =>"all"
durable => true
exchange => "rabbit.log"
exchange_type => "direct"
key => "info"
host => "192.168.2.13"
port => 5672
user => "light"
password => "light"
queue => "log_queue"
auto_delete => false
}
}
output {
file {
path => "/usr/test-log/test-%{+YYYY-MM-dd}.log"
codec => multiline {
pattern => "^\d"
negate => true
what => "previous"
}
}
}
注意: multiline 是 Logstash 的插件,需要手动安装。
配置表示 Logstash 服务从 RabbitMQ 读取日志信息,输出到指定的目录文件中。
四、编码
4.1 依赖
列出主要依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
</dependency>
4.2 日志文件
名为 logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="d:/" />
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出,%d:日期;%thread:线程名;%-5level:级别,从左显示5个字符宽度;%msg:日志消息;%n:换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<appender name="RABBITMQ"
class="org.springframework.amqp.rabbit.logback.AmqpAppender">
<layout>
<pattern><![CDATA[ %d %p %t [%c] - <%m>%n ]]></pattern>
</layout>
<!--rabbitmq地址 -->
<addresses>192.168.2.13:5672</addresses>
<username>light</username>
<password>light</password>
<declareExchange>true</declareExchange>
<exchangeType>direct</exchangeType>
<exchangeName>rabbit.log</exchangeName>
<routingKeyPattern>info</routingKeyPattern>
<generateId>true</generateId>
<charset>UTF-8</charset>
<durable>true</durable>
<deliveryMode>NON_PERSISTENT</deliveryMode>
<autoDelete>false</autoDelete>
</appender>
<logger name="com.light.rabbitmq" level="info" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="RABBITMQ"/>
</logger>
<!-- 日志输出级别,level 默认值 DEBUG,root 其实是 logger,它是 logger 的根 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="RABBITMQ" />
</root>
</configuration>
配置中的 exchangeType 和 exchangeName 就是我们上边创建的交换机的类型和名称。
4.3 测试类
自定义异常:
public class CustomException extends RuntimeException{
private static final long serialVersionUID = 1L;
private int code;
private String msg;
public CustomException(int code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
模拟打印日志:
@Component
public class DemoTask {
private static Logger logger = LoggerFactory.getLogger(DemoTask.class);
private int num = 1;
@Scheduled(fixedRate = 3000)
public void writeLog() {
try {
if (num % 5 == 0) {
throw new CustomException(500, "自定义异常错误");
}
logger.info("==={}===={}","hello rabbitmq", System.currentTimeMillis());
num++;
} catch (CustomException e) {
e.printStackTrace();
logger.error("=={}==", e);
}
}
}
五、代码测试
执行启动类:
@EnableScheduling
@SpringBootApplication
public class RabbitmqTestApplication {
public static void main(String[] args) {
SpringApplication.run(RabbitmqTestApplication.class, args);
}
}
执行结果如下图:

代码运行的日志信息已经输出到指定日志文件中了。
补充
由于多台服务器的日志都打印到同一个文件,为了区分日志来源,我们还得需要打印出日志信息对应的主机 ip 地址。具体实现步骤如下:
- 自定义日志转换器
需要继承 ClassicConverter 类
public class CustomLogConverter extends ClassicConverter {
public String convert(ILoggingEvent event) {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return null;
}
}
- 修改 logback-spring.xml 文件
以下只张贴关键配置信息
<conversionRule conversionWord="ip" converterClass="com.light.rabbitmq.log.CustomLogConverter" />
<appender name="RABBITMQ"
class="org.springframework.amqp.rabbit.logback.AmqpAppender">
<layout>
<pattern><![CDATA[%ip %date{yyyy-MM-dd HH:mm:ss} | %highlight(%-5level) | %yellow(%thread) | %green(%logger) | %msg%n ]]></pattern>
</layout>
</appender>
Logback 整合 RabbitMQ 实现统一日志输出的更多相关文章
- Spring AOP实现统一日志输出
目的: 统一日志输出格式 思路: 1.针对不同的调用场景定义不同的注解,目前想的是接口层和服务层. 2.我设想的接口层和服务层的区别在于: (1)接口层可以打印客户端IP,而服务层不需要 (2)接口层 ...
- 2.logback+slf4j+janino 配置项目的日志输出
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.创建项目 参考:http://www.cnblogs.com/yysbolg/p/6898453.html 2 ...
- springboot 学习之路 4(日志输出)
目录:[持续更新.....] spring 部分常用注解 spring boot 学习之路1(简单入门) spring boot 学习之路2(注解介绍) spring boot 学习之路3( 集成my ...
- Hibernate日志输出到SLF4J
一,Hibernate日志问题 工程使用SLF4J,但日志文件一直没有看到Hibernate相关日志及showsql 二,Logback文件配置 修改Hibernate 日志输出指定为SLF4J,当修 ...
- springboot(二).springboot整合logback用于日志输出
springboot整合logback用于日志输出 我们项目的基本框架已经完成,http请求已经可以访问,现在给我们的框架添加日志记录的功能并能将每天的记录记录到文件中去 在这里,我们使用logbac ...
- SpringBoot系列(十三)统一日志处理,logback+slf4j AOP+自定义注解,走起!
往期精彩推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配置文件详解 SpringBoot系列(四)we ...
- springboot+logback日志输出企业实践(上)
目录 1.引言 2.logback简介 3. springboot默认日志框架-logback 3.1 springboot示例工程搭建 3.2 日志输出与基本配置 3.2.1 日志默认输出 3.2. ...
- 使用logback.xml配置来实现日志文件输出
转自:http://sungang-1120.iteye.com/blog/2104296 Logback是由log4j创始人设计的又一个开源日志组件.logback当前分成三个模块:logback- ...
- logback KafkaAppender 写入Kafka队列,集中日志输出.
为了减少应用服务器对磁盘的读写,以及可以集中日志在一台机器上,方便使用ELK收集日志信息,所以考虑做一个jar包,让应用集中输出日志 网上搜了一圈,只发现有人写了个程序在github 地址:https ...
随机推荐
- Error Code: 1175. You are using safe update mode and you tried to ......
MySQL提示的错误信息: Error Code: 1175. You are using safe update mode and you tried to update a table witho ...
- 判断回文字符串(c,python)
回文字符串:一个字符串,不论是从左往右,还是从右往左,字符的顺序都是一样的(如abba,abcba等) 判断回文字符串比较简单,即用两个变量left,right模仿指针(一个指向第一个字符,一个指向最 ...
- Grep console 设置
Grep console DEBUG 9961B8 INFO 4B5E76 WARN 8A8A00 ERROR 9F6B00 8A7674
- notepad++设置右键
Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\*\Shell\NotePad++][HKEY_CLASSES_ROOT\*\Shell\ ...
- Idea检入boss项目
Idea检入boss项目
- httpclient cookie相关介绍
http状态管理 cookie是HTTP代理和目标服务器可以交流保持回话的状态信息的令牌或短包. httpclient使用Cookie接口来代表抽象的cookie令牌,在它的简单形式中http的coo ...
- bzoj1053&&51nod1060
题解: 其实就是求1-n之中拥有最多约数的数 一个数x的质因数分解为p1^e1*p2^e2*...*pn^en,则正因数的个数为(e1+1)(e2+1)...(en+1) 那么发现,正因数的个数和p没 ...
- 设置xml中控件的圆润边框效果
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http: ...
- NodeJS之express的路由浅析
路由路径和请求方法一起定义了请求的端点,它可以是字符串.字符串模式或者正则表达式.后端在获取路由后,可通过一系列类似中间件的函数去执行事务. 可使用字符串的路由路径: // 匹配根路径的请求 app. ...
- 经典T-SQL代码
1. N到M条记录(要有主索引ID)SelectTop M-N *From [Table] Where ID in (SelectTop M ID From [Table]) Orderby ID ...