【Java日志】Log4jdbc-log4j2介绍,以及集成Spring Boot

1,726 阅读4分钟

【文档资源】

1. Log4jdbc介绍

主要作用是可以完整的在日志中输出参数,而不是问号(?)。

具体来说:

  • 原来的日志可能是:select name from User where id = ?,那么通过Log4jdbc后,可以将日志输出改为:select name from User where id = 5
  • 或者,想要知道一个SQL的运行时间,了解某个功能的performance瓶颈是否在SQL上。

Log4jdbc算是一个很老的项目了,最近一次更新还是在2013年上下。

2. 发展史

2.1 首先是google的Log4jdbc

官网:code.google.com/archive/p/l…
Github:github.com/arthurblake…

算是最初版的Log4jdbc,最近一次的更新时间为: image.png

2.2 google的Log4jdbc-remix版本

官网:code.google.com/archive/p/l…

是一个deprecated项目了,不建议使用,以下摘自官网:

2013-11-06 log4jdbc-remix is dead! long live log4jdbc-log4j2!

You are strongly recommended to look at log4jdbc-log4j2 rather than log4jdbc-remix

2.3 google的Log4jdbc-log4j2介绍

官网:code.google.com/archive/p/l…

在支持slf4j的同时,默认的日志实现使用了log4j2。支持JDBC 4.1,功能包含了上述#2.1的Log4jdbc以及#2.2的Log4jdbc-remix的改动。

Log4jdbc-log4j2依然是个很古早的项目,最近一次更新时间: image.png

2.4 brunorozendo的Log4jdbc-log4j2

Github:github.com/brunorozend…

从描述中可以看出来,这个项目是从上述的#2.3 google的版本export出来的:

Automatically exported from code.google.com/p/log4jdbc-log4j2

在这里提的主要原因是,它的文档写的比较全,文档地址:log4jdbc.brunorozendo.com/

想要了解怎么对接Log4jdbc-log4j2,看上述这个文档就可以了。

【版本介绍】

  • 对于Java 5,需要使用log4jdbc-log4j2-jdbc3的版本。
  • 对于Java 6,需要使用log4jdbc-log4j2-jdbc4的版本。
  • 对于Java 7,需要使用log4jdbc-log4j2-jdbc4.1的版本。

鉴于如今我们可能都使用JDK 11甚至17了,那么就看最新版本即可。

【如何使用】

  • 修改连接数据库的Url:
    • 如原本是:jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
    • 那么就改成:jdbc:log4jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8,即在中间加上log4jdbc
  • 修改驱动类:
    • 如原本是:com.mysql.jdbc.Driver
    • 那么就改成:net.sf.log4jdbc.sql.jdbcapi.DriverSpy

更多的关于日志级别以及定制显示内容,请参考上述给的文档链接。

2.5 Spring boot starter版本

在2017年由Craig Andrews以及Yegor Bugayenko,在Log4jdbc-log4j2的版本上,推出了Log4jdbc Spring Boot Starter

具体参照Andrews的文章:candrews.integralblue.com/2017/03/log…
Github:github.com/candrews/lo… Maven repository: mvnrepository.com/artifact/co…

这个Starter需要的环境:

  • Java 1.8+
  • Spring Boot 2.1+

3. 示例:如果没有Log4jdbc-log4j2的引入,打印log

依赖:

  • spring-boot-starter-web(我使用的是2.5.7)
  • spring-boot-starter-web
  • spring-boot-starter-data-jpa
  • mysql的jar:mysql-connector-java

application.yaml内容:

  • spring.jpa.show-sql=true主要是为了显示sql。
  • spring.jpa.properties.hibernate-format_sql=true主要是为了换行打印sql。
spring:
    datasource:
        url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
        username: root
        password: xxxxxx
        driver-class-name: com.mysql.jdbc.Driver
    jpa:
        show-sql: true
        properties:
            hibernate:
                format_sql: true

测试代码:

@SpringBootTest
public class CourseRepositoryTest {

    @Autowired
    private CourseRepository courseRepository;

    @Test
    public void test() {
        Course course = new Course();
        course.setName("001");
        course.setStatus(StatusEnum.Approved);
        courseRepository.save(course);
    }
}

日志打印,可以看到values中是?, ?,这样比较难看懂:

image.png

4. 示例:Log4jdbc Spring Boot Starter

4.1 示例insert()以及findById()

引入依赖:
除了#3中的依赖,需要额外引入:

<dependency>
    <groupId>com.integralblue</groupId>
    <artifactId>log4jdbc-spring-boot-starter</artifactId>
    <version>2.0.0</version>
</dependency>

application.yaml配置:
可以删掉上述的spring.jpa.show-sql=truespring.jpa.properties.hibernate-format_sql=true

测试代码:同#3.

运行后日志: 可以看到jdbc下打印出不同类别的日志,如jdbc.connection, jdbc.audit, jdbc.sqlonly等等,并且打印的insert语句是将真实的value填进去的: image.png

测试courseRepository.findById(1)代码: 运行后日志: 可以看到:

  • jdbc.sqlonly能打印出sql,并且values是真实的值。
  • jdbc.sqltiming不但能打印出sql,而且还能将运行时间打印出来(executed in 3 msec)。
  • jdbc.resulttable:打印出查询的结果。
  • 其它还有一些类别...

image.png

4.2 关闭其中一些类别

参考:github.com/candrews/lo…

我们可以按需显示一些类别,即关闭不想要的类别。 比如关闭jdbc.audit, jdbc.sqlonly, jdbc.resultset, jdbc.connection, jdbc.resultsettable。

只留下jdbc.sqltiming。那么需要在application.yaml中配置: sqltiming=info遵循的log levels和日志框架的一致,可以是debug, info, error, ...

logging:
    level:
        jdbc:
            connection: OFF
            audit: OFF
            sqlonly: OFF
            sqltiming: info
            resultset: OFF
            resultsettable: OFF

测试courseRepository.findById(1)代码:
打印的日志则只有jdbc.sqltiming了: image.png

4.3 其它的一些定制

参考:github.com/candrews/lo…

Log4jdbc Spring Boot Starter除了可以按需显示日志内容,以及日志级别外,还有其它的一些定制,比如默认情况下curd语句/以及create建表语句都会打印,那么如果想要关闭select,但要显示其它的如insert等,可以在application.yaml中设置:

  • log4jdbc.dump.sql.select = false
  • log4jdbc.dump.sql.insert = true
  • log4jdbc.dump.sql.update = true
  • log4jdbc.dump.sql.delete = true
  • log4jdbc.dump.sql.create = true

又或者,上述的jdbc.sqltiming中,executed in的字默认会换行,我们想要放在同一行,可以设置:log4jdbc.trim.sql.extrablanklines = false

那么打印的日志效果会是: image.png

但上述为什么从from就开始换行了呢?是因为单行的sql超过了默认的最大字数,即90,可以通过设置log4jdbc.dump.sql.maxlinelength=1000来改变。

效果: image.png

这里只是举例,有很多其它的设置,可以参考上述贴出来的文档。

5. 遇到的问题

起初我是看了上述#2.4的文档,然后在Spring Boot的示例中也改了driver类以及在url中加上了log4jdbc,然后发现日志中所有的jdbc相关的都会多打印一份: image.png

原因是Log4jdbc Spring Boot Starter会自动set,并不需要手动再修改driver或是url了。如果使用原生的log4jdbc-log4j2-jdbc4.1.jar,则需要手动修改。