Logs with Java
Use Logs for Lumigo with our Java Distribution.
Overview
How does the logging instrumentation work? (essentially we hook into the logging library code seamlessly, worth detailing)
Scope
Lumigo supports Logback
and Log4j
libraries when working through Java. Refer to this table to see which versions are supported.
Basics
Instrumentation setup
How to work with logging on the platform
Ensure that Lumigo's OpenTelemetry distribution for Java is properly instrumented in your application through a JVM. Follow the instructions in Instrumentation Setup to properly activate the distribution.
To view, search, and filter logs based on these attributes, navigate to Lumigo's page.
Logging within an active span context
Ensure your application is instrumented using the Lumigo OpenTelemetry distribution. When a log is emitted within an active span, Lumigo automatically correlates the log with the corresponding trace. Load the Lumigo OpenTelemetry Distribution for Java through a JVM (Java Virtual Machine) before your application is loaded. The two supported ways to achieve this are:
export JAVA_TOOL_OPTIONS="-javaagent:<path-to-lumigo-otel-javaagent>"
java -javaagent:<path-to-lumigo-otel-javaagent> -jar app.jar
To test logging through Java with an HTTP server, try the following:
package org.example;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) throws IOException {
// Create a new HttpServer instance listening on port 8000
HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
// Create a new context for handling HTTP requests at the root ("/")
server.createContext("/", new RootHandler());
// Start the server
server.setExecutor(null); // Creates a default executor
server.start();
System.out.println("Server is running on http://localhost:8000/");
}
// Custom HttpHandler to process requests to the root "/"
static class RootHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
// Prepare the response
String response = "Welcome to my simple Java web server!";
for (int i = 0; i < 1; i++) {
try (CloseableHttpClient client = HttpClients.createDefault()) {
final ClassicHttpRequest httpGet = ClassicRequestBuilder.get("https://api.chucknorris.io/jokes/random").build();
client.execute(httpGet, httpResponse -> {
final HttpEntity entity = httpResponse.getEntity();
if (entity != null) {
// Convert the response entity to a String and print it
String result = EntityUtils.toString(entity);
logger.info("Response from the API: {}", result);
}
return null;
});
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
// Set the response header (200 OK) and the length of the response body
exchange.sendResponseHeaders(200, response.getBytes().length);
// Get the response body output stream
OutputStream os = exchange.getResponseBody();
// Write the response and close the output stream
os.write(response.getBytes());
os.close();
}
}
}
Advanced
Troubleshooting cases where logs are not being sent
If logs are not appearing in the Lumigo platform, enable the LUMIGO_DEBUG_LOGDUMP
environment variable.
LUMIGO_DEBUG_LOGDUMP
: This functions similarly to LUMIGO_DEBUG_SPANDUMP, but for logs instead of spans. This option is only effective when LUMIGO_ENABLE_LOGS is set to true.
This outputs additional debug information to help diagnose why logs are not being sent. Check the application logs for messages prefixed with [Lumigo Log Dump]
to identify potential issues. You should also ensure the Lumigo instrumentation is correctly initialized and verify network connectivity to Lumigo's backend.
Troubleshooting cases where logs are not correlated to traces
Verify that logs are emitted within an active span, and use the Lumigo debug logs (LUMIGO_DEBUG_LOGDUMP
) to inspect log traces and diagnose correlation issues. You should also ensure the Lumigo distribution is up-to-date and correctly configured for your environment.
Cases not covered by the distribution
We do not cover every scenario with our distribution. Because Lumigo only supports log4j and logback logging libraries, you will need to provide the explicit setup and libraries they use, unlike something like java.util.logging (JUL) which does not require as much setup.
To define inheritance through log4j or logback, you will need to input it manually, as opposed to the automatic inheritance of log levels and handlers based on logger naming hierarchy achievable in JUL.
You cannot use automatic inheritance like in JUL, as it is not supported:
Logger parent = Logger.getLogger("com.example");
Logger child = Logger.getLogger("com.example.module");
parent.setLevel(Level.WARNING);
System.out.println(child.getLevel()); // null → inherits from parent
Instead, you need to first modify the config file, such as logback.xml
in Logback's case:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%logger] %msg%n</pattern>
</encoder>
</appender>
<!-- Parent logger -->
<logger name="com.example" level="INFO" additivity="true">
<appender-ref ref="STDOUT"/>
</logger>
<!-- Child logger inherits from com.example -->
<logger name="com.example.module" additivity="true" />
<!-- Root logger -->
<root level="ERROR">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
For scenarios not covered by Lumigo's distribution, we have several alternate setups you can use:
- Vanilla OpenTelemetry setup: Implement standard OpenTelemetry instrumentation for advanced use cases.
- Kubernetes log collection: Use a centralized log collector (e.g., Fluent Bit, Fluentd) to aggregate and forward logs.
Refer to Lumigo documentation for detailed guidance on integrating with these alternative setups.
Updated 1 day ago