Java SpringBoot中的log4j2:JDBCAppender不';t将日志消息写入数据库';s柱

Java SpringBoot中的log4j2:JDBCAppender不';t将日志消息写入数据库';s柱,java,spring,spring-boot,hibernate,log4j2,Java,Spring,Spring Boot,Hibernate,Log4j2,最近,我尝试使用log4j2创建和配置JDBC日志appender 其主要思想是每次我们访问特定端点(Spring服务)时都发送一个日志,并将Hibernate SQL查询从日志中直接放入GDPR_日志数据库表中的OPERATION_DESCRIPTION列 以下是我迄今为止为实现这一目标所做的工作: 我在Gradle中排除了“logback classic”和“spring boot starter logging”依赖项 我添加了“log4japi”、“log4jcore”和“spring

最近,我尝试使用log4j2创建和配置JDBC日志appender

其主要思想是每次我们访问特定端点(Spring服务)时都发送一个日志,并将Hibernate SQL查询从日志中直接放入GDPR_日志数据库表中的OPERATION_DESCRIPTION列

以下是我迄今为止为实现这一目标所做的工作:

  • 我在Gradle中排除了“logback classic”和“spring boot starter logging”依赖项
  • 我添加了“log4japi”、“log4jcore”和“spring-boot-starter-log4j2”依赖项
我当前的build.gradle如下所示:


    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.5.7.BUILD-SNAPSHOT'
        }
    }
    
    plugins {
        id "org.springframework.boot" version "1.5.7.RELEASE"
    }
    
    apply plugin: 'java'
    apply plugin: 'idea'
    apply plugin: 'io.spring.dependency-management'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'war'
    
    war {
        baseName = 'CprUI'
        version =  '1.0.0-SNAPSHOT'
    }
    
    repositories {
        mavenLocal()
        mavenCentral()
        jcenter()
        maven { url "http://repo.spring.io/libs-snapshot" }
    }
    
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
    
    dependencies {
        compile("org.springframework.boot:spring-boot-starter-web")
        compile("org.springframework.boot:spring-boot-starter-actuator")
        compile("org.springframework.boot:spring-boot-starter-security")
        compile("org.springframework.ldap:spring-ldap-core")
        compile("org.springframework.security:spring-security-ldap")
        compile("org.springframework:spring-tx")
        compile("com.unboundid:unboundid-ldapsdk")
        compile("org.springframework.boot:spring-boot-starter-log4j2")
        compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf', version: '1.5.7.RELEASE'
        compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '1.5.7.RELEASE'
        compile group: 'org.springframework.boot', name: 'spring-boot-starter-parent', version: '1.5.7.RELEASE', ext: 'pom'
        compile("com.oracle:ojdbc6:11.2.0.3")
        compile("org.apache.any23:apache-any23-encoding:2.0")
        compile("org.apache.commons:commons-csv:1.5")
        compile group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-springsecurity4', version: '3.0.2.RELEASE'
        compile("org.springframework.boot:spring-boot-starter-web")
        providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
        testCompile("org.springframework.boot:spring-boot-starter-test")
        testCompile("org.springframework.security:spring-security-test")
        compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.7'
        compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.7'
        compile group: 'org.springframework.boot', name: 'spring-boot-starter-log4j2', version: '2.3.1.RELEASE'
        compile group: 'org.apache.commons', name: 'commons-dbcp2', version: '2.7.0'
        compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.20'
        compile group: 'org.apache.maven.plugins', name: 'maven-compiler-plugin', version: '3.8.1'
    }
    
    configurations.all {
        exclude module: 'spring-boot-starter-logging'
        exclude module: 'logback-classic'
    }

  • 接下来,我创建了log4j2.properties文件并将其放在/resources目录下。该文件如下所示:
  • 然后我在Spring Boot中更新了application.properties:
现在,我只想将Hibernate查询发送到db表中的一个特定列。其余的列由Spring服务方法设置。下面是我的实体类和服务的方法的外观:


    @Entity
    @Table(name = "GDPR_LOG")
    public class Log {
    
        @Id
        @SequenceGenerator(name="DWH_ID_SEQ_GEN", sequenceName="DIM_CPR_COUNTERPARTY_ID", allocationSize=10)
        @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="DWH_ID_SEQ_GEN")
        @Column(name = "ITEM_ID")
        private Long id;
        @Column(name = "CREATION_TIME")
        private String creation_time;
        @Column(name = "LOG_ID")
        private String log_id;
        @Column(name = "USER_ID")
        private String user_id;
        @Column(name = "WORKSTATION_ID")
        private String workstation_id;
        @Column(name = "SESSION_ID")
        private String session_id;
        @Column(name = "OPERATION_DESCRIPTION")
        private String operation_description;
        @Column(name = "APPLICATION_CODE")
        private String app_code;
        @Column(name = "LEGAL_ENTITY")
        private String entity;
    
    //getters, setters

你们能告诉我我做错了什么吗

尽管我在log4j2.properties文件中指定了字段和值,但仍然在那里只得到null,并且没有将Hibernate查询保存到数据库中。 我在春季是一个初学者,我已经为这个话题挣扎了两周,所以我非常感谢在这方面的任何帮助

提前谢谢


干杯

您正在混合两种不同的概念。要么让log4j将日志事件写入数据库,要么实现自己的与log4j无关的记录器

