Log4j生成压缩形式日志

Log4j生成压缩形式日志

转:http://blog.youkuaiyun.com/zhaosen241/article/details/3248331

 

Log4j提供了强大的日志功能,但是只能生成文本形式的日志文件,对于输出日志很频繁的应用会产生一些资源的浪费,例如我们的一个项目平均每20分钟就会生成一个大约10M的日志文件。为了节约硬盘资源,最近几天修改了一下Log4j,做了一个自己的版本将日志文件做成压缩包。

 

记录下这几天的工作吧:

 

1.       下载Log4j 1.2.15源代码,链接是:http://logging.apache.org/log4j/1.2/download.html

下载apache-log4j-1.2.15.tar.gz是带有源代码的包

 

2.       Log4j是用Maven2打包的,在链接http://maven.apache.org/download.html中下载

apache-maven-2.1.0-M1-bin.zip,这里需要注意下,2.0.9中有bug,打包会失败。

下载Maven后需要配置一下环境变量,就不细说了。

 

3.       下载安装MinGW,用来构建NTEventLogAppender.dll。下载链接:

http://mmtele3.skycn.com/down/MinGWStudioFullSetup-2_05.exe

 

4.       用Maven打包Log4j工程没问题后就可以开始修改里面的源代码了。在前一篇blog中转载了关于log4j的详细信息,我们主要更改两种方式的log,一种是DailyRollingFileAppender,一种是RollingFileAppender。

DailyRollingFileAppender在往日志文件打log的时候会检测日志文件上次修改的时间,如

果系统当前时间与上次修改时间不是一天,则将日志文件重新命名,在生成一个新的日志文件,例如日志文件是log.log,检测上次修改时间早于当天,则将log.log重命名为log.log.2008-11-7,并将log.log清空来打新的日志,其中2008-11-7是有配置文件指定的。

         RollingFileAppender在往日志文件打log的时候会根据配置文件设置的最大文件大小来与当前日志文件做比较,如果比文件大时,则将log文件重命名,规则为:根据最大日志备份个数做备份,例如最大日志备份个数设置为3,则将log.log更名为log.log.1、log.log.2、log.log.3、每次会判断这三个文件是否存在,如果存在,则将后缀最大的那个删掉,往后顺移一个,将log.log放到log.log.1中。

 

5.       现在需要做的就是将这两种方式的操作做一下修改。

DailyRollingFileAppender在判断需要将log.log重命名为log.log.2008-11-7时,我们将重命名这个操作改成将log.log打到zip包里面即可;同理,RollingFileAppender也是将文件重命名的操作改成打zip包。

 

6.       实现中主要需要修改两个类中的两个方法,相关代码如下:

DailyRollingFileAppender.java

修改方法rollOver

  

  1. void rollOver() throws IOException {
  2.         // Compute filename, but only if datePattern is specified 
  3.         if (datePattern == null) {
  4.           errorHandler.error("Missing DatePattern option in rollOver().");
  5.           return;
  6.         }
  7.         String datedFilename = fileName+sdf.format(now);
  8.         // It is too early to roll over because we are still within the
  9.         // bounds of the current interval. Rollover will occur once the
  10.         // next interval is reached.
  11.         if (scheduledFilename.equals(datedFilename)) {
  12.           return;
  13.         }
  14.         // close current file, and rename it to datedFilename
  15.         this.closeFile();
  16.         File target  = new File(scheduledFilename + ".zip");
  17.         if (target.exists()) {
  18.           target.delete();
  19.         }
  20.         //log old file 
  21.         File file = new File(fileName);
  22.         
  23.         //creat zip output stream to build zip file
  24.         ZipOutputStream out = null;
  25.        FileInputStream fin = null;
  26.        byte[] buf = new byte[1024];
  27.         
  28.        //file -> zip
  29.        try{
  30.            fin = new FileInputStream(file);
  31.            out = new ZipOutputStream(new FileOutputStream(scheduledFilename + ".zip"));
  32.            out.putNextEntry(new ZipEntry(file.getPath()));
  33.        
  34.            LogLog.debug(fileName + " -> " + scheduledFilename + ".zip");
  35.        
  36.            int len;
  37.            while ((len = fin.read(buf)) > 0) {
  38.               out.write(buf, 0, len);
  39.            }
  40.            
  41.            out.closeEntry();
  42.            fin.close();
  43.            
  44.            LogLog.debug(fileName + " -> " + scheduledFilename + ".zip successful!");
  45.        }catch(IOException e) {
  46.           errorHandler.error("add zip file("+scheduledFilename+") failed.");
  47.         }
  48.        finally{
  49.            if (out != null) {
  50.               out.closeEntry();
  51.               out.close();
  52.            }
  53.            if (fin != null)
  54.               fin.close();
  55.        }
  56.        
  57.        //delete old file
  58.        file.delete();
  59.        
  60.         try {
  61.           // This will also close the file. This is OK since multiple
  62.           // close operations are safe.
  63.           this.setFile(fileName, true, this.bufferedIO, this.bufferSize);
  64.         }
  65.         catch(IOException e) {
  66.           errorHandler.error("setFile("+fileName+", true) call failed.");
  67.         }
  68.         scheduledFilename = datedFilename;
  69.   }

 

