Customize Java dynamic logs for logger integration¶
Note
This feature is available for the Lightrun Java Agent.
This guide describes how to customize Lightrun logs to align with your application's logger format. Lightrun supports the integration of dynamic logs into your application's existing logs, maintaining the application’s log format and structure. If your application is configured to send logs to log management tools such as Kibana or New Relic, you can also include dynamic logs in real-time during runtime. These dynamic logs will be piped to those tools along with your application's static logs. For more information, see Dyanmic Logs Overview.
The Lightrun agent uses java.util.logging as its logging framework, and integration with the application's logger is achieved by adding a java.util.logging.Handler implementation to the agent. Certain logging frameworks offer built-in handler implementations, for example, SLF4J provides the SLF4JBridgeHandler, which serves as a bridge between the java.util.logging logger and the SLF4J APIs.
Before integrating Lightrun logs to your application logger, it is important to understand your application logger configuration, map its hierarchy, and determine the specific level of LoggerConfig within the hierarchy that you wish to be inherited by the Lightrun logger. Notably, Log4J2 implements a hierarchy mechanism between LoggerConfig objects.
The following diagram illustrates the integration between the Lightrun agent logger and the Application logger through JUL handlers.

Before you begin¶
- Prior knowledge of your application's logging configuration is essential for executing the described steps effectively. Familiarize yourself with relevant logging settings before proceeding.
- In your logger configuration file (typically named
<framework>.xmlor<framework>-spring.xmlin a Spring application), configure the Lightrun logger with the relevant appender(s) for your application by adding the appender(s) to Lightrun logger. Note that this step is unnecessary if the appenders you want are already configured on the root logger.<Loggers> <Logger name="com.lightrun" level="info"> <AppenderRef ref="AppAppender" /> </Logger> </Loggers>
- Keep in mind that later, when creating Lightrun logging actions, you will need to ensure that the Target for the Lightrun action(s) includes Stdout.

