Python 官方文档:入门教程 => 点击学习
目录log4j日志扩展---PatternLayout这是log4j官网上的配置下载官方文件发现有这样两个类给大家举个例子故完整的代码扩展log4j---自定义日志文件创建log4j
目前扩展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.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
到此扩展就完成呢!
之前使用过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.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
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0