RollingFileAppender.java

同样是修改rollOver方法:

  1. public// synchronization not necessary since doAppend is alreasy synched
  2.     void rollOver() {
  3.        File target;
  4.        File file;
  5.        if (qw != null) {
  6.            long size = ((CountingQuietWriter) qw).getCount();
  7.            LogLog.debug("rolling over count=" + size);
  8.            // if operation fails, do not roll again until
  9.            // maxFileSize more bytes are written
  10.            nextRollover = size + maxFileSize;
  11.        }
  12.        LogLog.debug("maxBackupIndex=" + maxBackupIndex);
  13.        boolean renameSucceeded = true;
  14.        // If maxBackups <= 0, then there is no file renaming to be done.
  15.        if (maxBackupIndex > 0) {
  16.            // Delete the oldest file, to keep Windows happy.
  17.            file = new File(fileName + maxBackupIndex + ".zip");
  18.            if (file.exists())
  19.               renameSucceeded = file.delete();
  20.            // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3,
  21.            // 2}
  22.            for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--) {
  23.               file = new File(fileName + i + ".zip");
  24.               if (file.exists()) {
  25.                   target = new File(fileName + (i + 1) + ".zip");
  26.                   LogLog.debug("Renaming file " + file + " to " + target);
  27.                   renameSucceeded = file.renameTo(target);
  28.               }
  29.            }
  30.            if (renameSucceeded) {
  31.               // zip fileName to fileName1.zip
  32.               
  33.               this.closeFile(); // keep windows happy.
  34.               file = new File(fileName);
  35.               // LogLog.debug("compress file " + file + " to " + target);
  36.               ZipOutputStream out = null;
  37.               FileInputStream fin = null;
  38.               byte[] buf = new byte[8192];
  39.               try {
  40.                   //create zip out put stream to build zip file
  41.                   fin = new FileInputStream(file);
  42.                   out = new ZipOutputStream(new FileOutputStream(fileName
  43.                          + 1 + ".zip"));
  44.                   out.putNextEntry(new ZipEntry(file.getPath()));
  45.                   LogLog.debug(fileName + " -> " + fileName + 1
  46.                          + ".zip");
  47.                   int len;
  48.                   while ((len = fin.read(buf)) > 0) {
  49.                      out.write(buf, 0, len);
  50.                   }
  51.                   out.closeEntry();
  52.                   fin.close();
  53.                   LogLog.debug(fileName + " -> " + fileName + 1
  54.                          + ".zip successful!");
  55.                   
  56.                   file.delete();
  57.               } catch (IOException e) {
  58.                   errorHandler.error("add zip file(" + fileName + 1
  59.                          + ".zip) failed.");
  60.               }finally{
  61.                   try {
  62.                      if (out != null) {
  63.                          out.closeEntry();
  64.                          out.close();
  65.                      }
  66.                      if (fin != null)
  67.                          fin.close();
  68.                   } catch (IOException e) {
  69.                      // TODO Auto-generated catch block
  70.                      errorHandler.error("close out and fin failed.");
  71.                   }
  72.               }
  73.               // if file compress failed, reopen file with append = true
  74.               //
  75.               if (!renameSucceeded) {
  76.                   try {
  77.                      this.setFile(fileName, true, bufferedIO, bufferSize);
  78.                   } catch (IOException e) {
  79.                      if (e instanceof InterruptedIOException) {
  80.                          Thread.currentThread().interrupt();
  81.                      }
  82.                      LogLog.error("setFile(" + fileName
  83.                             + ", true) call failed.", e);
  84.                   }
  85.               }
  86.            }
  87.        }
  88.        //
  89.        // if all renames were successful, then
  90.        //
  91.        if (renameSucceeded) {
  92.            try {
  93.               // This will also close the file. This is OK since multiple
  94.               // close operations are safe.
  95.               this.setFile(fileName, false, bufferedIO, bufferSize);
  96.               nextRollover = 0;
  97.            } catch (IOException e) {
  98.               if (e instanceof InterruptedIOException) {
  99.                   Thread.currentThread().interrupt();
  100.               }
  101.               LogLog
  102.                      .error("setFile(" + fileName + ", false) call failed.",
  103.                             e);
  104.            }
  105.        }
  106. }

 

