返回顶部
首页 > 资讯 > 后端开发 > Python >关于log4j日志扩展---自定义PatternLayout
  • 498
分享到

关于log4j日志扩展---自定义PatternLayout

2024-04-02 19:04:59 498人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录log4j日志扩展---PatternLayout这是log4j官网上的配置下载官方文件发现有这样两个类给大家举个例子故完整的代码扩展log4j---自定义日志文件创建log4j

log4j日志扩展---PatternLayout

目前扩展log4j的日志一般使用扩展adaper的方法,这里使用一种扩展PatternLayout方法。


log4j.rootLogger=debug, stdout, R
 
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
 
# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log
log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

这是log4j官网上的配置

请注意:


log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
log4j.appender.R.layout=org.apache.log4j.PatternLayout

注意到其实这是两个类

那么org.apache.log4j.ConsoleAppender可以自定义,思考是否可以自定义log4j.appender.R.layout=org.apache.log4j.PatternLayout

下载官方文件发现有这样两个类



 
package examples; 
import org.apache.log4j.*;
import org.apache.log4j.helpers.PatternParser;
 

public class MyPatternLayout extends PatternLayout {
  public
  MyPatternLayout() {
    this(DEFAULT_CONVERSION_PATTERN);
  }
 
  public
  MyPatternLayout(String pattern) {
    super(pattern);
  }
    
  public
  PatternParser createPatternParser(String pattern) {
    return new MyPatternParser(
      pattern == null ? DEFAULT_CONVERSION_PATTERN : pattern);
  }
  
  public
  static void main(String[] args) {
    Layout layout = new MyPatternLayout("[counter=%.10#] - %m%n");
    Logger logger = Logger.getLogger("some.cat");
    logger.addAppender(new ConsoleAppender(layout, ConsoleAppender.SYSTEM_OUT));
    logger.debug("Hello, log");
    logger.info("Hello again...");    
  }
}


 
package examples; 
import org.apache.log4j.helpers.FORMattingInfo;
import org.apache.log4j.helpers.PatternConverter;
import org.apache.log4j.helpers.PatternParser;
import org.apache.log4j.spi.LoggingEvent;
 

public class MyPatternParser extends PatternParser { 
  int counter = 0; 
  public
  MyPatternParser(String pattern) {
    super(pattern);
  }
    
  public
  void finalizeConverter(char c) {
    if (c == '#') {
      addConverter(new UserDirPatternConverter(formattingInfo));
      currentLiteral.setLength(0);
    } else {
      super.finalizeConverter(c);
    }
  }
  
  private class UserDirPatternConverter extends PatternConverter {
    UserDirPatternConverter(FormattingInfo formattingInfo) {
      super(formattingInfo);
    }
 
    public
    String convert(LoggingEvent event) {
      return String.valueOf(++counter);
    }
  }  
}

直接粘过去找个类测试一下发现是可以使用的,显示打印日志的行数

发现MyPatternLayout基本调用的是父类的方法

继续扒


 public
  void finalizeConverter(char c) {
    if (c == '#') {
      addConverter(new UserDirPatternConverter(formattingInfo));
      currentLiteral.setLength(0);
    } else {
      super.finalizeConverter(c);
    }
  }

注意看这段代码

发现字符为"#"的时候,创建了UserDirPatternConverter

推荐大家去看PatternParser这里面有答案

给大家举个例子


%#{MMMM}

使用extractOption()可以获得MMMM

有了MMMM是不是就可以处理很多问题.

想一下,比如我们要在日志里面打印公司的编号 orgId

那么首先配置


log4j.appender.R.layout.ConversionPattern= %#{orgId}  %p %t %c - %m%n

这样的话


if (c == '#') {
            String exs = super.extractOption();  //获取orgId
            addConverter(new ExrPatternConverter(formattingInfo, exs));
            currentLiteral.setLength(0); 
        } else {
            super.finalizeConverter(c);
        }

