问题描述
我正在尝试为log4j 2.0创建一个自定义模式转换器,但是有问题获得我的log4j配置以识别模式.这是自定义转换器:
package com.test.log4j.plugins; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.pattern.ConverterKeys; import org.apache.logging.log4j.core.pattern.LogEventPatternConverter; @Plugin(name="MarkerNamePatternConverter", category="Converter") @ConverterKeys({"markername"}) public class MarkerNamePatternConverter extends LogEventPatternConverter { public static MarkerNamePatternConverter newInstance(final String[] options) { return new MarkerNamePatternConverter("markername", "markername"); } protected MarkerNamePatternConverter(String name, String style) { super(name, style); } @Override public void format(LogEvent event, StringBuilder toAppendTo) { Marker marker = event.getMarker(); if (marker != null) { // MarkerPatternConverter appends Marker.toString() // which includes the parents of the marker. We just // want the marker's name toAppendTo.append(marker.getName()); } } }
这是我的log4j配置文件:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="trace" packages="com.test.log4j.plugins"> <Appenders> <Console name="console" target="SYSTEM_OUT"> <PatternLayout pattern=" %-6level %markername %d{YYYY-MM-dd HH:mm:ss} %msg%n"/> </Console> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="console"/> </Root> </Loggers> </Configuration>
请注意,我包含了包含配置中自定义转换器的软件包,在使用自定义插件时,缺少这些软件包似乎是出现问题的常见原因.
执行测试代码时,配置状态输出并不表示插件已加载或找到插件,并且Log4J将%MarkerName视为"%标记"转换模式,后跟"名称".例如,
Marker marker = MarkerManager.getMarker("TEST"); log.info(marker, "test message");
产生以下输出:
INFO TESTname 2014-07-23 14:47:57 test message
我尝试更改转换键,一个不以标准转换模式开头的值,例如" fmarker",并且执行log4j时会产生以下错误:
2014-07-23 14:44:55,814 ERROR Unrecognized format specifier [fmarker] 2014-07-23 14:44:55,816 ERROR Unrecognized conversion specifier [fmarker] starting at position 18 in conversion pattern. INFO %fmarker 2014-07-23 14:44:55 test message
文档表明插件是在构建时间而不是运行时收集的,但是我还没有找到任何表明我需要做的事情以使我的自定义转换器的其他内容除了:
以外.- 用@plugin和@converterkeys注释它
- 将插件的类别指定为"转换器"
- 包括静态" newinstance(string [])"方法
- 实施"格式"方法
- 使用配置的"软件包"参数指定插件软件包.
有Maven插件的文档,但我的简单测试只是Eclipse中开发的基本Java项目.
关于我做错了什么的想法?
推荐答案
要简要简短,因为版本2.0-rc2,包装属性不再起作用.取而代之的是,Log4J核中有一个注释处理器,该处理器将在构建过程中运行(应该?),并且会在JAR文件中为您的自定义插件生成元数据文件. log4j2开始时,它将在所有JAR文件中查找元数据文件,并快速发现所有可用的插件.
用Maven或Pline Javac编译时,注释处理器可以工作,但是在Eclipse中编译时可能无法正常工作.您需要使用右键单击项目>属性> java编译器>注释处理.
启用注释处理.仍然,我不确定这将从Eclipse起作用.目前,一种选择是用Maven构建自定义插件.
我将尝试在即将发布的版本中再次使包裹属性再次起作用.
此处在此处跟踪: https://issues.apace.apache.org/jira/浏览/log4j2-741
更新(7/28)这是在中继中修复的,将包含在2.0.1版本中.
其他推荐答案
我也花了几个小时来挣扎着这个...
显然,这都是关于类加载!
使用此技巧:
使用 -verbose运行您的应用:类(它将通过其订单打印所有由JVM加载的类)
)例如.
java -verbose:class -cp <your_jar> <your_main_class> ...
搜索 log4j2 转换器类;在您的情况下,应该看起来像这样:
[Loaded com.test.log4j.plugins.MarkerNamePatternConverter from jar:file: ...]
您可能会注意到,转换器类已加载相对较晚(我假设应该加载Log4J2插件后).
要解决此问题,您可以尝试以下一项:
- 显式加载转换器类,即类(...)
- 更改转换器类位置:将其放在您的主类旁边或下方(按软件包层次结构)
我尝试了这两个选项 - 第二个选择对我有用!
goodluck
问题描述
I am trying to create a custom pattern converter for log4j 2.0, but am having issues getting my log4j configuration to recognize the pattern. Here is the custom converter:
package com.test.log4j.plugins; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.pattern.ConverterKeys; import org.apache.logging.log4j.core.pattern.LogEventPatternConverter; @Plugin(name="MarkerNamePatternConverter", category="Converter") @ConverterKeys({"markername"}) public class MarkerNamePatternConverter extends LogEventPatternConverter { public static MarkerNamePatternConverter newInstance(final String[] options) { return new MarkerNamePatternConverter("markername", "markername"); } protected MarkerNamePatternConverter(String name, String style) { super(name, style); } @Override public void format(LogEvent event, StringBuilder toAppendTo) { Marker marker = event.getMarker(); if (marker != null) { // MarkerPatternConverter appends Marker.toString() // which includes the parents of the marker. We just // want the marker's name toAppendTo.append(marker.getName()); } } }
And here is my log4j configuration file:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="trace" packages="com.test.log4j.plugins"> <Appenders> <Console name="console" target="SYSTEM_OUT"> <PatternLayout pattern=" %-6level %markername %d{YYYY-MM-dd HH:mm:ss} %msg%n"/> </Console> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="console"/> </Root> </Loggers> </Configuration>
Note that I have included the package which contains the custom converter in my configuration, the lack of which seems to be a common cause of issues when using custom plugins.
When test code is executed, the configuration status output does not indicate that the plugin is loaded or found, and log4j treats the %markername as if it is the "%marker" conversion pattern followed by "name". For example,
Marker marker = MarkerManager.getMarker("TEST"); log.info(marker, "test message");
produces the following output:
INFO TESTname 2014-07-23 14:47:57 test message
I tried changing the conversion key a value that did not start with a standard conversion pattern, e.g. "fmarker", and when executed log4j produces the following error:
2014-07-23 14:44:55,814 ERROR Unrecognized format specifier [fmarker] 2014-07-23 14:44:55,816 ERROR Unrecognized conversion specifier [fmarker] starting at position 18 in conversion pattern. INFO %fmarker 2014-07-23 14:44:55 test message
Documentation indicates that plugins are gathered at build time rather than runtime, but I haven't found anything that indicates that I need to do something specific to get my custom converter to be found other than to:
- Annotate it with @Plugin and @ConverterKeys
- Specify the plugin's category to be a "Converter"
- Include a static "newInstance(String[])" method
- Implement the "format" method
- Specify the plugin package with the configuration's "packages" parameter.
There was documentation for a Maven plugin, but my simple test is just a basic Java project developed in Eclipse.
Any ideas on what I am doing wrong?
推荐答案
To make a long story short, since version 2.0-rc2, the packages attribute does not work any more. Instead, there is an annotation processor in log4j-core that will (should?) run during the build and will generate a metadata file for your custom plugins in your jar file. When log4j2 starts it will look for the metadata file in all jar files and quickly discover all available plugins.
The annotation processor works when compiling with Maven or with plain javac, but it may not work well when compiling in Eclipse. You need to enable annotation processing with right-click on a project > Properties > Java Compiler > Annotation Processing.
Still, I am not 100% sure this will work from Eclipse. For now, one alternative is to build your custom plugin with Maven.
I will try to make the packages attribute work again in an upcoming release.
This issue is tracked here: https://issues.apache.org/jira/browse/LOG4J2-741
UPDATE (7/28) This is fixed in trunk and will be included in the 2.0.1 release.
其他推荐答案
I spent a couple of hours struggling with this one as well...
Apparently, it's all about class loading!
Use this trick:
Run your app using -verbose:class (it will print all the classes loaded by the JVM by their order)
e.g.
java -verbose:class -cp <your_jar> <your_main_class> ...
Search for the log4j2 converter class; in your case, it should look like this:
[Loaded com.test.log4j.plugins.MarkerNamePatternConverter from jar:file: ...]
You'll probably note that the converter class is loaded relatively late (I assume after the log4j2 plugins are supposed to get loaded).
To fix this, you can try one of the following:
- Load the converter class explicitly, i.e. Class.forName(...)
- Change the converter class location: put it next to your main class or underneath it (in terms of package hierarchy)
I tried both of these options - the second one worked for me!
Goodluck