大数跨境
0
0

强大!基于Spring Boot HTTP请求响应日志记录组件,值得一用

强大!基于Spring Boot HTTP请求响应日志记录组件,值得一用 Spring全家桶实战案例
2024-09-04
2
导读:强大!无所不能的SpringBoot请求响应日志记录组件

环境:Spring2.7.18



1. 简介

记录HTTP API请求响应日志对于监控、调试和性能优化至关重要。它帮助开发者追踪API的使用情况,包括请求来源、参数、响应状态码及耗时等,从而快速定位问题、分析用户行为及评估系统性能。在生产环境中,合理的日志记录策略能及时发现并预警潜在问题,减少故障影响。

在本篇文章中 我将介绍一款非常强大的Logbook库,它可为不同的客户端和服务器端技术提供完整的请求和响应日志。它允许开发人员记录应用程序接收或发送的任何 HTTP 流量。这可用于日志分析、审计或调查流量问题。

Logbook实用非常的简单,它针对spring boot提供了starter,根据你当前spring boot使用的版本引入不同版本的Logbook即可。

依赖管理

<properties>  <!--如果你使用的springboot2.x版本请引入2.16.0版本-->  <logbook.version>2.16.0</java.version>  <!--如果你使用的springboot3.x版本请引入3.9.0版本-->  <logbook.version>3.9.0</java.version></properties><dependency>  <groupId>org.zalando</groupId>  <artifactId>logbook-spring-boot-starter</artifactId>  <version>${logbook.version}</version></dependency>

注意:上面使用的版本说明;接下来进入实战案例。

2. 实战案例

根据上面,引入了相关的依赖后,还需要进行如下的配置

logging:  level:    org.zalando.logbook.Logbook: TRACE

调整Logbook日志级别为TRACE。

2.1 基本用法

根据上面配置的日志级别,接下来你可以不用做任何的配置,随意访问一个接口就能在控制台看到非常详细的信息

// 接口@GetMapping("/query")public Object query(String name, Integer id) {  return String.format("name = %s, id = %d", name, id) ;}

访问上面的接口,控制台输出如下:

这里看到了详细的请求/响应信息。再来个POST接口

@PostMapping("/save")public Book save(@RequestBody Book book) {  return book ;}

输出日志信息

同样请求/响应输出了详细的信息。

输出格式配置

以上日志是以HTTP格式输出,它还支持:curl,json,splunk格式。通过如下配置:

logbook:  format:    style: json

输出格式如下

日志输出策略

在上面的示例中,日志中包括了完整的请求信息,header+body,你可以通过如下进行配置:

logbook:  strategy: without-body

如上配置后,日志输出将不会有body信息。

排除URL

默认情况下会对所有的请求进行日志的记录,你可以通过如下配置自定义:

logbook:  exclude:  - /users/*  - /products/*

当请求匹配上面2个url模式时,将不会记录日志信息。

2.2 结合Logback

你还可以与Logback结合使用,将日志信息记录到文件当中,你只需要进行如下的配置即可。

在logback-spring.xml文件中如下配置:

<appender name="RequestLogger" class="ch.qos.logback.core.rolling.RollingFileAppender">  <file>logs/log_api_info.log</file>  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">    <fileNamePattern>${LOG_PATH}/log-api_info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>    <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">      <maxFileSize>20MB</maxFileSize>    </timeBasedFileNamingAndTriggeringPolicy>  </rollingPolicy></appender><logger name="org.zalando.logbook" level="TRACE" additivity="false">   <appender-ref ref="RequestLogger"/></logger>

有了上面的配置后,日志不会输出到控制台,而是记录到文件中,如下:

日志信息记录在该文件当中

2.3 自定义核心类Logbook

该库中最为核心的类是Logbook,几乎所有的配置都可以通过该类完成

@Beanpublic Logbook logbook() {  Logbook logbook = Logbook.builder()    .condition(Conditions.exclude(Conditions.requestTo("/users/*")        Conditions.contentType("application/json")))      .sink(new DefaultSink(new DefaultHttpLogFormatter(), new DefaultHttpLogWriter()))    .build();}

在该配置中,我们设定了/users/*请求的路径不会记录日志,请求的contentType必须是application/json类型。而这里的sink用来指定日志的格式及如何进行写入。

Logbook还有很多其它的配置项,具体请查看相应的API。

2.4 自定义日志输出Sink

直接实现 Sink 接口可以实现更复杂的用例,例如将请求/响应写入结构化的持久存储(如数据库)。

Logbook 提供了一些具有常用日志格式的 Sink 实现,即 CommonsLogFormatSink 和 ExtendedLogFormatSink。ChunkingSink 会将长信息分割成较小的块,并单独写入。

自定义Sink

@BeanLogbook logbook() {  Logbook logbook = Logbook.builder()    .condition(Conditions.exclude(Conditions.requestTo("/users/*")    .sink(new Sink() {      public void write(Correlation correlation, HttpRequest request, HttpResponse response) throws IOException {        System.err.println("==============================") ;        System.err.println("request header:\t" + request.getHeaders()) ;        System.err.println("request body:\t" + request.getBodyAsString()) ;        System.out.println() ;        System.err.println("response header:\t" + response.getHeaders()) ;        System.err.println("response body:\t" + response.getBodyAsString()) ;        System.err.println("==============================") ;      }    })    .build() ;  return logbook ;}

上面实现了一个非常简单的Sink,通过System直接将请求/响应内容输出到控制

2.5 与RestTemplate集成

默认Logbook提供了ClientHttpRequestInterceptor实现,并且注册为了bean。在创建RestTemplate对象时,我们只需要将其添加到RestTemplate中即可。如下示例:

@BeanRestTemplate logbookRestTemplate(LogbookClientHttpRequestInterceptor interceptor) {  RestTemplate restTemplate = new RestTemplate() ;  restTemplate.setInterceptors(Arrays.asList(interceptor)) ;  return restTemplate ;}

如上将logbook的拦截器添加到RestTemplate中,接下来在请求中,也会详细的记录日志。

@GetMapping("/remote")public Object remote() {  return this.logbookRestTemplate.getForObject("http://localhost:8010/books/666", Map.class) ;}

请求日志输出如下

以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

绝对让你大开眼界的Spring依赖注入问题

强大!SpringBoot几行代码生成word文档

真香!SpringBoot内置性能监控工具

当心!SpringBoot错误的数据绑定带来安全隐患

SpringBoot读取配置文件信息8种方式,你会哪几种?

在SpringBoot中拦截修改请求Body的2种正确方式

我给Spring提交一个Bug,已在最新版修复!请这样修复!

SpringBoot错误使用拦截器导致系统奔溃,发生OOM错误

放弃ThreadLocal!TTL真香

SpringBoot @Value注解这些高级玩法用过吗?

SpringBoot3优雅停止/重启定时任务

强大!SpringBoot结合STOMP简化数据实时通信

要不要升级?Java 21强大的新特性,代码量减半

SpringBoot多租户3种架构实现方案详解

OpenFeign高级用法:这些强大的功能你用过吗?

请一定牢记SpringBoot项目开发中的8个扩展接口

SpringCloud项目开发中实用技巧总结

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读195
粉丝0
内容832