7.       最后,由于打zip包的时候用到了Ant中的zip代码,下载带源代码的Ant包,链接是

http://archive.apache.org/dist/ant/source/apache-ant-1.6.5-src.zip 。将里面zip的类放入log4j工程中,并用refactor将包重命名到org.apache.log4j中。

 

 

PS:这样做肯定会影响Log4j对输出日志的性能的影响,需要做进一步的性能方面的测试。

【Log4j2】Log4j2最佳实践:Log4j2配置超过7天压缩,超过3个月删除文件的滚动日志,分别定义info文件和error文件,按照每小时存储 如果你想要在控制台输出美化的日志信息,你可以使用Log4j2的ConsoleAppender和AnsiColorConverter来实现。在这个配置中,我们新增了一个Console appender(ConsoleAppender),用于在控制台输出美化的日志信息。使用PatternLayout的`%highlight{}`和AnsiColorConverter可以根据日志级别为日志信息添加颜色。在示例配置中,我们为不同的日志级别设置了不同的颜色。 阅读详情

相关推荐

Java 领域 Log4j 的日志文件压缩策略

日志是系统的“健康档案”,但你是否遇到过这样的场景?一个运行3个月的Java应用,日志文件夹占满了500GB磁盘空间,删除旧日志怕丢关键信息,不删又面临服务器宕机风险。本文将聚焦Log4j2的日志文件压缩策略日志为什么需要压缩?Log4j2如何实现“边写边滚动+自动压缩”?如何根据业务需求定制压缩策略(如按大小/时间滚动、选择Gzip/Zip格式)?实战中常见问题(如压缩失败、日志丢失)如何解决?用“叠作业本”的故事引出日志滚动与压缩的必要性;

Java大师兄的博客 1272

日志文件自动压缩

使用 log4j 记录日志,每天0点进行分隔,由于日志文件较大,为节省空间,需要将历史文件自动压缩。需要使用 Apache Extras™ for Apache log4j™  的 org.apache.log4j.rolling.TimeBasedRollingPolicy 类进行配置。配置如下:

Yewberry 的点滴积累 2万+

【log4j2日志框架】修改转储日志文件权限

0.背景 对于安全要求严格的系统,对于转储的压缩日志文件,要求文件权限为只读,而找遍了log4j2的资料,都没发现有这样操作,log4j2框架对于日志的默认权限都是640。不过log4j2是支持自定义日志 1. ...

weixin_36142042的博客 4074

log4j 日志压缩

log4j 压缩日志文件配置所需文件:1.创建自己的Appender2.log4j.properties 中 选择自己的Appender3.输出日志测试结果如下总结: 所需文件: commons-logging.jar log4j-1.2.15.jar 1.创建自己的Appender package net.wwwyibu.wechat.service; import java.io.File; import java.io.FileInputStream; import java.io.FileOu

qq_42792934的博客 4942

深入掌握Java日志管理:Log4j详解与实战