The following sections describe common use cases with examples on logging frameworks.
Configure Dynamic Logger with SLF4J¶
Note
If you are using the Spring Boot framework, refer to spring boot & SLF4J.
This section describes how to set up the dynamic logger with SLF4J, without Spring Boot, using one of the following options:
- Configure Dynamic Logger with SLF4J with code change
- Configure Dynamic Logger with SLF4J without changing your code
Configure Dynamic Logger with SLF4J with Code Change¶
- In your code, configure the
SLF4JBridgeHandleroforg.slf4j:jul-to-slf4jon the root logger at the beginning of the execution. For more details, see Class SLF4JBridgeHandler. - Configure the agent with
com.lightrun.DynamicLog.useParentHandlers=truewhich can be set in theagent.configfile, as a Java property, or as an environment variable.
Configure Dynamic Logger with SLF4J without changing your code¶
Note
This option is not supported for a JAR containing nested JARs (Uber JAR) because it is not possible to specify a classpath for nested JARs.
Prerequisites
slf4j-jul libraries must be available at runtime. Typically, the required packages are slf4j-jul-{version}.jar, slf4j-api-{version}.jar, slf4j-core-{version}.jar. In case of containerized applications, ensure that the packages are packaged inside the container.
-
Search for the
jul-to-slf4jlibrary.-
For Maven:
bash mvn dependency: tree -Dincludes=org.slf4j:jul-to-slf4j
-
For Gradle:
bash gradle dependencyInsight --dependency jul-to-slf4j (or ./gradlew)
-
-
Find and copy the JARs to where the Lightrun agent is located. In the
agent.configfile, add the following configuration:com.lightrun.DynamicLog.handlers=org.slf4j.bridge.SLF4JBridgeHandler com.lightrun.DynamicLog.SLF4JBridgeHandler.classpath=<PATH_TO_jul-to-slf4j.jar>
Configure Dynamic Logger with Log4J2¶
Note
If you are using the Spring Boot framework, refer to spring boot & SLF4J.
This procedure describes how to set up the dynamic logger with Log4j2 without Spring Boot using one of the following options:
- Configure Dynamic Logger with Log4J2 with code change
- Configure Dynamic Logger with Log4J2 without code change
Configure Dynamic Logger with Log4J2 with Code Change¶
- In your code, configure the
Log4JBridgeHandleravailable in theorg.apache.logging.log4j:log4j-julpackage on the root logger of your application as part of the application utilization:Log4JBridgeHandler.install(false, "", true); - Configure the agent with
com.lightrun.DynamicLog.useParentHandlers=true, which can be set in theagent.configfile, as a Java property or as an environment variable.
Configure Dynamic Logger with Log4J2 without Code Change¶
Note
This option is not supported for a JAR containing nested JARs (uber JAR) because it it not possible to specfiy a classpath insided a JAR.
Prerequisites
Log4j-jul libraries must be available at runtime. Typically, the required packages are log4j-jul-{version}.jar, log4j-api-{version}.jar, and log4j-core{version}.jar. In case of containerized applications, ensure that the packages are copied inside the container.
-
Search for the
log4j-jullibrary.-
For Maven:
mvn dependency:tree -Dincludes=org.apache.logging.log4j:log4j-jul
-
For Gradle:
gradle dependencyInsight --dependency log4j-jul (or ./gradlew).
-
-
Find and copy the JARs to the location where the Lightrun agent is located.
- Add the following to the
agent.configfile:com.lightrun.DynamicLog.handlers=org.apache.logging.log4j.jul.Log4jBridgeHandler com.lightrun.DynamicLog.Log4jBridgeHandler.classpath=<PATH_TO_log4j-jul.jar>
Configure Dynamic Logger with Log4J (1.x)¶
Log4J 1.x does not have a built-in bridge, unlike some logging frameworks, requiring the implementation of a custom handler.
-
Implement this simple handler:
import java.util.logging.Handler; import java.util.logging.LogRecord; import org.apache.log4j.Level; import org.apache.log4j.Logger; public class Log4J1BridgeHandler extends Handler { @Override public void publish(LogRecord record) { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); try { Logger log4j = getLog4jLogger(record.getLoggerName()); Level log4jLevel = getLog4jLevel(record.getLevel()); log4j.log(log4jLevel, record.getMessage(), record.getThrown()); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } @Override public void flush() { } @Override public void close() throws SecurityException { } private Logger getLog4jLogger(String name) { return Logger.getLogger(name); } private Level getLog4jLevel(java.util.logging.Level level) { if (java.util.logging.Level.SEVERE.equals(level)) { return Level.ERROR; } else if (java.util.logging.Level.WARNING.equals(level)) { return Level.WARN; } else if (java.util.logging.Level.INFO.equals(level)) { return Level.INFO; } else if (java.util.logging.Level.CONFIG.equals(level) || java.util.logging.Level.FINE.equals(level)) { return Level.DEBUG; } else if (java.util.logging.Level.FINER.equals(level) || java.util.logging.Level.FINEST.equals(level)) { return Level.TRACE; } else { return Level.ALL; } } } -
Compile the handler.
-
Add the handler and its classpath to the
agent.configfile:com.lightrun.DynamicLog.handlers = <FULLY_QUALIFIED_NAME>.Log4J1BridgeHandler com.lightrun.DynamicLog.Log4JBridgeHandler.classpath=<PATH_TO_FILE>/Log4J1BridgeHandler.class
Configure Dynamic Logger with Spring Boot & SLF4J¶
By definition, Spring adds the SLF4JBridgeHandler handler to the root logger, bridging java.util.logging logs to SLF4J. The Lightrun logger (com.lightrun) parents are com and the root logger. Therefore, setting the following property to true will cause the Lightrun logger to publish logs to its parent's handlers, including the SLF4JBridgeHandler handler of the root logger.
- Congfigure the agent with
com.lightrun.DynamicLog.useParentHandlers=true. which can be set in theagent.configfile, or alternatively as a Java property or as an environment variable.
Configure Dynamic Logger with a custom handler¶
You can implement a custom handler of your own and add it to the agent jul logger.
- Compile your handler.
- Add your handler and its classpath to the
agent.configfile:com.lightrun.DynamicLog.handlers = <FULLY_QUALIFIED_NAME>.YourCustomHandler com.lightrun.DynamicLog.YourCustomHandler.classpath=<PATH_TO_FILE>/YourCustomHandler.class