这是一个或许对你有用的社群
一对一交流/面试小册/简历优化/求职解惑,欢迎加入「」知识星球。下面是星球提供的部分资料:
这是一个或许对你有用的开源项目
国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。
功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号等等功能:
【国内首批】支持 JDK 21+ SpringBoot 3.2.2、JDK 8 + Spring Boot 2.7.18 双版本
logback, log4j2 等都是非常优秀的日志框架, 在日常使用中,我们很少会关注去使用哪一个框架, 但其实这些日志框架在性能方面存在明显的差异。
尤其在生产环境中, 有时候日志的性能高低,很可能影响到机器的成本, 像一些大企业,如阿里、腾讯、字节等,一点点的性能优化,就能节省数百万的支出。
再次, 统一日志框架也是大厂常有的规范化的事情, 还可以便于后续的ETL流程, 因此,我们选一个日志框架,其实还是比较重要的。
笼统的讲就是slf4j是一系列的日志接口,而log4j logback是具体实现了这些接口的日志框架,也可以简单理解为 slf4j 是接口, logback 和log4j是slf4j的具体实现, slf4j 具备很高的易用性和很好的抽象性。
使用SLF4J编写日志消息非常简单。首先需要调用 LoggerFactory 上的 getLogger 方法来实例化一个新的 Logger 对象。一共有两种方法:
方法1:使用lombok (推荐)
直接在类上打上lombok的注解, 这个方法是最简单,代码量最小,编程效率最高的, 而且lombok组件在很多场景都很好用,
@Slf4j
public class Main {}
方法2:直接使用
使用 org.slf4j.LoggerFactory 的 getLogger 方法获取logger实例,注意推荐 private static final
private static final Logger LOG = LoggerFactory.getLogger(Main.class);
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
从上图可以得出两个结论:
“
tips:
已知的影响效率的是,打出方法名称和行号都会显著降低日志输出效率, 如我们单单去掉 行号,在单线程情况下, log4j2 的性能相差一倍多。
见下图:
CPU AMD Ryzen 5 3600 6-Core Processor Base speed: 3.95 GHz
Memory 32.0 GB Speed: 2666 MHz
<log4j.version>2.22.1</log4j.version>
<logback.version>1.4.14</logback.version>
<!-log4j2 的配置 -->
<Property name="log.pattern">[%d{yyyyMMdd HH:mm:ss.SSS}] [%t] [%level{length=4}] %c{1.}:%L %msg%n</Property>
<!-logback 的配置 -->
<pattern>[%date{yyyyMMdd HH:mm:ss.SSS}] [%thread] [%-4level] %logger{5}:%line %msg%n</pattern>
长度大约 129个字符,常见长度 输出到文件 app.log, 格式统一, 一模一样
[20240125 16:24:27.716] [thread-3] [INFO] c.w.d.Main:32 main - info level ...this is a demo script, pure string log will be used!
[20240125 16:24:27.716] [thread-1] [INFO] c.w.d.Main:32 main - info level ...this is a demo script, pure string log will be used!
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
pom 文件, 不需要做任何事情, spring官方默认使用logback, 非spring项目可以直接引入下面的xml, 同时包含logback 和slf4j
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
配置文件放置位置: src/main/resource/logback.xml,样例如下:
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<file>log/output.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>log/output.log.%i</fileNamePattern>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>1MB</MaxFileSize>
</triggeringPolicy>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>
由于spring官方默认使用logback,因此我们需要对spring默认的依赖进行排除然后再引入以下依赖:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>${log4j.version}</version>
</dependency>
配置文件放置位置: src/main/resource/log4j2.xml, 样例如下:
<Configuration>
<Properties>
<Property name="log.pattern">%d{MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36}%n%msg%n%n</Property>
<Property name="file.err.filename">log/err.log</Property>
<Property name="file.err.pattern">log/err.%i.log.gz</Property>
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="${log.pattern}" />
</Console>
<RollingFile name="err" bufferedIO="true" fileName="${file.err.filename}" filePattern="${file.err.pattern}">
<PatternLayout pattern="${log.pattern}" />
<Policies>
<SizeBasedTriggeringPolicy size="1 MB" />
</Policies>
<DefaultRolloverStrategy max="10" />
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="console" level="info" />
<AppenderRef ref="err" level="error" />
</Root>
</Loggers>
</Configuration>
最佳实践:
滚动日志,永远不让磁盘满
日志如何使用才方便统计和定位问题
日志如何配置性能才比较高
全公司,或者个人使用习惯统一,这样有助于后续的日志收集、分析和统计
package com.winjeg.demo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
@Slf4j
public class Main {
private static final Logger LOG = LoggerFactory.getLogger(Main.class);
private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(128, 256, 1L,
TimeUnit.MINUTES, new ArrayBlockingQueue(512),
new BasicThreadFactory.Builder().namingPattern("thread-%d").daemon(true).build());
public static void main(String[] args) {
long start = System.currentTimeMillis();
execute(8, 160_000);
long first = System.currentTimeMillis();
execute(8, 160_000);
System.out.printf("time cost, preheat:%dt, formal:%dn", first - start, System.currentTimeMillis() - first);
}
private static void execute(int threadNum, int times) {
List<Future> futures = new ArrayList();
for (int i = 0; i < threadNum; i++) {
Future f = EXECUTOR.submit(() -> {
for (long j = 0; j < times; j++) {
log.info("main - info level ...this is a demo script, pure string log will be used!");
}
});
futures.add(f);
}
futures.forEach(f -> {
try {
f.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
});
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.winjeg.spring
demo
1.0-SNAPSHOT
jar
UTF-8
2.22.1
1.4.14
1.8
org.projectlombok
lombok
1.18.30
org.apache.commons
commons-lang3
3.12.0
org.apache.logging.log4j
log4j-core
${log4j.version}
org.apache.logging.log4j
log4j-api
${log4j.version}
org.apache.logging.log4j
log4j-slf4j2-impl
${log4j.version}
这些参考资料有可能不太对, 但是为了方便大家查阅, 我还是给出了一些官方的和比较受欢迎的资料
[1]logback官方测试结果:
[2]log4j2官方测试结果:
[3]Java日志框架:log4j vs logback vs log4j2:
欢迎加入我的知识星球,全面提升技术能力。
加入方式,“长按”或“扫描”下方二维码噢:
星球的内容包括:项目实战、面试招聘、源码解析、学习路线。
文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: lzxmw777