In the development process, printing logs is essential, because logs are related to application troubleshooting, application monitoring, etc. Nowadays, slf4j is generally used for printing logs, because the use of the log facade helps to unify the printing method. Even if the log framework is changed later, it is very convenient. There are also related protocols in the Java Development Manual.

Therefore, in development, the following method is generally used to print logs.

 LOGGER.info("print: {}", "this is the log");

However, some applications will encapsulate LOGGER and finally write:

 LoggerUtil.info(LOGGER, "print: {}", "this is the log");

The main content of this article is to discuss why encapsulation is necessary, whether it is necessary to encapsulate, and how to encapsulate. If your friends have better suggestions, they can put forward and learn from each other.

Why encapsulate

Many people think that slf4j is originally a log facade, and it has been packaged very well. Why do you need to make an extra effort to package an additional one LoggerUtil ?

In fact, this is also stated in the development specification:

If it is not encapsulated, it will be written as follows:

 if (LOGGER.isInfoEnabled()) {
    LOGGER.info("print: {}", "this is the log");
}

Therefore, the general encapsulation is to uniformly encapsulate the logic of if judgment into a tool class.

There may be some friends here who don't quite understand why the if judgment is added. You can look at the following code:

It can be seen that the conversion logic is relatively complex and time-consuming. This is just a simulated scenario. There may be other situations in actual use, such as the parameters of the printing method and the time-consuming calculation:

 LOGGER.info("xxx 方法请求参数为:{}", JSON.toJSONString(req));
LOGGER.info("xxx 执行耗时:{}ms", System.currentTimeMillis() - startTime);

In some scenarios, in order to improve performance, the log needs to be turned off, such as big promotions, spikes, and so on.

Speaking of which, I believe that my friends have already seen the problem, because in this way, when I close the log printing, I only close the disk output, but the time-consuming logic will continue to execute.

 # 日志级别调整到 error
logging.level.com.liuzhihang=error

This is why it is recommended that you make judgments by hand in the development specification. Although the log framework helps us make judgments, it just avoids printing and outputting logs. In fact, things like assembling logs, serializing instance objects, etc. will still be executed.

logback 框架中的判断逻辑

Of course, if the current application only has single-digit tps or tpm, then there is no need to consider these, and there is no need to give up food because of choking, just use it normally.

how to encapsulate

In order to avoid the problem of if judgment every time, the if module is encapsulated as a tool class:

The above package effectively avoids the need to make judgments every time, just replace the print log in the code with LogUtil:

But this situation can only avoid the if judgment when printing 既有参数 , which has no effect on the method type. Here you need to use Supplier :

Actual use effect:

The above is only one encapsulation method, other encapsulations can be considered by themselves, such as encapsulation of the entire log framework.

other use

This part of the package is also reflected in log4j-api-2.17.2.jar , but there is no package in Supplier support, you can read the source code yourself for detailed implementation.

Then why slf4j does not support it, there is actually a discussion, you can see issue #70 , which has a series of discussions.

The end result is support for the Fluent Logging API syntax in 2.0.

slf4j 2.0 use

 <!-- slf4j 2.0 依赖 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>2.0.0</version>
</dependency>

You can use it directly according to the use case of the official document:

 logger.atDebug()
    .setMessage("Temperature set to {}. Old value was {}.")
    .addArgument(() -> t16()).addArgument(oldT)
    .log();

Why do you want to write this? It can only be said that the API design of others is like this. Of course, there are other considerations. You can look at the github issue. Which one to use, whether to use encapsulation, etc., these are all used according to your actual situation.

This article is published by mdnice Multiplatform


程序员小航
99 声望58 粉丝