控制日志的输出频率
背景
在实际的生产开发中,记录日志是非常重要的一步。记录日志的主要原因是方便排查和分析问题。当软件出现异常、运行缓慢或数据错误时,日志记录可以提供大量有价值的信息,帮助开发人员快速定位问题的原因和位置,并加速问题的修复过程。
但是记录日志不是越详细越好,不是内容越多越优质。日志输出到文件中会占有大量的IO性能,拖慢程序吞吐量,加快服务器硬盘消耗,内容过多也对我们查找日志带来了难度。
针对日志对性能的消耗问题,我们首先考虑的是异步日志,这确实效果显著。但满屏的响应报文对我们查找日志并不有利,这个问题异步日志没办法解决。
有时候我们想,能不能给日志的响应报文设置一下长度,这样一来能提高性能,二来能方便我们找日志。但是如果需要完整的响应报文怎么办?那我们就随机将一些响应报文的长度限制一下,并不是针对所有的响应报文。
具体地说,通过一个注解给定预设值,程序生成一个随机数,并将其与预定义的值进行比较,以确定是否应该截取该日志消息。通过这种方式,应用程序可以更细粒度地控制日志的输出,避免记录过多的冗余信息或无关紧要的日志消息,以便更快地排除应用程序的问题或故障。
开发步骤
1.注解
package com.example.logcontrol.annotation;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface LogControl {
int value() default 100;
}
2.响应日志切面
package com.example.logcontrol.advice;
import com.alibaba.fastjson2.JSON;
import com.example.logcontrol.annotation.LogControl;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Set;
@RestControllerAdvice
@Slf4j
public class ResponseResultAdvice implements ResponseBodyAdvice<Object> {
// 文字内容限制长度
private static final int RESPONSE_CONTENT_LENGTH = 200;
// return true表示对响应进行处理,你可以用returnType来做判断什么时候不需要做处理
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
String responseStr = JSON.toJSONString(body);
// 获取当前方法
Method method = returnType.getMethod();
// 是否被LogControl注解修饰
if (method.isAnnotationPresent(LogControl.class)) {
// 获得注解
LogControl logControl = method.getAnnotation(LogControl.class);
// 获得随机数
Random random = new Random();
int nextInt = random.nextInt(logControl.value());
// 当生成的随机数为0时,对日志长度进行控制
if (nextInt == 0) {
// 将body转成json字符串 再截取预设的长度
responseStr = JSON.toJSONString(body).substring(0, RESPONSE_CONTENT_LENGTH) + "...【内容太长啦】";
}
}
log.info("【调用URL】:【{}】,【--返回结果--】:【{}】", request.getURI().toString(), responseStr);
return body;
}
}
如果注解上配置的数字为1,那生成的随机数就永远是0,则意味着对该接口的响应报文都截取长度
3.测试接口
package com.example.logcontrol.controller;
import com.example.logcontrol.annotation.LogControl;
import com.example.logcontrol.domain.Result;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@PostMapping("/ping")
@LogControl(1)
public Result Ping(@RequestBody String testStr) {
String str =
"拯救你就是拯救全世界,因为你就是我的全世界\n" +
"你眼里的星辰大海,是我从未见过的皓月星空。\n" +
"我喜欢的你是最好的,你喜欢的他是最好的,最好的你应该和最好的他在一起\n" +
"一个从未见过的你,一件从未发生过的事,我们终于在一起~\n" +
"下次再想去环游世界,我就围着你转一圈就好了。\n" +
"说真的是想你。\n" +
"我想你了。\n" +
"猜到了你喜欢我,所以提前开心\n" +
"太阳总是照着月亮,即使月亮属于地球" +
"你不用多好,我喜欢你就好,我没有很好,你不嫌弃就好。\n" +
"我直视不了阳光,我可以直视你呀\n" +
"众多星星之间,我总是会想到你\n" +
"我们来玩123木头人吧!完了我输了,我心动了\n" +
"我的爱情长成你的样子。——苏亚伦\n" +
"妙语连珠是猎物支支吾吾才是喜欢\n" +
"世间万物皆苦,你明目张胆的偏爱就是救赎\n" +
"If you are still looking for that one person who will change you life ,take a look in the mirror.\n" +
"如果不是因为这世界有些古怪,我巴不得永远和你厮守在一起。\n" +
"从看到你就心跳加快的那一刻开始,我便知道纵使我在厉害也逃不出你的五指山了。";
return Result.SUCCESS(str);
}
}
4.运行效果
完整代码
移步代码仓库:【https://gitcode.net/interestANd/logcontroldemo.git】
如果你有好的建议,不要忘了push噢