官网:http://logging.apache.org/log4j/1.2/manual.html

事件:
最近在项目中使用log4j 1.x JDBCAppender记录管理员操作日志到数据库,在测试时发现系统启动后运行一段时间无法继续记录相关操作日志到数据库。
配置如下:
log4j.properties:

log4j.logger.oplog=INFO, oplog
log4j.appender.oplog=com.lenovo.moc.portal.dao.LogJDBCAppender
log4j.appender.oplog.driver=com.mysql.jdbc.Driver
log4j.appender.oplog.URL=jdbc:mysql://192.168.2.164:3306/oplog?characterEncoding=utf8
log4j.appender.oplog.user=xxx
log4j.appender.oplog.password=xxx
log4j.appender.oplog.sql=insert into operation_loginfo (staff_id, staff_name, user_role, op_type, op_alias, create_time, content, content_alias) values ('%x{login_staff_id}', '%x{login_staff_name}','%x{login_user_role}', '%x{op_type}', '%x{op_alias}', '%d{yyyy-mm-dd hh:mm:ss}','%m', '%x{content_alias}')
log4j.appender.oplog.layout=org.apache.log4j.PatternLayout

java代码:

public class OperationLogService {
  private static final Logger logger = Logger.getLogger(OperationLogService.class);
  private static ExecutorService threadPool = Executors.newFixedThreadPool(3);;   private static ExecutorService getThreadPool() {
    return threadPool;
  }   /**
  * 记录操作日志
  * @param login_staff_id 员工id
  * @param login_staff_name 员工姓名
  * @param login_user_role 员工角色
  * @param op_type 操作类型
  * @param op_alias 操作别名
  * @param content_alias 操作内容
  * @param msg 附加信息
  */
  public static void log(String login_staff_id, String login_staff_name, String login_user_role, String op_type,
    String op_alias, String content_alias, final String msg) {
    getThreadPool().execute(new Runnable() {
      @Override
      public void run() {
        MDC.put("login_staff_id", login_staff_id);
        MDC.put("login_staff_name", login_staff_name);
        MDC.put("login_user_role", login_user_role);
        MDC.put("op_type", op_type);
        MDC.put("op_alias", op_alias);
        MDC.put("content_alias", content_alias);
       logger.info(msg);
      }
    });
  }   public static void main(String[] args) {
    log("1", "zhangsan", "admin", "add_user", "添加用户", "zhangsan添加用户", "test msg");
  }
}

解决办法:
通过查看log4j 1.x JDBCAppender源码发现,并没有对数据库连接的有效性进行判断。即:一旦数据库连接断开,就无法继续写入日志。
故而,通过扩展JDBCAppender的方式,进行数据库连接重连处理:

/**
* 自定义实现Log4j日志组件,将日志记录到数据库<br />.
* 解决问题: 原生组件在系统运行过程中可能会出现数据库连接断开,导致无法正常记录日志信息到数据库.
*
* @desc com.lenovo.moc.portal.dao.LogJDBCAppender
* @author chench9@lenovo.com
* @date 2017年3月15日
*/
public class LogJDBCAppender extends JDBCAppender {
  private static final Logger logger = Logger.getLogger(LogJDBCAppender.class);   @Override
  protected Connection getConnection() throws SQLException {
    Connection connection = super.getConnection();
    if(connection == null || connection.isClosed()) {
      logger.warn(String.format("reconnect log jdbc appender connection"));
      connection = reconnect();
    }
    return connection;
  }   /**
  * 重新创建数据库连接
  * @return
  * @throws SQLException
  */
  private Connection reconnect() throws SQLException {
    Connection connection = DriverManager.getConnection(databaseURL, databaseUser,databasePassword);
    return connection;
  }   /**
  * 重载父类方法,打印错误信息到日志文件 <br />
  * 同时,处理数据库重连并在出错时重试记录日志信息.
  */
  @Override
  protected void execute(String sql) throws SQLException {
    try {
      super.execute(sql);
    } catch (Exception e) {
      logger.error(String.format("log jdbc appender execute sql eror: %s", getSql()), e);
      closeConnectionInterval();
      super.execute(sql);
    }
  }   // 真正地关闭数据库连接
  private void closeConnectionInterval() {
    if(connection == null) {
      return;
    }     try {
      connection.close();
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      connection = null;
    }
  }
}

log4j 1.x org.apache.log4j.jdbc.JDBCAppender类图:

org.apache.log4j.jdbc.JDBCAppender数据库连接实现:

log4j 2.x org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender类图:

显然,在log4j 2.x中,使用了数据库连接池,所以建议使用log4j 2.x版本的JdbcAppender。

【参考】
http://stackoverflow.com/questions/3880521/reconnect-to-db-within-log4j Reconnect to DB within log4j

