Spring集成log4j2

参考文档

log4j2官方文档:
http://logging.apache.org/log4j/2.x/manual/appenders.html#JDBCAppender

Log4j2简明教程:内含各种环境变量的用法
https://www.cnblogs.com/lzb1096101803/p/5796849.html

配置文件解析

关键配置文件:module1/conf/log4j2_module1.xml

关键行:
配置自定义日志输出格式的变量:

<property name="myLogPattern">[%d{yyyy-MM-dd HH:mm:ss.SSS z}][%p][%t][%F:%L][%X{user_name}][%X{client_ip}]
            %enc[%X{operation_name}][%X{operation_result}]{Parameter:%m}{HTML}%n
        </property>
// 这些信息由ThreadContext进行管理

配置输出文件位置:

<property name="mylog_file">${env:MODULE_LOGDIR}/audit/gui-audit-${env:MODULE_HOSTNAME}.log</property>
// env代指环境变量

日志关键信息:最大size,一天最大数目,默认保存日期等,参见

<!-- Log file size -->
        <Property name="LOG_MAX_SIZE" value="20 MB" />
        <!-- Maximum number of logs in a day -->
        <Property name="LOG_MAX_NUM" value="50" />
        <!-- Log retention period -->
        <Property name="DEFAULT_KEEP_DAYS" value="7D" />
        <!-- Log retention period -->
        <Property name="LONG_KEEP_DAYS" value="30D" />
        <!-- Format of the log to be deleted -->
        <Property name="LOG_DELETE_PATTERN" value="*.log.gz" />
        <!-- Rolling interval -->
        <Property name="TIME_BASED_INTERVAL" value="1" />

压缩方案:

<property name="mylog_rolling_filename">
            ${env:MODULE_LOGDIR}/mylog/mylog-${env:MODULE_HOSTNAME}-%d{yyyy-MM-dd}-%i.log.gz
        </property>

自定义级别:

<CustomLevels>
        <CustomLevel name="MyLog1" intLevel="180" />
        <CustomLevel name="SECURITY" intLevel="420" />
        <CustomLevel name="OPERATE" intLevel="440" />
    </CustomLevels>
 

Log4j2配置某个log文件输出某种指定级别的日志
参考:https://blog.51cto.com/1197822/2310226、https://blog.csdn.net/ThinkWon/article/details/101627162

onMatch="ACCEPT"匹配该级别及以上级别;
onMatch="DENY"不匹配该级别及以上级别;
onMismatch="ACCEPT" 表示匹配该级别以下的级别;
onMismatch="DENY" 表示不匹配该级别以下的级别;
 
<ThresholdFilter level="WARN" onMatch="DENY"     onMismatch="NEUTRAL"/>
<ThresholdFilter level="INFO"   onMatch="ACCEPT" onMismatch="DENY"/>

Log4j2自定义日志级别介绍:
https://blog.csdn.net/qq_26462567/article/details/84139496
在这里插入图片描述

输出到文件的配置:指定级别,参见日志自定义输出级别

<RollingFile name="myLogAppender" fileName="${my_file}" filePattern="${mylog_rolling_filename}">
            <ThresholdFilter level="MyLog1" onMatch="ACCEPT" onMismatch="DENY" />
            <PatternLayout pattern="${myLogPattern}" />
            <Policies>
                <TimeBasedTriggeringPolicy modulate="true" interval="${TIME_BASED_INTERVAL" />
                <SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}" />
            </Policies>
            <DefaultRolloverStrategy max="${LOG_MAX_NUM}">
                <Delete basePath="${env:GUI_LOGDIR}/error/" maxDepth="1">
                    <IfFileName glob="${LOG_DELETE_PATTERN}" />
                    <IfLastModified age="${LONG_KEEP_DAYS}" />
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

输出到数据库的配置:

<JDBC name="jdbcAppender" tableName="hpc.hpc_operation_log"> //指定数据库
            <Filters>
                <ThresholdFilter level="AUDIT" onMatch="ACCEPT" onMismatch="DENY" />
            </Filters>
            <ConnectionFactory class="com.huawei.conductor.gui.common.datasource.ConnectionFactory" method="getDatabaseConnection" />  //数据库连接的配置类以及连接具体方式
            <Column name="operation_name" pattern="%X{operation_name}" isUnicode="false"/>
            <Column name="execute_result" pattern="%X{operation_result}" isUnicode="false"/>
            <Column name="user_name" pattern="%X{user_name}" isUnicode="false"/>
            <Column name="operation_description" pattern="%message" isUnicode="false"/>
            <Column name="operation_time" isEventTimestamp="true"/>
            <Column name="ip" pattern="%X{client_ip}" isUnicode="false"/>