考虑orgId的赋值问题

使用ThreadLocal

故完整的代码


package com.yogapay.core; 
import java.util.HashMap;
import java.util.Map; 
import org.apache.log4j.helpers.FormattingInfo;
import org.apache.log4j.helpers.PatternConverter;
import org.apache.log4j.helpers.PatternParser;
import org.apache.log4j.spi.LoggingEvent; 
public class ExPatternParser extends PatternParser {
 
 static final ThreadLocal<Map<String, Object>> TH_LOCAL = new ThreadLocal<Map<String, Object>>(){
  @Override
        protected HashMap<String, Object> initialValue() {
            return new HashMap<String, Object>();
        } 
 };
 
 public static void setCurrentValue(String key, Object value) {
  Map<String, Object> map = TH_LOCAL.get();
  map.put(key, value);  
 }
 
 public ExPatternParser(String pattern) {
  super(pattern);
 }
 
 public void finalizeConverter(char c) {
  if (c == '#') {
   String exs = super.extractOption();
   addConverter(new ExrPatternConverter(formattingInfo, exs));
   currentLiteral.setLength(0); 
  } else {
   super.finalizeConverter(c);
  }
 }
 
 private class ExrPatternConverter extends PatternConverter { 
  private String cfg; 
  ExrPatternConverter(FormattingInfo formattingInfo, String cfg) {
   super(formattingInfo);
   this.cfg = cfg;
  }
 
  public String convert(LoggingEvent event) {
   Map<String, Object> valueMap = TH_LOCAL.get();
   if (valueMap != null) {
    Object value = valueMap.get(cfg);
    if (value != null) {
     return String.valueOf(value);
    }
   }
   return "";
  }
 }
}

package com.yogapay.core; 
import org.apache.log4j.*;
import org.apache.log4j.helpers.PatternParser; 
public class ExPatternLayout extends PatternLayout {
 public ExPatternLayout() {
  this(DEFAULT_CONVERSION_PATTERN);
 }
 
 public ExPatternLayout(String pattern) {
  super(pattern);
 } 
        @Override
 public PatternParser createPatternParser(String pattern) {
  return new ExPatternParser(pattern == null ? DEFAULT_CONVERSION_PATTERN : pattern);
 }
}

### set log levels ###
log4j.rootLogger = info,stdout
 
### 输出到控制台 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = com.yogapay.core.ExPatternLayout
log4j.appender.stdout.layout.ConversionPattern = lGCNo:%#{orgId} %d{yyyy-MM-dd HH:mm:ss} [%t] %p [%c] - %m%n

到此扩展就完成呢!

扩展log4j---自定义日志文件创建

之前使用过logstash,发现它的文件写入功能比log4j更加完善

logstash允许动态创建文件夹,我只使用了按照日期创建日志文件

如果配置日志路径如下

/home/log/log/%{yyyy}/%{MM}/%{dd}-log.log

那么就会创建路径为/home/log/log/2018/06/12-log.log的文件

log4j有个DailyRollingFileAppender,支持按一定时间规则写入日志,但是创建规则是在原有的日志文件之后加上时间后缀,这样所有日志文件都在一个文件夹,非常不友好

因此,我自定义了appender,允许创建文件夹的方式存储日志文件,每天凌晨写入新的日志文件

内容如下


import org.apache.log4j.spi.LoggingEvent; 
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 

public class EveryDayRollingFileAppender extends FileAppender { 
    private SimpleDateFormat format;
    private String fileName; 
    private Level level; 
    private static final String SEPERTOR = "-";
    private String regex = "\\{([^\\{\\}]+)\\}";// 
    private long next; 
    private Date now; 
    public Level getLevel() {
        return level;
    }
 
    public void setLevel(Level level) {
        this.level = level;
    }
 
    public EveryDayRollingFileAppender() {
        now = new Date();
        level = Level.WARN;
    }
 
 
    public String getFileName() {
        return fileName;
    }
 
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
 
