From aa774a999447eae79376e31f60f4454bc6ff517d Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Thu, 10 Feb 2022 15:25:02 +0000 Subject: [PATCH] Add 'domain' parameter to the Log4j 2.x agent The initial Log4j 2.x agent commit only implemented a compatibility mode to be used with the existing LOG4J domain in lttng-tools. In this mode the agent converts the new Log4j 2.x loglevel values to their corresponding Log4j 1.x values in the same way the upstream compatibility bridge does. This is great when doing in-place migration using the upstream compatibility bridge but doesn't cover the usecase of an application that natively uses Log4j 2.x. This commit adds a new mandatory 'domain' parameter to the Log4j2 agent which currently only implements the 'LOG4J' compatibility domain in preparation to adding a 'LOG4J2' domain. The configuration for a single appender in Log4j 1.x compat mode will now look like this: Change-Id: I7fd5f79ad58c77175714bd4198d8ff5db2e6b846 Signed-off-by: Michael Jeanson Signed-off-by: Mathieu Desnoyers --- doc/examples/java-log4j2-basic/log4j2.xml | 2 +- doc/examples/java-log4j2-ctx/log4j2.ctx1.xml | 2 +- doc/examples/java-log4j2-ctx/log4j2.ctx2.xml | 2 +- .../java-log4j2-prog/HelloLog4j2Prog.java | 7 +- .../ust/agent/log4j2/LttngLogAppender.java | 78 +++++++++++++------ 5 files changed, 63 insertions(+), 28 deletions(-) diff --git a/doc/examples/java-log4j2-basic/log4j2.xml b/doc/examples/java-log4j2-basic/log4j2.xml index 2dc83dd3..6ebcc3e1 100644 --- a/doc/examples/java-log4j2-basic/log4j2.xml +++ b/doc/examples/java-log4j2-basic/log4j2.xml @@ -4,7 +4,7 @@ - + diff --git a/doc/examples/java-log4j2-ctx/log4j2.ctx1.xml b/doc/examples/java-log4j2-ctx/log4j2.ctx1.xml index d59ce770..52ad5a7c 100644 --- a/doc/examples/java-log4j2-ctx/log4j2.ctx1.xml +++ b/doc/examples/java-log4j2-ctx/log4j2.ctx1.xml @@ -4,7 +4,7 @@ - + diff --git a/doc/examples/java-log4j2-ctx/log4j2.ctx2.xml b/doc/examples/java-log4j2-ctx/log4j2.ctx2.xml index c62af2e5..011152dc 100644 --- a/doc/examples/java-log4j2-ctx/log4j2.ctx2.xml +++ b/doc/examples/java-log4j2-ctx/log4j2.ctx2.xml @@ -4,7 +4,7 @@ - + diff --git a/doc/examples/java-log4j2-prog/HelloLog4j2Prog.java b/doc/examples/java-log4j2-prog/HelloLog4j2Prog.java index 685eebfa..2632ab1d 100644 --- a/doc/examples/java-log4j2-prog/HelloLog4j2Prog.java +++ b/doc/examples/java-log4j2-prog/HelloLog4j2Prog.java @@ -50,18 +50,19 @@ public class HelloLog4j2Prog { standardLayout.addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"); /* Create a console appender */ - AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE"); + AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "Console"); appenderBuilder.add(standardLayout); builder.add(appenderBuilder); /* Create an Lttng appender */ - appenderBuilder = builder.newAppender("Lttng", "LTTNG"); + appenderBuilder = builder.newAppender("Lttng1", "Lttng"); + appenderBuilder.addAttribute("domain", "LOG4J"); builder.add(appenderBuilder); /* Create a root logger with both appenders attached */ RootLoggerComponentBuilder rootLogger = builder.newRootLogger(Level.DEBUG); rootLogger.add(builder.newAppenderRef("Stdout")); - rootLogger.add(builder.newAppenderRef("Lttng")); + rootLogger.add(builder.newAppenderRef("Lttng1")); builder.add(rootLogger); Configurator.initialize(builder.build()); diff --git a/liblttng-ust-java-agent/java/lttng-ust-agent-log4j2/org/lttng/ust/agent/log4j2/LttngLogAppender.java b/liblttng-ust-java-agent/java/lttng-ust-agent-log4j2/org/lttng/ust/agent/log4j2/LttngLogAppender.java index 08612f57..3b7afa5b 100644 --- a/liblttng-ust-java-agent/java/lttng-ust-agent-log4j2/org/lttng/ust/agent/log4j2/LttngLogAppender.java +++ b/liblttng-ust-java-agent/java/lttng-ust-agent-log4j2/org/lttng/ust/agent/log4j2/LttngLogAppender.java @@ -26,6 +26,7 @@ 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.message.Message; +import org.lttng.ust.agent.ILttngAgent.Domain; import org.lttng.ust.agent.ILttngHandler; import org.lttng.ust.agent.context.ContextInfoSerializer; @@ -61,20 +62,24 @@ public final class LttngLogAppender extends AbstractAppender implements ILttngHa * Constructor * * @param name The name of the Appender. + * @param domain The LTTng-UST agent domain 'LOG4J' / 'LOG4J2'. * @param filter The Filter or null. - * @param ignoreExceptions If {@code "true"} (default) exceptions encountered - * when appending events are logged; otherwise they are + * @param ignoreExceptions If {@code "true"} exceptions encountered when + * appending events are logged; otherwise they are * propagated to the caller. * - * @throws IOException This handler requires the lttng-ust-log4j-jni.so - * native library, through which it will send the - * trace events. This exception is thrown if this - * library cannot be found. - * @throws SecurityException We will forward any SecurityExcepion that may be - * thrown when trying to load the JNI library. + * @throws IOException This handler requires the + * lttng-ust-log4j-jni.so native library, + * through which it will send the trace events. + * This exception is thrown if this library + * cannot be found. + * @throws IllegalArgumentException If the provided domain is unsupported. + * @throws SecurityException We will forward any SecurityExcepion that + * may be thrown when trying to load the JNI + * library. */ - protected LttngLogAppender(String name, Filter filter, boolean ignoreExceptions) - throws IOException, SecurityException { + protected LttngLogAppender(String name, LttngLog4j2Agent.Domain domain, Filter filter, boolean ignoreExceptions) + throws IOException, IllegalArgumentException, SecurityException { super(name, filter, null, ignoreExceptions, Property.EMPTY_ARRAY); @@ -86,7 +91,12 @@ public final class LttngLogAppender extends AbstractAppender implements ILttngHa } /* Register to the relevant agent. */ - agent = LttngLog4j2Agent.getInstance(); + if (domain == LttngLog4j2Agent.Domain.LOG4J) { + agent = LttngLog4j2Agent.getInstance(); + } else { + throw new IllegalArgumentException("Unsupported domain '" + domain + "'"); + } + agent.registerHandler(this); } @@ -94,35 +104,59 @@ public final class LttngLogAppender extends AbstractAppender implements ILttngHa * Create an LttngLogAppender. * * @param name The name of the Appender, null returns null. + * @param domain The LTTng-UST agent domain 'LOG4J' / 'LOG4J2'. * @param ignoreExceptions If {@code "true"} (default) exceptions encountered * when appending events are logged; otherwise they are * propagated to the caller. * @param filter The Filter or null. * - * @return A new LttngLogAppender, null if the name was null. - * - * @throws IOException This handler requires the lttng-ust-log4j-jni.so - * native library, through which it will send the - * trace events. This exception is thrown if this - * library cannot be found. - * @throws SecurityException We will forward any SecurityExcepion that may be - * thrown when trying to load the JNI library. + * @return A new LttngLogAppender, null if the name was null or the domain is + * null or invalid. */ @PluginFactory public static LttngLogAppender createAppender(@PluginAttribute("name") String name, - @PluginAttribute("ignoreExceptions") Boolean ignoreExceptions, @PluginElement("Filters") Filter filter) - throws IOException, SecurityException { + @PluginAttribute("domain") String domain, @PluginAttribute("ignoreExceptions") Boolean ignoreExceptions, + @PluginElement("Filters") Filter filter) { if (name == null) { LOGGER.error("No name provided for LttngLogAppender"); return null; } + if (domain == null) { + LOGGER.error("No domain provided for LttngLogAppender"); + return null; + } + if (ignoreExceptions == null) { ignoreExceptions = true; } - return new LttngLogAppender(name, filter, ignoreExceptions); + /* Parse the domain string */ + LttngLog4j2Agent.Domain parsedDomain; + try { + parsedDomain = LttngLog4j2Agent.Domain.valueOf(domain.toUpperCase()); + } catch (IllegalArgumentException e) { + LOGGER.error("Invalid domain '{}' for LttngLogAppender", domain); + return null; + } + + /* Create the appender and handle the possible failures. */ + LttngLogAppender newAppender; + try { + newAppender = new LttngLogAppender(name, parsedDomain, filter, ignoreExceptions); + } catch (IllegalArgumentException e) { + LOGGER.error("Invalid domain '{}' for LttngLogAppender", parsedDomain); + newAppender = null; + } catch (SecurityException e) { + LOGGER.error("Security error trying to load '{}' JNI library for LttngLogAppender", SHARED_OBJECT_NAME); + newAppender = null; + } catch (IOException e) { + LOGGER.error("Failed to load '{}' JNI library for LttngLogAppender", SHARED_OBJECT_NAME); + newAppender = null; + } + + return newAppender; } @Override -- 2.34.1