//上述为数据库中的列与变量之间的映射关系,其中%X{}为环境变量,其余的为log4j2自带变量
        </JDBC>

配置指定最高级别以及生效的appender

<loggers>
        <!-- Global log level -->
        <root level="AUDIT">
            <appenderRef ref="jdbcAppender"/>
            <appenderref ref="debugAppender" />
            <appenderref ref="defaultAppender" />
            <appenderref ref="operateAppender" />
            <appenderref ref="securityAppender" />
            <appenderref ref="errorAppender" />
            <appenderref ref="mylogAppender" />
            <appenderref ref="CONSOLE" />
        </root>

Java配置

数据库连接的配置类:与jdbc的数据库连接保持一致

public class ConnectionFactory {
    private final DataSource dataSource;

    private ConnectionFactory() {
        List<DataSourceConfigYml> datasourceList = new ArrayList<>();
        try {
            datasourceList = YamlUtil.readDatasourceYaml(ExternalConfig.INSTANCE.DATASOURCE_CONFIG_PATH);
        } catch (IOException e) {
            logger.error("Failed to get data source from yaml");
        }
        DataSourceConfigYml dataSourceConfigYml = datasourceList.get(0);
        PooledDataSource pooledDataSource = new PooledDataSource();
        pooledDataSource.setDriver(dataSourceConfigYml.getDriver());
        pooledDataSource.setUrl(dataSourceConfigYml.getUrl());
        pooledDataSource.setUsername(dataSourceConfigYml.getUsername());
        pooledDataSource.setPassword(HpcCipherProvider.byte2String(passwd));
        Arrays.fill(passwd, (byte) 0);
        dataSource = pooledDataSource;
    }
    public static Connection getDatabaseConnection() throws SQLException {
        return Singleton.INSTANCE.dataSource.getConnection();
    }

    private interface Singleton {
        ConnectionFactory INSTANCE = new ConnectionFactory();
    }
}

该类中,私有构造器值得国内了数据库配置的必要信息,url,驱动,用户名,秘钥等
从一个配置文件中读取这些信息
几个Java连接数据库的例子;
https://blog.csdn.net/weixin_39782583/article/details/85928545
https://blog.csdn.net/qq_40774175/article/details/84582315

使用入口:
ExtLogger.java

设置自定义日志输出级别:

	private static final Level SECURITY = Level.forName("SECURITY", 420);
 
    private static final Level OPERATE = Level.forName("OPERATE", 440);
 
    private static final Level AUDIT = Level.forName("Mylog", 180);

设置输出:

public void mylog(……) {
    ThreadContext.put(……, ……);
    ThreadContext.put(……, ……);
    logger.logIfEnabled(FQCN, AUDIT, null, message, (Throwable) null);
}
 

参考:

日志输出到数据库教程参考文件:
https://blog.csdn.net/sajdkla/article/details/103928587?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.nonecase

https://blog.csdn.net/qq_23543983/article/details/80687643

过程中遇到的setNString问题,解释:
https://oomake.com/question/5054811
了解setNString方法即可,实际上真正的解决方案:
https://stackoverflow.com/questions/24242137/log4j2-jdbc-appender-issuefailed-to-insert-record
设置为:

<Appenders>
    <JDBC name="databaseAppender" tableName="dbo.application_log">
      <DataSource jndiName="java:/comp/env/jdbc/LoggingDataSource" />
      <Column name="eventDate" isEventTimestamp="true" />
      <Column name="level" pattern="%level" isUnicode="false" />
      <Column name="logger" pattern="%logger" isUnicode="false" />
      <Column name="message" pattern="%message" isUnicode="false" />
      <Column name="exception" pattern="%ex{full}" isUnicode="false" />
    </JDBC>
  </Appenders>

Log4j2的多线程中的变量管理ThreadContext

Log4j用的是MDC与NDC,log4j2中用的是ThreadContext作为解决方案
https://www.cnblogs.com/zhenghengbin/p/11769661.html

官方提供的API接口说明:
http://logging.apache.org/log4j/2.x/manual/thread-context.html

然而这些适用的前提是:在同一个线程中进行调用的
即Controller-》Service-》Service中调用的其他类

如果遇到在service中新启线程,比如@Async注解,那么新线程中的ThreadContext是完全新的对象,会没有主线程中的key、value,因此需要做到上下文信息的继承。详情参见@Async部分的文章,包含上下文信息继承的内容。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值