1.log4j配置
<appender name="DATABASE" class="com.sf.core.log4j.DataSourceAppender"> <filter class="org.apache.log4j.varia.LevelRangeFilter" > <param name="levelMin" value="error"/> </filter> </appender> <root> <level value="INFO"/> <appender-ref ref="CONSOLE"/> <appender-ref ref="DATABASE"/> </root>
2.自己定义Appender类,这里使用spring提供的JdbcTemplate批量插入日志.
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.sf.core.log4j; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import org.apache.log4j.Level; import org.apache.log4j.MDC; import org.apache.log4j.PatternLayout; import org.apache.log4j.spi.LoggingEvent; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; import com.sf.core.util.AppUtil; import com.sf.core.util.UniqueIdUtil; public class DataSourceAppender extends org.apache.log4j.AppenderSkeleton implements org.apache.log4j.Appender { protected String sqlStatement = ""; /** * size of LoggingEvent buffer before writting to the database. Default is * 1. */ protected int bufferSize = 1; protected int maxBuffSize = 10000; /** * ArrayList holding the buffer of Logging Events. */ protected ArrayList buffer; /** * Helper object for clearing out the buffer */ protected ArrayList removes; private boolean locationInfo = false; public DataSourceAppender() { super(); buffer = new ArrayList(bufferSize); removes = new ArrayList(bufferSize); } /** * Gets whether the location of the logging request call should be captured. * * @since 1.2.16 * @return the current value of the <b>LocationInfo</b> option. */ public boolean getLocationInfo() { return locationInfo; } /** * The <b>LocationInfo</b> option takes a boolean value. By default, it is * set to false which means there will be no effort to extract the location * information related to the event. As a result, the event that will be * ultimately logged will likely to contain the wrong location information * (if present in the log format). * <p/> * <p/> * Location information extraction is comparatively very slow and should be * avoided unless performance is not a concern. * </p> * * @since 1.2.16 * @param flag * true if location information should be extracted. */ public void setLocationInfo(final boolean flag) { locationInfo = flag; } /** * Adds the event to the buffer. When full the buffer is flushed. */ public void append(LoggingEvent event) { event.getNDC(); event.getThreadName(); // Get a copy of this thread's MDC. event.getMDCCopy(); if (locationInfo) { event.getLocationInformation(); } event.getRenderedMessage(); event.getThrowableStrRep(); buffer.add(event); if (buffer.size() >= bufferSize) flushBuffer(); } /** * By default getLogStatement sends the event to the required Layout object. * The layout will format the given pattern into a workable SQL string. * * Overriding this provides direct access to the LoggingEvent when * constructing the logging statement. * */ protected String getLogStatement(LoggingEvent event) { String statement = getLayout().format(event); return statement; } /** * Closes the appender, flushing the buffer first then closing the default * connection if it is open. */ public void close() { flushBuffer(); this.closed = true; } /** * loops through the buffer of LoggingEvents, gets a sql string from * getLogStatement() and sends it to execute(). Errors are sent to the * errorHandler. * * If a statement fails the LoggingEvent stays in the buffer! */ @SuppressWarnings("unchecked") public void flushBuffer() { removes.ensureCapacity(buffer.size()); try { if (AppUtil.getContext() != null && AppUtil.getServletContext()!=null) { removes.addAll(buffer); JdbcTemplate jdbcTemplate = (JdbcTemplate) AppUtil.getBean("jdbcTemplateLog4j"); try{ String sql = "INSERT INTO SYS_LOG4J_MSG("+ "ID_,"+ "CLAZZ," + "PRIORITY," + "MESSAGE," + "LOG_DATE," + "USER_ID," + "USER_NAME," + "USER_ACCOUNT) " +"values(?," + "?," + "?," + "?," + "?," + "?," + "?," + "?)"; jdbcTemplate.batchUpdate(sql,new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { LoggingEvent logEvent = (LoggingEvent) buffer.get(i); String clazz = logEvent.getLocationInformation().getClassName(); String level = getLogLevelH(logEvent.getLevel()); String message = logEvent.getMessage().toString(); Timestamp time = new Timestamp(logEvent.getTimeStamp()); Long userId = (Long) MDC.get("current_user_id"); String userName = (String) MDC.get("current_user_name"); String userAccount = (String) MDC.get("current_user_account"); ps.setLong(1, UniqueIdUtil.genId()); ps.setString(2, clazz); ps.setString(3, level); ps.setString(4, message); ps.setTimestamp(5,time); ps.setLong(6, userId==null?0L:userId); ps.setString(7, userName); ps.setString(8, userAccount); } @Override public int getBatchSize() { return buffer.size(); } }); }catch (Exception e) { e.printStackTrace(); } }else{ if(buffer.size()>maxBuffSize){ removes.addAll(buffer.subList(0, maxBuffSize/10)); } } } catch (Exception e) { e.printStackTrace(); } buffer.removeAll(removes); removes.clear(); } private String getLogLevelH(Level l){ String ls=""; if(l.toInt()==Level.ALL.toInt()){ ls="ALL"; }else if(l.toInt()==Level.DEBUG.toInt()){ ls="DEBUG"; }else if(l.toInt()==Level.ERROR.toInt()){ ls="ERROR"; }else if(l.toInt()==Level.FATAL.toInt()){ ls="FATAL"; }else if(l.toInt()==Level.INFO.toInt()){ ls="INFO"; }else if(l.toInt()==Level.OFF.toInt()){ ls="OFF"; }else if(l.toInt()==Level.TRACE.toInt()){ ls="TRACE"; }else if(l.toInt()==Level.WARN.toInt()){ ls="WARN"; } return ls; } /** closes the appender before disposal */ public void finalize() { close(); } /** * JDBCAppender requires a layout. * */ public boolean requiresLayout() { return true; } /** * */ public void setSql(String s) { sqlStatement = s; if (getLayout() == null) { this.setLayout(new PatternLayout(s)); } else { ((PatternLayout) getLayout()).setConversionPattern(s); } } /** * Returns pre-formated statement eg: insert into LogTable (msg) values * ("%m") */ public String getSql() { return sqlStatement; } public void setBufferSize(int newBufferSize) { bufferSize = newBufferSize; buffer.ensureCapacity(bufferSize); removes.ensureCapacity(bufferSize); } public int getBufferSize() { return bufferSize; } }
3.建立数据表
-- Create table create table SYS_LOG4J_MSG ( CLAZZ VARCHAR2(512), PRIORITY VARCHAR2(64), LOG_DATE TIMESTAMP(6), MESSAGE VARCHAR2(2000), USER_ID NUMBER(18), USER_NAME VARCHAR2(256), USER_ACCOUNT VARCHAR2(256), ID_ NUMBER(18) not null ); -- Add comments to the table comment on table SYS_LOG4J_MSG is 'log4j消息'; -- Add comments to the columns comment on column SYS_LOG4J_MSG.CLAZZ is '类型名'; comment on column SYS_LOG4J_MSG.PRIORITY is '级别'; comment on column SYS_LOG4J_MSG.LOG_DATE is '时间截'; comment on column SYS_LOG4J_MSG.MESSAGE is '消息内容'; comment on column SYS_LOG4J_MSG.USER_ID is '用户ID'; comment on column SYS_LOG4J_MSG.USER_NAME is '用户名'; comment on column SYS_LOG4J_MSG.USER_ACCOUNT is '账号'; comment on column SYS_LOG4J_MSG.ID_ is 'ID'; -- Create/Recreate primary, unique and foreign key constraints alter table SYS_LOG4J_MSG add constraint PK_LOG4J_MSG primary key (ID_);
相关推荐
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n') log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout log4j.appender....
log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n # 在应用中记录数据库操作的日志 log4j.logger....
### 四、配置文件`log4j.properties` `log4j.properties`是Log4j的主要配置文件,用于定义日志级别、目的地和格式。以下是一个基本的配置示例: ```properties # 设置全局日志级别为INFO log4j.rootLogger=INFO, ...
然后,配置Log4j2的`log4j2.xml`或`log4j2.json`文件,添加JDBC Appender。这里我们以XML为例: ```xml <?xml version="1.0" encoding="UTF-8"?> <ConnectionFactory class="org.apache.logging.log4j.core....
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n # 文件输出 log4j.appender.R=org.apache.log4j....
- `log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender`:指定了数据库输出的Appender类型为`JDBCAppender`。 - `log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/log4j`:连接数据库的URL。 ...
首先,我们需要在`log4j2.xml`配置文件中定义一个使用JDBC Appender的配置: ```xml <ConnectionFactory class="org.apache.logging.log4j.core.jdbc.DriverManagerConnectionFactory"> ...
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ``` - **File Appender**:将日志写入文件。 ```...
log4j.appender.MongoDBAppender.Database=logdb log4j.appender.MongoDBAppender.Collection=logcollection log4j.appender.MongoDBAppender.Pattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n ``` 在这个...
Log4j由三个主要组件构成:Logger(日志器)、Appender(输出端)和Layout(格式化器)。Logger负责生成日志事件,Appender负责接收这些事件并将其输出到指定的目标,如控制台、文件或数据库。Layout则用于定义日志...
log4j.appender.db=org.apache.log4j.jdbc.JDBCAppender log4j.appender.db.URL=jdbc:mysql://localhost:3306/testdb log4j.appender.db.Driver=com.mysql.jdbc.Driver log4j.appender.db.User=root log4j....
6. **配置文件结构**:`log4j.properties`文件通常采用键值对的形式,如`log4j.rootLogger=DEBUG, Console, File`表示根Logger的日志级别为DEBUG,并将其输出到Console和File两个Appender。Appender的配置会紧接着...
标题中的“Log4J.xml”指的是Apache Log4j框架的配置文件。Log4j是Java平台上广泛使用的日志记录工具,它允许程序员以灵活和可配置的方式控制应用程序的日志输出。XML格式的配置文件提供了更高级别的结构和可读性,...
log4j.appender.MongoDBAppender.Database=logdb log4j.appender.MongoDBAppender.Collection=logcollection ``` 4. **MongoDBAppender实现** `MongoDBAppender`是一个自定义的日志处理器,需要继承`org.apache...
<appender name="console" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1}:%L - %m%n" /> </...
因此,本文将深入探讨如何利用数据库对Log4j日志进行高效管理,特别是通过DBCP(Database Connection Pooling)和MySQL数据库的结合,实现日志的集中式存储和查询,同时添加用户名等附加信息,增强日志的可追溯性和...
5. 插件和布局:Log4j支持多种Appender(如ConsoleAppender、FileAppender等)和Layout(如PatternLayout、XMLLayout等)。 总的来说,这个压缩包包含了开发Java应用程序时与Oracle和SQL Server数据库交互所需的...
log4j.appender.server.layout=org.apache.log4j.PatternLayout log4j.appender.server.File=logs/azkaban-execserver.log log4j.appender.server.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss.SSS Z} %p [%...
<appender name="FileAppender" type="log4net.Appender.FileAppender"> <file value="logs/application.log" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date - %message%...
只需要在类路径中包含log4jdbc3-1.2beta2.jar,并在Log4j的配置文件中指定适当的Appender,即可开始收集SQL日志。同时,附带的`license.txt`文件提供了关于软件许可的详细信息,确保了合法合规的使用。 log4jjdbc....