问题描述
我将EAR应用程序从log4j迁移到log4j2.我有课程扩展了附录,过滤器,不同的EAR罐中的布局,现在,我将其转换为插件.这意味着我在一个以上的罐子中有自定义插件(假设3罐).
我没有在log4j2.xml中使用packages属性,并且通过使用指向log4j2.xml log4j2.xml ear META-INF位置的Dlog4j.configurationFile JVM参数来初始化记录系统.
在所有三个JAR项目中添加以下插件均无效.
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <executions> <execution> <id>log4j-plugin-processor</id> <goals> <goal>compile</goal> </goals> <phase>process-classes</phase> <configuration> <proc>only</proc> <annotationProcessors> <annotationProcessor>org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor</annotationProcessor> </annotationProcessors> </configuration> </execution> </executions> </plugin>
模式布局: 在下面的模式布局中,e是自定义模式,其中写了自定义模式转换器插件以转换此字符串.
<Pattern>%d %-5p [%c{1}] [EventId: %e] [%t] %m%n</Pattern>
上述图案布局的自定义转换器插件(在JAR1中):
jar1在META-INF in org.apache..文件夹中Log4J2Plugins.dat文件.
@Plugin(name = "EventPatternConverter", category = "Converter") @ConverterKeys({"e"}) public class EventPatternConverter extends LogEventPatternConverter { protected EventPatternConverter(String name, String style) { super(name, style); } public static EventPatternConverter newInstance(String[] options) { return new EventPatternConverter("e", "e"); } @Override public void format(LogEvent event, StringBuilder toAppendTo) { String eventId= ""; // Append empty string (OR) value toAppendTo.append(eventId); } }
但是,我得到以下错误
ERROR Unrecognized format specifier [e]
,即使我在jar2,jar3中都可以使用的其余自定义插件invalid element都没有确定自定义插件.
ERROR File contains an invalid element or attribute "TestFilter"
我正在使用log4j-api-2.4.jar,log4j-core-2.4.jar,log4j-jcl-2.4.jar,log4j-web-2.4.1.jar,commons-logging-1.1.1.jar耳朵中的罐子.
我已经定义了一个自定义模式转换器插件,并期望将此转换器应用于所有模式布局,包括使用<patternlayout>定义的默认模式布局.这是对的吗?
如果是的,请提供帮助,如果有人遇到此问题并指导我在定义自定义插件方面是错误的,因为它们都没有从耳朵中的罐子中被检测到.
推荐答案
编译自定义插件时,log4j pom.xml定义了一个插件,该插件自动在文件meta meta-inf/org/apache/loging/log4j/log4j/core config/config/fignins/log4j2plugins.dat中自动生成高速缓存数据 您可以在Maven项目中在目标/类下看到此.
log4j-core-2.x.x.jar还包含一个log4j2plugins.dat定义其缓存数据.
问题是在使用shninkwrap测试耳朵时创建一个jar,通常是log4j-core-2.x.x.x.jar log4j2plugins.dat添加到测试罐中,因为它很可能是在类路径中首次.<<<<<<<<<<<<<<<<<<<<<<<<
这意味着您的自定义插件缓存丢失.
使用缩小关节的解决方案是创建一个新的log4j2plugins.dat将任何必需的自定义插件缓存文件与内核合并,然后将其添加到JAR中.
以下功能实现了...
private static void mergeLog4J2Log4j2PluginsFile(JavaArchive ja, Class... uniqueJARClasses) { // @Author: Johnathan Ingram <jingram@rogueware.org> // Log4J2 uses /META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat within a JAR to define custom plugins // This is automatically generated by the plugin defined in the log4j-core-2.x.x pom.xml when compiling your custom plugin // The problem with shrinkwrap is that the JAR is not preserved and only a single // /META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat // file can exist as JAR files cannot be added to a JAR file as a library. // This is normally the default contained in log4j-core-2.x.x.jar which does not expose any custom plugins // To rectify, both the core and the custom plugin JAR file Log4j2Plugins.dat need to be merged into a single Log4j2Plugins.dat try { // List of a unique class in each JAR containing a Log4j2Plugins.dat requiring merging Vector<URL> datUrls = new Vector<URL>(); for (Class klass : uniqueJARClasses) { // Find the JAR the class belongs to URL classLoc = klass.getProtectionDomain().getCodeSource().getLocation(); URL resourceURL = classLoc.toString().endsWith(".jar") ? new URL("jar:" + URLDecoder.decode(classLoc.toString(), "UTF-8") + "!/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat") : new URL(URLDecoder.decode(classLoc.toString(), "UTF-8") + "/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat"); datUrls.add(resourceURL); } // Use the Log4J2 PluginCache to build a merged Log4j2Plugins.dat File mergedDatFile = new File("target/Log4j2Plugins.dat"); try (FileOutputStream fo = new FileOutputStream(mergedDatFile)) { org.apache.logging.log4j.core.config.plugins.processor.PluginCache pc = new org.apache.logging.log4j.core.config.plugins.processor.PluginCache(); pc.loadCacheFiles(datUrls.elements()); pc.writeCache(fo); } // Replace the default Log4j2Plugins.dat if present ja.delete("/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat"); ja.addAsManifestResource(mergedDatFile, "org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat"); } catch (Exception ex) { ex.printStackTrace(System.err); } }
使用您的示例运行:
JavaArchive ja = ShrinkWrap.create(JavaArchive.class, "my-test.jar"); ... mergeLog4J2Log4j2PluginsFile(ja, org.apache.logging.log4j.core.config.plugins.processor.PluginCache.class, EventPatternConverter.class);
问题描述
I am migrating an EAR application from log4j to log4j2. I had classes extending appenders, filters, layouts in different jars of EAR and now, I have converted those to plugins. This means I have custom plugins in more than one jar (assume 3 jars).
I am not using packages attribute in log4j2.xml and am initializing the logging system by using Dlog4j.configurationFile JVM argument pointing to log4j2.xml location in META-INF of EAR.
Adding the below plugin in all the three jar projects did not work .
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <executions> <execution> <id>log4j-plugin-processor</id> <goals> <goal>compile</goal> </goals> <phase>process-classes</phase> <configuration> <proc>only</proc> <annotationProcessors> <annotationProcessor>org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor</annotationProcessor> </annotationProcessors> </configuration> </execution> </executions> </plugin>
Pattern layout: In the below pattern layout, e is the custom pattern where a custom pattern converter plugin is written to convert this string.
<Pattern>%d %-5p [%c{1}] [EventId: %e] [%t] %m%n</Pattern>
Custom converter plugin for the above pattern layout (in jar1):
jar1 has Log4J2Plugins.dat file under META-INF in org.apache.. folder.
@Plugin(name = "EventPatternConverter", category = "Converter") @ConverterKeys({"e"}) public class EventPatternConverter extends LogEventPatternConverter { protected EventPatternConverter(String name, String style) { super(name, style); } public static EventPatternConverter newInstance(String[] options) { return new EventPatternConverter("e", "e"); } @Override public void format(LogEvent event, StringBuilder toAppendTo) { String eventId= ""; // Append empty string (OR) value toAppendTo.append(eventId); } }
But, I am getting the below error
ERROR Unrecognized format specifier [e]
Even, none of the custom plugins are identified as I am getting invalid element for rest of the custom plugins which are all available in jar2, jar3 and they all have Log4J2Plugins.dat file.
ERROR File contains an invalid element or attribute "TestFilter"
I am using log4j-api-2.4.jar, log4j-core-2.4.jar, log4j-jcl-2.4.jar, log4j-web-2.4.1.jar, commons-logging-1.1.1.jar jars in the EAR.
I have defined a custom pattern converter plugin and expecting this converter gets applied to all pattern layout including default pattern layout defined using <patternlayout>. Is this right ?
If yes, the please help if anyone faced this issue and guide me if I am wrong in defining the custom plugin as they are all not getting detected from jars in EAR.
推荐答案
When compiling a custom Plugin, the Log4J pom.xml defines a plugin that automatically generates cache data in the file META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat You can see this under your target/classes in a Maven project.
The log4j-core-2.x.x.jar also contains a Log4j2Plugins.dat defining its cache data.
The problem is a single JAR is created when testing an EAR using ShrinkWrap and normally the log4j-core-2.x.x.jar Log4j2Plugins.dat is added to the test JAR as it would most likely be first in the class path.
This means your custom plugin cache is missing.
The solution using ShrinkWrap is to create a new Log4j2Plugins.dat merging any required custom plugin cache files with the cores and then adding that to the JAR.
The following function achieves that...
private static void mergeLog4J2Log4j2PluginsFile(JavaArchive ja, Class... uniqueJARClasses) { // @Author: Johnathan Ingram <jingram@rogueware.org> // Log4J2 uses /META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat within a JAR to define custom plugins // This is automatically generated by the plugin defined in the log4j-core-2.x.x pom.xml when compiling your custom plugin // The problem with shrinkwrap is that the JAR is not preserved and only a single // /META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat // file can exist as JAR files cannot be added to a JAR file as a library. // This is normally the default contained in log4j-core-2.x.x.jar which does not expose any custom plugins // To rectify, both the core and the custom plugin JAR file Log4j2Plugins.dat need to be merged into a single Log4j2Plugins.dat try { // List of a unique class in each JAR containing a Log4j2Plugins.dat requiring merging Vector<URL> datUrls = new Vector<URL>(); for (Class klass : uniqueJARClasses) { // Find the JAR the class belongs to URL classLoc = klass.getProtectionDomain().getCodeSource().getLocation(); URL resourceURL = classLoc.toString().endsWith(".jar") ? new URL("jar:" + URLDecoder.decode(classLoc.toString(), "UTF-8") + "!/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat") : new URL(URLDecoder.decode(classLoc.toString(), "UTF-8") + "/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat"); datUrls.add(resourceURL); } // Use the Log4J2 PluginCache to build a merged Log4j2Plugins.dat File mergedDatFile = new File("target/Log4j2Plugins.dat"); try (FileOutputStream fo = new FileOutputStream(mergedDatFile)) { org.apache.logging.log4j.core.config.plugins.processor.PluginCache pc = new org.apache.logging.log4j.core.config.plugins.processor.PluginCache(); pc.loadCacheFiles(datUrls.elements()); pc.writeCache(fo); } // Replace the default Log4j2Plugins.dat if present ja.delete("/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat"); ja.addAsManifestResource(mergedDatFile, "org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat"); } catch (Exception ex) { ex.printStackTrace(System.err); } }
To run using your example:
JavaArchive ja = ShrinkWrap.create(JavaArchive.class, "my-test.jar"); ... mergeLog4J2Log4j2PluginsFile(ja, org.apache.logging.log4j.core.config.plugins.processor.PluginCache.class, EventPatternConverter.class);