    //TODO 18-6-16 该方法被调用了两次
    @Override
    public void activateOptions() {
        Pattern pattern = Pattern.compile(regex);  
        Matcher matcher = pattern.matcher(fileName);
        StringBuilder builder = new StringBuilder();
        while (matcher.find()) {
            String temp = matcher.group(1); 
            builder.append(temp).append(SEPERTOR);
 
        }
        if (builder.length() != 0) {
            format = new SimpleDateFormat(builder.deleteCharAt(builder.length() - 1).toString());
            changeFile();
            setNextTime();日志采集小工具
        } else {
            format = null;
            try {
                setFile(fileName, getAppend(), getBufferedIO(), getBufferSize());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }  
    }
 
    private void changeFile() {
        if (format != null) {
            try {
                setFile(createFile(), getAppend(), getBufferedIO(), getBufferSize());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
    protected void setNextTime() {
        Calendar c = Calendar.getInstance();
        c.setTime(now);
        c.add(Calendar.DAY_OF_YEAR, 1);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.HOUR, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        next = c.getTimeInMillis(); 
        System.out.println(new Date(next));
    } 
 
    @Override
    protected void subAppend(LoggingEvent event) {
        if (event.getLevel().syslogEquivalent <= level.syslogEquivalent) {
            long n = System.currentTimeMillis();
            if (n >= next) {
                now.setTime(n); 
                changeFile(); 
                setNextTime();  
            }
            super.subAppend(event);
        }
    }
 
    public String createFile() {
        String file = format.format(now); 
        String s[] = file.split(SEPERTOR); 
        String temp = fileName;
        for (int i = 0; i < s.length; i++) {
            temp = temp.replaceFirst(regex, s[i]);
        } 
 
        File f = new File(temp);
        if (!f.getParentFile().exists())
            f.getParentFile().mkdirs();
        else if (f.exists())
            f.delete(); 
        return f.getAbsolutePath(); 
    }
}

log4j配置如下


log4j.appender.logfile=org.apache.log4j.EveryDayRollingFileAppender
# 需要写入的日志级别
log4j.appender.logfile.level=INFO
# 日志路径
log4j.appender.logfile.fileName=/home/inkbox/log/log/{yyyy}/{MM}/{dd}_logSocket.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%m%n

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: 关于log4j日志扩展---自定义PatternLayout

本文链接: https://lsjlt.com/news/160610.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 关于log4j日志扩展---自定义PatternLayout
    目录log4j日志扩展---PatternLayout这是log4j官网上的配置下载官方文件发现有这样两个类给大家举个例子故完整的代码扩展log4j---自定义日志文件创建log4j...
    99+
    2024-04-02
  • log4j如何自定义日志级别
    要自定义日志级别,您可以按照以下步骤进行操作:1. 创建一个自定义的日志级别。在Log4j中,日志级别是通过`Level`类表示的。...
    99+
    2023-09-13
    log4j
  • 自定义log4j日志文件命名规则说明
    目录自定义log4j日志文件命名规则根据log4j的API定义自己的FileAppender对应的log4j.properties的配置文件如下输出的日志文件命名如下log4j自定义...
    99+
    2024-04-02
  • 自定义log4j日志文件命名规则是什么
    小编给大家分享一下自定义log4j日志文件命名规则是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!自定义log4j日志文件命名规则项目中的日志需要采用一致的命...
    99+
    2023-06-22
  • log4j日志格式加入自定义字段信息方式
    目录log4j日志格式加入自定义字段信息log4j2入库自定义字段类型官方API文档中只提供了几个属性设置isNumber=“true”log4j日志格式加入自定义字段信息 在使用l...
    99+
    2024-04-02
  • PHP怎么自定义扩展
    本篇内容主要讲解“PHP怎么自定义扩展”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PHP怎么自定义扩展”吧!利用源码工具自动生成扩展目录结构先进入php源码ext目录下执行下面命令/www/t...
    99+
    2023-06-22
  • php 自定义安装扩展
    ✨ 目录 🎈 扩展目录🎈 编译扩展🎈 配置扩展🎈 编译安装🎈 编译结果🎈 开启扩展&#...
    99+
    2023-08-31
    php 开发语言 扩展 经验分享 安装教程
  • 如何实现log4j日志格式加入自定义字段信息
    这篇文章主要为大家展示了“如何实现log4j日志格式加入自定义字段信息”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何实现log4j日志格式加入自定义字段信息”这篇文章吧。log4j日志格式加...
    99+
    2023-06-22
  • 关于Spring自定义XML schema 扩展的问题(Spring面试高频题)
    引言 自从SpringBoot时代的到来,去除了Spring的各种繁琐的XML配置,让我们可以腾出双手以便于更加专注的搬砖。记得那时候刚学Spring的时候,每天被Spring的各种...
    99+
    2024-04-02
  • Mybatis-Generator扩展自定义的生成
    Mybatis-Generator 可自动生成Model、Dao、Mapper代码,但其自带生成的代码存在以下问题:生成的注释不是我们想要的,我们期望的是根据数据库表、字段生成不同的注释;分页代码生成缺失,...
    99+
    2024-04-02
  • SpringBoot之自定义Schema扩展方式
    目录SpringBoot 自定义Schema扩展1. 配置ServiceConfig属性2. 编写XSD文件3. 编写NamespaceHandler4. 编写BeanDefinit...
    99+
    2024-04-02
  • jquery怎么扩展自定义方法
    要扩展自定义方法,可以使用jQuery的`$.fn`命名空间。下面是一个简单的示例:```javascript// 扩展自定义方法$...
    99+
    2023-08-12
    jquery
  • .NetCore日志记录之自定义日志组件
    一、前言 回顾:日志记录之日志核心要素揭秘 在上一篇中,我们通过学习了解在.net core 中内置的日志记录中的几大核心要素,在日志工厂记录器(ILoggerFactory)中实现...
    99+
    2024-04-02
  • ThinkPHP下 自定义日志输出
    项目场景: 不想调用TP的 think/Log类工具,而是自定义日志的输出路径、文件名和内容: 解决方案: 提示:这里填写该问题的具体解决方案: 首先在common.php公共函数文件下写需...
    99+
    2023-10-12
    php 开发语言
  • JMeter自定义日志与日志分析的实现
    目录1 JMeter日志概览2 JMeter自定义日志3 JMeter日志分析1 JMeter日志概览 JMeter与Java程序一样,会记录事件日志,日志文件保存在bin目录中,名...
    99+
    2024-04-02
  • 如何实现JMeter自定义日志与日志分析
    这篇文章主要介绍如何实现JMeter自定义日志与日志分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1 JMeter日志概览JMeter与Java程序一样,会记录事件日志,日志文件保存在bin目录中,名称为jmet...
    99+
    2023-06-22
  • 怎么自定义一个jQuery扩展接口
    这篇文章给大家介绍怎么自定义一个jQuery扩展接口,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。jQuery是一款很优秀的轻量级JavaScript框架,有其独特的优点。很多Web开...
    99+
    2024-04-02
  • 什么是Mybatis-Generator扩展自定义生成
    这篇文章给大家介绍什么是Mybatis-Generator扩展自定义生成,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Mybatis-Generator 可自动生成Model、Dao、...
    99+
    2024-04-02
  • vue实现自定义表格工具扩展
    本文实例为大家分享了vue自定义表格工具扩展的具体代码,供大家参考,具体内容如下 工具组件 <template>     <div class="right-btn...
    99+
    2024-04-02
  • Springboot自定义mybatis拦截器实现扩展
    前言 相信大家对拦截器并不陌生,对mybatis也不陌生。 有用过pagehelper的,那么对mybatis拦截器也不陌生了,按照使用的规则触发sql拦截,帮我们自动添加分页参数 ...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作