第一部分显示您将使用log4j。好的但是,您不需要使用相同表的JPA实体。类
Log
,方法
saveLogForGetAll(Log Log)
只是不需要。Log4j将把日志事件保存到数据库中

log4j的思想是,代码不应该知道日志事件将如何持久化(在文件系统中、数据库中、通过消息队列可以访问的远程设备上,等等)

第二部分,class
Log
和方法
saveLogForGetAll(Log Log)
,表明您希望直接持久化日志事件,而不使用log4j。那么在log4j中定义数据库附加器的目的是什么

他们两个都不是对的或错的。但是有两个独立的日志机制没有多大意义。但是实现自己的日志记录可能是一项相当复杂的任务:考虑性能、异步持久性、按类和包配置日志记录级别、检索有关当前线程和方法的信息等等


这就是为什么我建议您选择一个log4j(或logback),配置并使用它。只有当您发现使用log4j无法实现真正重要的事情时,才可以扔掉log4j,实现自己的日志记录。

您混合了两个不同的概念。要么让log4j将日志事件写入数据库,要么实现自己的与log4j无关的记录器

第一部分显示您将使用log4j。好的但是,您不需要使用相同表的JPA实体。类
Log
,方法
saveLogForGetAll(Log Log)
只是不需要。Log4j将把日志事件保存到数据库中

log4j的思想是,代码不应该知道日志事件将如何持久化(在文件系统中、数据库中、通过消息队列可以访问的远程设备上,等等)

第二部分,class
Log
和方法
saveLogForGetAll(Log Log)
,表明您希望直接持久化日志事件,而不使用log4j。那么在log4j中定义数据库附加器的目的是什么

他们两个都不是对的或错的。但是有两个独立的日志机制没有多大意义。但是实现自己的日志记录可能是一项相当复杂的任务:考虑性能、异步持久性、按类和包配置日志记录级别、检索有关当前线程和方法的信息等等


这就是为什么我建议您选择一个log4j(或logback),配置并使用它。只有当您发现使用log4j无法实现真正重要的事情时,才可以扔掉log4j并实现您自己的日志记录。

这里我真正需要的是将SQL查询从Hibernate保存到db中的OPERATION_DESCRIPTION字段。我认为最快的方法是从日志消息中检索查询——这就是为什么我尝试使用db appender和所有log4j的东西。也许这是我的根本错误。您是否建议使用任何其他方法来捕获查询并将其传递给spring service?“您是否建议使用任何其他方法…?”-否。我已经说过,使用log4j或logback,定义一个将日志事件写入数据库的附加器,删除类
log
及其存储库。您是否已配置log4j或logback将日志事件写入数据库?结果如何?您在数据库中看到日志条目了吗?您是否看到任何异常?是的,我已经配置了log4j db appender-这是您在log4j2.properties文件中可以看到的(但是可能我仍然缺少其中重要的内容?),但我在数据库中看不到任何日志条目。应该包含日志消息的字段只有空值,也没有异常。若要确定日志配置是否有效,请直接从代码中使用错误级别将一些消息写入日志。如果您在DB日志中看到该消息,则问题与Hibernate有关。如果消息没有出现在DB日志中,那么日志的配置有问题。我真正需要的是将SQL查询从Hibernate保存到DB中的操作描述字段。我认为最快的方法是从日志消息中检索查询——这就是为什么我尝试使用db appender和所有log4j stu

    # LOGGING
    logging.level.org.hibernate.SQLQuery=debug
    logging.level.org.hibernate.type.descriptor.sql=trace
    logging.level.org.springframework.web=${LOG_LEVEL_SPRING:info}
    logging.level.org.hibernate=${LOG_LEVEL_SPRING:debug}
    logging.level.web=${LOG_LEVEL_SPRING:info}
    logging.config=classpath:log4j2.properties
    
    spring.datasource.url=my_datasource
    spring.datasource.username=my_user
    spring.datasource.password=my_password
    spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
    
    server.context-path=/CprUI


    @Entity
    @Table(name = "GDPR_LOG")
    public class Log {
    
        @Id
        @SequenceGenerator(name="DWH_ID_SEQ_GEN", sequenceName="DIM_CPR_COUNTERPARTY_ID", allocationSize=10)
        @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="DWH_ID_SEQ_GEN")
        @Column(name = "ITEM_ID")
        private Long id;
        @Column(name = "CREATION_TIME")
        private String creation_time;
        @Column(name = "LOG_ID")
        private String log_id;
        @Column(name = "USER_ID")
        private String user_id;
        @Column(name = "WORKSTATION_ID")
        private String workstation_id;
        @Column(name = "SESSION_ID")
        private String session_id;
        @Column(name = "OPERATION_DESCRIPTION")
        private String operation_description;
        @Column(name = "APPLICATION_CODE")
        private String app_code;
        @Column(name = "LEGAL_ENTITY")
        private String entity;
    
    //getters, setters


    @Transactional
        public void saveLogForGetAll(Log log) {
            log.setCreation_time(formatDateTime);
            log.setLog_id("SecLog");
            log.setUser_id(checkUser());
            log.setWorkstation_id(checkIP());
            log.setSession_id(session_string);
            log.setApp_code("QRP");
            log.setEntity("AG");
            logsRepository.save(log);
        }