Log4j 是 Java 生态中最早、最成熟、也是最广泛使用的日志记录框架之一。其设计思想和模块化架构对后来的日志框架(如 Logback)产生了深远影响。本章将系统性地介绍 Log4j 的发展背景、核心架构特点及其五大核心组件的运作机制,帮助开发者从架构层面理解其工作原理与使用方式。PatternLayout通过参数定义输出格式,常用占位符如下:占位符含义%d日期%t线程名%p日志级别%c类名%M方法名%L行号%m消息内容%n换行符@Override。

weixin_35639680的博客 715

log4j日志配置以及配置文件详解

log4j配置文件以及配置文件说明 包里有一个log4j配置文件 和一个配置详解

log4j日志按日期拆分压缩及按大小拆分压缩

此次对于项目中的日志打印做了一些了解及线上系统的应用。 项目中用到的日志打印的工具是org.apache.log4j中的工具。此次主要用到的是三个: org.apache.log4j.ConsoleAppender(控制台) org.apache.log4j.Daily...

chenglu9032的博客 5798

保姆级教程:手把手教你用Jacquard V2数据集训练机器人抓取模型(附完整代码)

本文提供了一份详细的保姆级教程,手把手教你使用Jacquard V2数据集训练机器人抓取模型。从环境配置、数据准备到模型架构设计、训练优化和实际部署,全程解析并附完整代码,帮助开发者快速掌握视觉抓取技术。

weixin_29031057的博客 313

log4j 压缩日志_Spring Boot 日志各种使用姿势,是时候捋清楚了!

来自公众号:江南一点雨1. Java 日志概览1.1 总体概览1.2 日志级别1.3 综合对比1.4 最佳实践2. Spring Boot 日志实现2.1 Spring Boot 日志配置2.2 Logback 配置2.3 Log4j 配置3.小结通过一篇文章来和大家捋一捋 Java 中的日志问题,顺便我们把 Spring Boot 中的日志问题也说清楚。1. Java 日志概览说到 J...

weixin_39925350的博客 863

Zemax单模光纤耦合仿真避坑指南:数值孔径、模式匹配与镀膜影响详解

本文详细解析了Zemax单模光纤耦合仿真中的关键避坑要点,包括数值孔径的多重定义与换算、模式匹配度评估及镀膜影响分析。通过实际案例和技术公式,帮助工程师避免常见仿真误差,提升激光通信和光纤传感系统的设计精度。特别针对OpticStudio用户提供了实用的参数设置建议和优化策略。

weixin_30836759的博客 464

ContextCapture导入点云进行重建

ContextCapture导入点云进行重建

天桥飞熊的博客 1万+

SpringBoot配置日志(log4j版)

SpringBoot配置日志(log4j版) 介绍 在软件开发中,日志是个很重要的东西,它记录系统中方法运行的过程信息和系统报错时的错误信息。开发人员在排查系统中的错误,就可以通过错误日志来进行排查,如果没有日志那排查错误得发疯。。。 在SpringBoot版本2.X.X以后,SpringBoot就将log4j设置为默认的日志框架了。 后面我将介绍SpringBoot中如何设置log4j,好好保存日志,是我们必须的。 这里的日志指的就是我们在控制台中看到的信息,如图所示: Log4j简介 Log4j有三个

孙霸天的专栏 4483

用STM32手搓一个体温计

市面上大多额温计、测温计精度。

m0_61687959的博客 2375

log4j2 java 记录日志_记录日志之log4j2

log4j2apache官方已经声明log4j1.x不再更新,建议开发者使用log4j2,它相比1.x在使用上发生了较大的变化。使用log4j2记录日志的步骤1.下载jar包log4j2官网下载:http://logging.apache.org/log4j/2.x/百度网盘下载:http://pan.baidu.com/s/1minAspq下载后需要将下面两个jar包导入到项目中log4j-ap...

weixin_29582919的博客 395

Flotherm XT学习历程

大家好,通过半年的热仿真软件学习使用,最终发现最好用,最好上手的软件就是Flotherm XT,对新手非常友好,但由于软件近几年才发布,网上教程非常少,后面我将在这里持续分析软件使用心得,和大家一起学习。

xiaoredred的博客 6257

JW01二氧化碳传感器实战:5分钟搞定Arduino环境监测系统(附完整代码)