Log4j 1.x JDBCAppender记录日志失效问题详解的更多相关文章

  1. 《手把手教你》系列基础篇(八十七)-java+ selenium自动化测试-框架设计基础-Log4j 2实现日志输出-上篇(详解教程)

    1.简介 Apache Log4j 是一个非常古老的日志框架,并且是多年来最受欢迎的日志框架. 它引入了现代日志框架仍在使用的基本概念,如分层日志级别和记录器. 2015 年 8 月 5 日,该项目管 ...

  2. java log4j基本配置及日志级别配置详解

    java log4j日志级别配置详解 1.1 前言 说出来真是丢脸,最近被公司派到客户公司面试外包开发岗位,本来准备了什么redis.rabbitMQ.SSM框架的相关面试题以及自己做过的一些项目回顾 ...

  3. Flume中的flume-env.sh和log4j.properties配置调整建议(图文详解)

    GC是内存的回收的意思. Flume中的flume-env.sh配置调整建议 [hadoop@master conf_HostInterceptor]$ pwd /home/hadoop/app/fl ...

  4. Android 定时器实现的几种方式和removeCallbacks失效问题详解

    实现定时器有很多种方式,在这里我简单的介绍几种方式 (1)使用Handler + Runnable的方式 Handler handler = new Handler(); Runnable runna ...

  5. 【转】Android 定时器实现的几种方式和removeCallbacks失效问题详解--不错

    原文网址:http://blog.csdn.net/xiaanming/article/details/9011193 实现定时器有很多种方式,在这里我简单的介绍几种方式 (1)使用Handler + ...

  6. IDEA里运行代码时出现Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger的解决办法(图文详解)

    不多说,直接上干货! 问题详情 运行出现log4j的问题 -classpath "C:\Program Files\Java\jdk1.8.0_66\jre\lib\charsets.jar ...

  7. 《手把手教你》系列基础篇(八十八)-java+ selenium自动化测试-框架设计基础-Log4j 2实现日志输出-下篇(详解教程)

    1.简介 上一篇宏哥讲解和分享了如何在控制台输出日志,但是你还需要复制粘贴才能发给相关人员,而且由于界面大小限制,你只能获取当前的日志,因此最好还是将日志适时地记录在文件中直接打包发给相关人员即可.因 ...

  8. mysql 索引B-Tree类型对索引使用的生效和失效情况详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt343 当人们谈论索引的时候,如果没有特别指明类型 ,那多半说的是 B-Tre ...

  9. 对于maven创建spark项目的pom.xml配置文件(图文详解)

    不多说,直接上干货! http://mvnrepository.com/ 这里,怎么创建,见 Spark编程环境搭建(基于Intellij IDEA的Ultimate版本)(包含Java和Scala版 ...

随机推荐

  1. windows 路由转发

    netsh interface ipv6 install 将内网的2433端口转发到外网的11111端口netsh interface portproxy add v4tov4 listenaddre ...

  2. js-元素相关

    获取元素方法一 可以使用内置对象document上的getElementById方法来获取页面上设置了id属性的元素,获取到的是一个html对象,然后将它赋值给一个变量,比如: <script ...

  3. ImageMagick: DrawImage(Image*,DrawInfo*) 绘制填充图片时卡住的原因分析

    今天傍晚在测试的时候无意发现有两个动画会卡住,正常情况下,20秒就完成的操作,突然卡住. CPU:95%+,经过30 - 50秒左右后,程序又能正常的向下执行,结果是对的. 这种情况不是每次都发生,有 ...

  4. 第三十一节,目标检测算法之 Faster R-CNN算法详解

    Ren, Shaoqing, et al. “Faster R-CNN: Towards real-time object detection with region proposal network ...

  5. 第二十九节,目标检测算法之R-CNN算法详解

    Girshick, Ross, et al. “Rich feature hierarchies for accurate object detection and semantic segmenta ...

  6. unittest的使用二——生成基于html的测试报告

    mac下的安装: 1.下载HTMLTestRunner.py文件,下载地址http://tungwaiyip.info/software/HTMLTestRunner.html,可以复制里面的内容到一 ...

  7. JS with

    <script type="text/javascript"> function Dog(){ this.type="dog"; this.tail ...

  8. 新建工程时报错(26, 13) Failed to resolve: com.android.support:appcompat-v7:28.+ ,

    allprojects { repositories { jcenter() maven { url "https://maven.google.com" } } }

  9. Elastic 基础篇(2)

    1.基本概念 1)Elastic和RDMS对比 RDMS Elastic 数据库database 索引index 表table 类型type 行row 文档document 列column 字段fie ...

  10. windows下ngnix+php配置

    1.需要工具: 下载ngnix  网址:http://nginx.org/ 下载:RunHiddenConsole 第二步 将下载文件解压后,将RunHiddenConsole拷贝到ngnix目录与p ...