log日志最佳实践

log日志最佳实践

1、占位符的使用

在进行日志打印的时候,推荐使用占位符进行字符串打印,而不是直接使用字符串拼接。原因:

  • 这样可以避免不必要的字符串拼接。使用占位符时,实际字符串拼接由日志框架在确定真正需要输出日之后才执行。例如,如果日志输出的是debug(),但是配置的是info级别,则不会执行字符串拼接
  • 减少临时对象创建。字符串拼接会产生多个临时String对象,而占位符方式通常由日志框架优化为更高效的内存处理方式
  • 更清晰的日志模版。日志输出模版和变量分离

接下来代码显示。定义实体类:

java 复制代码
@Setter
@Getter
public class User {

    public Integer age;
    private String name;
    public boolean gender;

    @Override
    public String toString() {
    	// 延迟10秒,为了查看延迟计算
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        sb.append("name:").append(name).append(",");
        sb.append("age:").append(age).append(",");
        sb.append("gender:").append(gender);
        sb.append("}");
        return sb.toString();
    }
}
java 复制代码
@Slf4j
public class Test {
    public static void main(String[] args) {
        User user = new User();
        user.setAge(15);
        user.setName("Jack");
        user.setGender(true);
        // 方式一:直接字符串拼接
        log.trace("output1:" + JSONUtil.toString(user));
        // 方式二:使用占位符进行输出。相比于第一种方式,更推荐这种进行日志打印
        log.trace("output2:{}", JSONUtil.toString(user));
	}
}

2、延迟计算

延迟计算就是只有真正进行日志打印的时候才会计算打印的内容。尤其是日志打印的内容特别的大或者是计算打印的日志内容特别的耗时。

模拟JSON序列化类:

java 复制代码
@Setter
public class JSONUtil {
	// 目标对象
    Object o;
	// 对目标对象简单序列化
    @Override
    public String toString() {
        return JSON.toJSONString(o);
    }
    
	// 对对象简单序列化
    public static String toString(Object o) {
        return o.toString();
    }
}

测试延迟计算:

java 复制代码
@Slf4j
public class Test {

    public static void main(String[] args) {
        User user = new User();
        user.setAge(15);
        user.setName("Jack");
        user.setGender(true);
        
        long start = System.currentTimeMillis();
        log.trace("output1:" + JSONUtil.toString(user));
        long end = System.currentTimeMillis();
        System.out.println("字符串拼接用时: " + (end - start) / 1000);

        start = System.currentTimeMillis();
        log.trace("output2:{}", JSONUtil.toString(user));
        end = System.currentTimeMillis();
        System.out.println("占位符加序列化用时: " + (end - start) / 1000);

        start = System.currentTimeMillis();
        log.trace("output3:{}", user);
        end = System.currentTimeMillis();
        System.out.println("占位符加自身toString用时: " + (end - start) / 1000);

        start = System.currentTimeMillis();
        JSONUtil jsonUtil1 = new JSONUtil();
        jsonUtil1.setO(user);
        log.trace("output4:{}", jsonUtil1);
        end = System.currentTimeMillis();
        System.out.println("占位符加自身toString调用JSON序列化用时: " + (end - start) / 1000);

    }
}

结果输出:

java 复制代码
字符串拼接用时: 10
占位符加序列化用时: 10
占位符加自身toString用时: 0
占位符加自身toString调用JSON序列化用时: 0

本文的日志级别为debug,所以这里使用的是trace()进行打印,就是为了不打印查看延迟计算效果。通过上面结果可以看出,只要字符串拼接或者是使用占位符,但是对打印对象进行操作都不会出发延迟计算,都是直接计算出结果再执行log日志打印。

延迟计算条件:

  • 使用占位符进行日志打印
  • 打印的变量不能在打印语句中执行任何方法、操作。直接输出变量

在最终确定日志打印的时候会调用打印变量的toString()方法进行字符串拼接输出。如果默认的toString()方法或者Lombok输出的toString()方法输出的不满足诉求【例如,elk需要严格的json】,要么重写,要么封装到另一个对象中,另一个对象toString()方法进行序列化,例如上述的JSONUtil。

相关推荐
一 乐1 小时前
家政服务管理系统|基于springboot + vue家政服务管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·家政服务管理系统
IT_陈寒1 小时前
Vite热更新失效?可能你在用Windows
前端·人工智能·后端
碳基硅坊2 小时前
Spring AI:把大模型接进 Spring 应用
java·人工智能·spring ai
椰椰椰耶2 小时前
[SpringCloud][14]OpenFeign参数传递方法
后端·spring·spring cloud
黄毛火烧雪下2 小时前
Java 核心知识点总结(一)
java·开发语言
onething3652 小时前
Spring Boot + Spring AI 从入门到实战:7天转型计划 Day 3 —— 消息表设计 + 级联删除 + 事务管理
人工智能·后端
荣江3 小时前
Hermes Agent 代码仓库打包工具使用指南(repomix-rs 高性能版)
后端
王某某人3 小时前
LangChain4j 入门:Java 程序员的第一个 AI 对话程序
人工智能·后端
码农刚子3 小时前
从零开始:在 Windows 服务器上部署 Node.js 项目(小白实战教程)
后端·node.js
Cache技术分享3 小时前
435. Java 日期时间 API - Clock 灵活获取当前时间
前端·后端