本文详细介绍了如何使用JW01二氧化碳传感器与Arduino快速搭建环境监测系统。通过简单的硬件连接和完整的代码示例,读者可以在5分钟内实现CO2浓度实时监测,并了解数据解析、常见问题解决及进阶应用扩展。JW01传感器的高精度和易用性使其成为创客和嵌入式开发者的理想选择。

kite3的博客 382

LOG4J2指定不同类型的日志输出到不同的文件

在项目中,可能会产生非常多的日志记录,为了方便日志分析,一般可以将日志按级别输出到指定文件,本次就先说说log4j2的实现吧。 我们配置的Appender默认情况下是可以输出任何类型的日志的,只要某个Logger引用了Appender,那么这个Logger中输出的任何日志信息都能输出到该Appender中,当前了Logger中是可以设置日志级别的,高于设置的级别才能输出,但是也不能达到我们想要的...

P19777的博客 5248

5.44GHz超高精度!STM32G474的HRTIM时钟配置避坑指南

本文深入解析STM32G474内置高分辨率定时器的时钟配置要点,帮助工程师避开常见陷阱。文章详细阐述了从系统时钟到5.44GHz等效时基的路径,重点分析了预分频器乘法器、周期计算溢出、影子寄存器同步等关键配置,并结合实测波形对比,确保HRTIM在电机控制、数字电源等精密应用中发挥极限性能。

book8的博客 522

Log4j和Log4j2的安装、配置讲解

什么是日志? 日志是记录系统或应用程序在运行过程中所发生事件或行为的详细信息的文件。它通常包括时间戳、事件类型、事件描述等信息,以便在需要时进行故障排查、性能优化、安全审计等工作。日志可以帮助开发人员和系统管理员诊断应用程序问题,了解系统运行情况,以及存档和监控事件。

qq_71443736的博客 1196

Electron vue3 - 使用SerialPort与串口交互教程,计算机串行端口(COM口、USB转串口等)进行通信连接读取或写入Arduino、单片机、PLC、扫码枪、打印机、老式调制解调器!

实战Electron使用SerialPort与串口交互详细全过程,Electron-vue3与串口交互示例,Electron vue使用serialport实现串口交互通讯,Electron-vue使用serialport连接本地串口,electron-vue 台称串口对接 SerialPort,electron串口调试工具,electron+vue+serialport实现串口通信,串口通信serialport使用和调试,electron-vue使用serialport串口通信及踩过的坑(已解决!)ele

🏆 前端领域优质创作者 4640

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

java 日志框架log4j2 示例4

java 日志框架log4j2 示例4

weixuan_的博客 301

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Java日志框架学习--JUL和Log4j--上

Java日志框架学习--上引言日志框架市面流行的日志框架日志门面和日志框架的区别JULJUL简介JUL组件介绍实际使用Logger之间的父子关系默认配置文件位置读取自定义配置文件追加日志信息Log4jLog4j简介Log4j组件介绍LoggersAppendersLayouts日志输出格式说明应用配置文件加载时机打开日志输出的详细信息自定义日志输出格式日志输出到文件日志按照文件大小进行拆分日志按照文件时间进行拆分 引言 日志框架 1.控制日志输出的内容和格式。 2.控制日志输出的位置。 3.日志文件相关的

m0_53157173的博客 1372

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

IDEA下Log4j使用教程

Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套 接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级 别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修 改应用的代码。 下

u010814766的博客 3万+

Log4J日志配置详解

一、Log4j简介 Log4j 有三个主要的组件:Loggers(记录器),Appenders (输出源)和Layouts(布局)。这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出。综合使用这三个组件可以轻松地记录信息的类型和 级别,并可以在运行时控制日志输出的样式和位置。 1、Loggers Loggers 组件在此系统中被分为五个级别:DEBUG、INF...

aiyu0831的博客 125

log4j2配置定期清理日志文件

<?xml version="1.0" encoding="UTF-8"?> <!-- configuration 属性 monitorInterval: 置配置文件的动态加载时间(s),在程序运行过程中,如果修改配置文件,程序会随之改变。 status: 设置 log4j 日志框架内部输出的日志级别 日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG

qq_36555149的博客 5738

log4j滚动输出压缩格式的文件

log4j滚动输出压缩格式的文件

我的博客 5305
上一篇: Oracle同义词
java2_0_1_0
博客等级 码龄17年 0粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值