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部分的文章,包含上下文信息继承的内容。