log4j2 with custom appender and patternlayout not working
我在我的Web项目中使用log4j2。 我试图通过扩展abstractAppender将日志直接放入kafka。 根据文档,我的理解是,我可以为自定义的附加程序指定patternlayout,并设置该格式,我的记录器将使用格式化后的字符串将日志事件发送到kafka,但这没有发生。 log4j2.xml看起来像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <?xml version="1.0" encoding="UTF-8"?> <Configuration status="info" packages="com.abc.webservice.log.appender"> <Appenders> <Console name="console" target="SYSTEM_OUT"> <PatternLayout> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L- %X{sessionId}--%X{guid}- %m #]%n</pattern> </PatternLayout> </Console> <Kafka name="kafka" topic="test"> <PatternLayout> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L- %X{sessionId}--%X{guid}- %m #]%n</pattern> </PatternLayout> <Property name="metadata.broker.list">127.0.0.1:9092</Property> <Property name="serializer.class">kafka.serializer.StringEncoder</Property> </Kafka> </Appenders> <Loggers> <AsyncLogger name="async"> <AppenderRef ref="kafka" /> <AppenderRef ref="console" /> </AsyncLogger> <Root level="info"> <AppenderRef ref="console" /> <AppenderRef ref="kafka" /> </Root> <Logger name="com.abc" level="debug"> <!-- --> <!----> <!----> </Logger> <Logger name="org.hibernate.SQL"> </Logger> <Logger name="org.hibernate.type"> </Logger> <Root level="info"> <AppenderRef ref="kafka"/> <AppenderRef ref="console"/> </Root> </Loggers> </Configuration> |
如果我使用控制台附加程序,则日志采用正确的格式,但是当我使用自定义附加程序时,将接收不带格式的日志。 我如何使用指定的paatternlayout将日志发送到kafka。
请找到我的追加器实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | import java.io.Serializable; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.logging.log4j.core.Filter; import org.apache.logging.log4j.core.Layout; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.appender.AbstractAppender; import org.apache.logging.log4j.core.appender.AppenderLoggingException; import org.apache.logging.log4j.core.config.Property; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.plugins.PluginAttribute; import org.apache.logging.log4j.core.config.plugins.PluginElement; import org.apache.logging.log4j.core.config.plugins.PluginFactory; import org.apache.logging.log4j.core.layout.PatternLayout; import org.apache.logging.log4j.core.util.Booleans; import org.apache.logging.log4j.message.Message; @Plugin(name ="Kafka", category ="Core", elementType ="appender", printObject = true) public final class KafkaAppender extends AbstractAppender { private final Lock lock = new ReentrantLock(); private KafkaManager manager; protected KafkaAppender(String name, Filter filter, Layout layout, boolean ignoreExceptions, KafkaManager manager) { super(name, filter, layout, ignoreExceptions); System.err.println("hello world hello"); this.manager = manager; } @PluginFactory public static KafkaAppender createAppender(@PluginAttribute("name") final String name, @PluginElement("Filter") final Filter filter, @PluginAttribute("ignoreExceptions") final String ignore, @PluginAttribute("topic") final String topic, @PluginElement("Properties") final Property[] properties, @PluginElement("layout") final Layout layout) { boolean ignoreExceptions = Booleans.parseBoolean(ignore, true); KafkaManager kafkaManager = KafkaManager.getKafkaManager(name, topic, properties); if (kafkaManager == null) { return null; } // Layout patternLayout = PatternLayout.createLayout("%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L- %X{sessionId}--%X{guid}- %m #]%n", // null, null, null, true, false, null, null); // System.err.println(patternLayout.toString()); return new KafkaAppender(name, filter, layout, ignoreExceptions, kafkaManager); } @Override public final void start() { if (this.getManager() == null) { LOGGER.error("No KafkaManager set for the appender named [{}].", this.getName()); } super.start(); if (this.getManager() != null) { this.getManager().startup(); } } @Override public final void stop() { super.stop(); if (this.getManager() != null) { this.getManager().release(); } } public final KafkaManager getManager() { return this.manager; } public void append(LogEvent event) { this.lock.lock(); try { String s = event.getMessage().getFormattedMessage(); Message logEvent1 = event.getMessage(); String sp = logEvent1.getFormattedMessage(); this.getManager().send(event.getMessage().getFormattedMessage()); } catch (final Exception e) { LOGGER.error("Unable to write to kafka [{}] for appender [{}].", this.getManager().getName(), this.getName(), e); throw new AppenderLoggingException("Unable to write to kafka in appender:" + e.getMessage(), e); } finally { this.lock.unlock(); } } @Override public Layout<? extends Serializable> getLayout() { Layout patternLayout = PatternLayout.createLayout("%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L- %X{sessionId}--%X{guid}- %m #]%n", null, null, null, true, false, null, null); return patternLayout; } } |
在KafkaAppender类中,您的append方法应调用
我注意到示例代码覆盖了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @Override public void append(LogEvent event) { this.lock.lock(); try { // let the Layout format the data in the LogEvent object final byte[] bytes = getLayout().toByteArray(event); // then pass the byte[] array with the formatted event to the manager // (I assume that your manager provides this method) manager.write(bytes, 0, bytes.length); } catch (Exception e) { LOGGER.error("Unable to write to kafka [{}] for appender [{}].", this.getManager().getName(), this.getName(), e); if (!ignoreExceptions()) { throw new AppenderLoggingException( "Unable to write to kafka in appender:" + e.getMessage(), e); } } finally { this.lock.unlock(); } } // I would recommend not to override getLayout. // The AbstractAppender implementation of getLayout returns the configured // layout, which allows you to control the layout in configuration // without code changes. // @Override // public Layout<? extends Serializable> getLayout() {... |