Logback 整合 RabbitMQ 实现统一日志输出
一、前言
公司项目做了集群实现请求分流,由于线上或多或少会出现请求失败或系统异常,为了查看失败请求的日志信息,我们得将所有服务的日志文件都打开来进行问题的定位分析,操作起来非常麻烦。因此,我们开发组决定设计一套日志查看系统来解决上述问题。
二、实现思路
默认的,应用服务日志信息会保存在本地服务器的目录中,为了方便查看日志我们应该把多台服务器日志统一输出到一个日志文件中。
由于项目使用的 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"
}}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 application.properties 文件
spring.rabbitmq.host=192.168.2.13
spring.rabbitmq.port=5672
spring.rabbitmq.username=light
spring.rabbitmq.password=light
# 4.3 日志文件
名为 logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false"><!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="d:/" /><springProperty name="rabbitmqHost" source="spring.rabbitmq.host"/>
<springProperty name="rabbitmqPort" source="spring.rabbitmq.port"/>
<springProperty name="rabbitmqUsername" source="spring.rabbitmq.username"/>
<springProperty name="rabbitmqPassword" source="spring.rabbitmq.password"/><!-- 控制台输出 -->
<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地址 -->
<host>${rabbitmqHost}</host>
<port>${rabbitmqPort}</port>
<username>${rabbitmqUsername}</username>
<password>${rabbitmqPassword}</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.4 测试类
自定义异常:
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 实现统一日志输出相关推荐
- 接口自动化系列一: Pytest 夹具统一鉴权, 统一日志输出
统一鉴权的意义 接口自动化一般需要登录获得鉴权信息, 供各个suite和case使用, 因此登录鉴权适合定义在Session级别的夹具中, 供所有用例共享. 示例: @pytest.fixture(s ...
- SpringBoot/Cloud AOP 统一日志输出
文章目录 1. 导入依赖 2. aop拦截器 3. logback配置 4. 测试类 5. 关键点 6. 效果图 1. 导入依赖 <!-- AOP --><dependency> ...
- Java项目如何统一日志框架?
在程序运行的过程中,我们需要在重要的代码逻辑分支点,将关键的程序运行状态信息打印出来,便于我们对程序调试和观察.java项目中有成熟高性能的日志框架,很方便地集成到项目中实现我们对关键信息的打印输出. ...
- log4j 禁止类输出日志_SpringBoot统一日志处理原理
阅读推荐 程序员跳槽时机已到,闲聊中面试官无意泄题 SpringBoot作为日常开发利器,开箱即用,大量的star等已经成为节省开发的重要框架之一,但是各个框架的star中引入的日志框架却不尽相同,有 ...
- MDC日志logback整合使用
MDC日志logback整合使用 为什么使用MDC记录日志? 场景: 由于我的搜索服务并发量比较高,而处理一次搜索请求需要记录多个日志,因此日志特别多的情况下去查一次搜索整个日志打印情况会比较复杂. ...
- 实现Log4j和Logback的统一日志封装与动态日志级别调整
一.背景 项目中使用日志的地方非常广泛, 如果要做统一的处理,比如调整格式, 增加信息打印, 要修改很多地方,难以维护,所以需要能够将日志做一个统一的封装, 便于扩展使用:同时想做到动态调整日志级别, ...
- log4j和logback的冲突导致日志输出异常
2019独角兽企业重金招聘Python工程师标准>>> 前一阵在在项目中碰到一个日志问题.工程使用的是log4j,log4j.xml中也配置了工程日志路径和策略,并把日志级别定为wa ...
- java 使用logback进行日志输出
在java项目中使用logback可以非常方便的进行日志输出,logback的使用方法与log4j非常类似:使用logback所需要的jar包包括: logback-classic-1.0.13.ja ...
- logback指定不同包下的日志输出到不同的文件
<?xml version="1.0" encoding="UTF-8"?> <!--~ Copyright (c) 2018-2025, l ...
最新文章
- easyui框架前后端交互_easyui前后端分离
- html批量转doc linux,HTML+CSS入门 Linux下如何批量将md文件转换为html文件
- mac 内核调试环境搭建
- python语言程序设计实践教程实验八答案_清华大学出版社-图书详情-《Java程序设计教程及实验指导》...
- 试戴系统完全开放—zoomla!逐浪cms在后4.6时代的又一个亮点
- Python字符串count()
- 如何找出当前占用磁盘io 最多的进程 - linux,如何找出当前占用磁盘IO最多的进程...
- 桌面下雪软件测试工程师,Win7系统如何设置桌面下雪屏保?
- 安装svn + vs code配置svn
- go 的基本命令详解
- LaTeX 文档类型
- javascript写的日历控件(收藏)
- linux进阶之道 pdf,PDF
- win7系统安装高版本node
- [08006][17002] io 错误: the network adapter could not establish the connection (connection_id=qdoc1bwg
- 大数据Q1741班女孩们的技术博客链接
- C语言程序与设计:篮球游戏
- SRS4.0源码分析-RTMP延迟
- python如何取0到无穷大_python如何表示无穷大
- IE和Firefox兼容性