`
lumingming1987
  • 浏览: 116592 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

log4j-database appender

 
阅读更多

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_);

 

分享到:
评论

相关推荐

    YOLO算法-城市电杆数据集-496张图像带标签-电杆.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    (177406840)JAVA图书管理系统毕业设计(源代码+论文).rar

    JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代码+论文) JAVA图书管理系统毕业设计(源代

    (35734838)信号与系统实验一实验报告

    内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。

    YOLO算法-椅子检测故障数据集-300张图像带标签.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    基于小程序的新冠抗原自测平台小程序源代码(java+小程序+mysql+LW).zip

    系统可以提供信息显示和相应服务,其管理新冠抗原自测平台小程序信息,查看新冠抗原自测平台小程序信息,管理新冠抗原自测平台小程序。 项目包含完整前后端源码和数据库文件 环境说明: 开发语言:Java JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 部署容器:tomcat7 小程序开发工具:hbuildx/微信开发者工具

    YOLO算法-俯视视角草原绵羊检测数据集-4133张图像带标签-羊.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    (171674830)PYQT5+openCV项目实战:微循环仪图片、视频记录和人工对比软件源码

    内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。

    新建 文本文档.docx

    新建 文本文档.docx

    hw06.zip

    hw06

    3. Kafka入门-安装与基本命令

    3. Kafka入门-安装与基本命令

    燃气管道施工资质和特种设备安装改造维修委托函.docx

    燃气管道施工资质和特种设备安装改造维修委托函.docx

    The state of AI 2024.pdf

    AI大模型研究相关报告

    lab02.zip

    lab02

    Unity视频插件AVPro的Win端2.2.3

    仅供学习使用,其他用途请购买正版资源AVPro Video Core Windows Edition 2.2.3 亲测可用的视频播放插件,能丝滑播放透明视频等.

    建设工程消防验收现场指导意见表.docx

    建设工程消防验收现场指导意见表.docx

    MVIMG_20241222_194113.jpg

    MVIMG_20241222_194113.jpg

    五相电机双闭环矢量控制模型-采用邻近四矢量SVPWM-MATLAB-Simulink仿真模型包括: (1)原理说明文档(重要):包括扇区判断、矢量作用时间计算、矢量作用顺序及切时间计算、PWM波的生成

    五相电机双闭环矢量控制模型_采用邻近四矢量SVPWM_MATLAB_Simulink仿真模型包括: (1)原理说明文档(重要):包括扇区判断、矢量作用时间计算、矢量作用顺序及切时间计算、PWM波的生成; (2)输出部分仿真波形及仿真说明文档; (3)完整版仿真模型:包括邻近四矢量SVPWM模型和完整双闭环矢量控制Simulink模型; 资料介绍过程十分详细,零基础手把手教学,资料已经写的很清楚

    YOLO算法-锡罐-牙罐-盖子打开数据集-179张图像带标签-锡罐-牙罐-盖子打开.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    java毕设项目之ssm基于JSP的乡镇自来水收费系统+jsp(完整前后端+说明文档+mysql+lw).zip

    项目包含完整前后端源码和数据库文件 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 服务器:tomcat7

Global site tag (gtag.js) - Google Analytics