DEV Community

Leanid Herasimau
Leanid Herasimau

Posted on • Originally published at suddo.io on

Effective Logging in Quarkus Microservices using Lombok

Effective Logging in Quarkus Microservices using Lombok

Effective logging in Java microservices using Quarkus and Lombok. By the end of this article, you'll be armed with the knowledge to turn your logs from a chaotic mess into a finely-tuned instrument of debugging precision. Let's get started!

1. Why Logging is Crucial in Microservices

You've just deployed your shiny new microservices architecture. Everything seems fine until suddenly, your app starts throwing tantrums. Without proper logging, you're essentially flying blind. Here's why logging is your secret weapon:

  • Visibility: Logs are your eyes and ears in a distributed system
  • Troubleshooting: Quickly identify and diagnose issues
  • Performance Monitoring: Spot bottlenecks before they become showstoppers
  • Security: Detect and investigate suspicious activities

But microservices logging comes with its own set of challenges:

  • Distributed Nature: Tracing requests across multiple services
  • Data Volume: Managing the sheer amount of log data
  • Correlation: Connecting related events across different services

2. Lombok: Your Logging Sidekick

Enter Lombok, the unsung hero of Java development. With its magical annotations, Lombok can turn your logging boilerplate into a one-liner. Let's see how:

import lombok.extern.java.Log;

@Log
public class UserService {
    public void createUser(String username) {
        log.info("Creating user: {}", username);
        // User creation logic here
        log.debug("User created successfully");
    }
}

Enter fullscreen mode Exit fullscreen mode

No more static logger declarations! Lombok's @Log annotation automatically creates a log field for you. But wait, there's more! Lombok offers a buffet of logging annotations:

  • @Slf4j: Uses slf4j
  • @Log4j2: For Log4j 2.x
  • @CommonsLog: Apache Commons Logging

Choose the one that matches your logging framework of choice. It's like picking your favorite flavor of ice cream, but for logging.

3. Quarkus: Supersonic Logging Configuration

Quarkus, the supersonic subatomic Java framework, makes configuring logs as easy as ordering a pizza (maybe even easier, depending on your local pizzeria).

Let's start with a basic configuration in your application.properties:

quarkus.log.level=INFO
quarkus.log.category."com.mycompany.myapp".level=DEBUG

Enter fullscreen mode Exit fullscreen mode

But why stop there? Let's add some JSON logging for that extra oomph:

quarkus.log.console.json=true

Enter fullscreen mode Exit fullscreen mode

Now your logs are not just informative, they're also stylish and machine-readable. It's like giving your logs a fancy suit.

4. Logging Pro Tips: Level Up Your Game

Ready to take your logging skills from "meh" to "wow"? Here are some pro tips that'll make your colleagues wonder if you've secretly been replaced by an AI:

Selective Debugging

Need to debug a specific class without flooding your logs? Quarkus has got you covered:

quarkus.log.category."com.mycompany.myapp.CriticalService".level=DEBUG

Enter fullscreen mode Exit fullscreen mode

Tame Noisy Libraries

Is Hibernate being too chatty? Put it on mute:

quarkus.log.category."org.hibernate".level=WARN

Enter fullscreen mode Exit fullscreen mode

Context is King

Use Mapped Diagnostic Context (MDC) to add extra context to your logs:

import org.slf4j.MDC;

public void processOrder(String orderId) {
    MDC.put("orderId", orderId);
    try {
        log.info("Processing order");
        // Order processing logic
    } finally {
        MDC.clear();
    }
}

Enter fullscreen mode Exit fullscreen mode

Different Strokes for Different Folks

Use different log formats for development and production:

%dev.quarkus.log.console.format=%d{HH:mm:ss} %-5p [%c{2.}] (%t) %s%e%n
%prod.quarkus.log.console.json=true

Enter fullscreen mode Exit fullscreen mode

Tag, You're It!

Use tags to categorize your logs:

log.info("[SECURITY] User {} logged in", username);

Enter fullscreen mode Exit fullscreen mode

5. Elastic Stack: Your Logging Command Center

Now that we're generating awesome logs, let's centralize them with the Elastic Stack. It's like building a mission control for your microservices.

First, set up Filebeat to ship your logs:

filebeat.inputs:
- type: log
  paths:
    - /path/to/your/quarkus/logs/*.log
output.elasticsearch:
  hosts: ["localhost:9200"]

Enter fullscreen mode Exit fullscreen mode

With Elasticsearch storing your logs and Kibana visualizing them, you'll feel like a data scientist (without the math anxiety).

Pro tip: JSON logging in Quarkus plays nicely with Elasticsearch, making your logs easily searchable and visualizable.

6. Connecting the Dots: Tracing in Microservices

In a microservices world, a single request can bounce around more than a hyperactive kid in a bouncy castle. Let's see how to keep track of these globe-trotting requests:

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;

@Inject
Tracer tracer;

public void handleRequest() {
    Span span = tracer.spanBuilder("handleRequest").startSpan();
    try (io.opentelemetry.context.Scope scope = span.makeCurrent()) {
        MDC.put("traceId", span.getSpanContext().getTraceId());
        log.info("Handling request");
        // Request handling logic
    } finally {
        span.end();
        MDC.clear();
    }
}

Enter fullscreen mode Exit fullscreen mode

Integrate this with Jaeger, and you'll have a beautiful visualization of your request's journey. It's like Google Maps for your microservices!

7. Microservices Logging Best Practices

Here are some golden rules to live by:

  • Log smart, not hard: Only log what's necessary
  • Keep it clean: No passwords or sensitive data in logs
  • Be specific: Use formatted messages for clarity
  • Rotate logs: Don't let your logs eat up all your disk space

Remember, good logging is like good writing - clear, concise, and informative.

8. When Things Go South: Error Logging

Errors happen. When they do, make sure you're capturing all the juicy details:

try {
    riskyOperation();
} catch (Exception e) {
    log.error("Failed to perform risky operation", e);
}

Enter fullscreen mode Exit fullscreen mode

For Quarkus, set up a global exception handler to catch those sneaky uncaught exceptions:

@Provider
public class GlobalExceptionHandler implements ExceptionMapper {
    @Inject
    Logger log;

    @Override
    public Response toResponse(Throwable exception) {
        log.error("Unhandled exception", exception);
        return Response.status(500).entity("Oops, something went wrong").build();
    }
}

Enter fullscreen mode Exit fullscreen mode

9. Monitoring: Bringing Your Logs to Life

With Elastic Stack set up, create dashboards in Kibana to visualize your application's health. Set up alerts for important events, like a sudden spike in error logs. It's like having a 24/7 on-call developer, minus the 3 AM wake-up calls.

10. Wrapping Up: Your Roadmap to Logging Nirvana

Let's recap our journey to microservices logging excellence:

  • Use Lombok to simplify logger creation
  • Configure Quarkus for flexible logging
  • Implement context-rich logging with MDC
  • Centralize logs with Elastic Stack
  • Trace requests across services
  • Follow best practices for clean, informative logs
  • Handle errors gracefully
  • Monitor and visualize your logs

Remember, great logging is an art. It takes practice, but with these tools and techniques, you're well on your way to becoming a logging Picasso.

"The art of debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." - Brian W. Kernighan

So, log smart, debug easier, and may your microservices live long and prosper! 🖖

Top comments (0)