Logging & Observability
SLF4J and Logback, log levels, structured logging, and basic metrics.
Deutsche Übersetzung in Arbeit
Diese Lektion ist noch nicht ins Deutsche übersetzt und wird daher auf Englisch angezeigt. Der Rest der Seite ist vollständig lokalisiert.
Auf dieser Seite
When an app runs in production, you can't attach a debugger - you need it to tell you what it's doing. Logging and observability are how you understand a live system: what happened, when, and why. Skimp on this and production problems become guessing games.
Logging: leave a trail
A log is a timestamped record of events. Good logs are your eyes into a running system.
An aircraft's black box continuously records what's happening so investigators can reconstruct events after the fact. Logs are your application's black box: when something goes wrong at 3 a.m., they're often the only record of what led up to it. Log thoughtfully, and future-you can piece the story together.
Use SLF4J + Logback, not println
System.out.println has no timestamps, levels, or control. Real apps use a
logging framework: SLF4J (the standard API) with Logback (the
implementation).
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class OrderService {
private static final Logger log = LoggerFactory.getLogger(OrderService.class);
void process(Order order) {
log.info("Processing order {}", order.id()); // {} is a safe placeholder
try {
// ...
} catch (Exception e) {
log.error("Failed to process order {}", order.id(), e); // logs stack trace
}
}
}Use placeholders, not string concatenation
Write log.info("Order {}", id) rather than log.info("Order " + id). The
placeholder version skips building the string entirely if that log level is
disabled - cheaper and cleaner. And always pass the exception as the last argument
so the stack trace is logged.
Log levels
Levels let you control verbosity - chatty in development, quiet in production:
| Level | Use for |
|---|---|
ERROR | Something failed and needs attention |
WARN | Something odd, but the app continues |
INFO | Notable business events (order placed) |
DEBUG | Detailed diagnostic info for developers |
TRACE | Very fine-grained, rarely enabled |
You configure which levels to actually output per environment - no code changes needed.
Never log secrets
Passwords, tokens, credit-card numbers, and personal data must never appear in logs - logs are widely accessible and long-lived. Redact or omit sensitive fields. A leaked log file has caused many real breaches.
Structured logging
Instead of plain text, structured logs (often JSON) attach machine-readable fields, so tools can search and filter them:
{"time":"...","level":"INFO","orderId":42,"msg":"Order placed","userId":7}This makes logs searchable at scale - "show every ERROR for user 7 today" becomes a simple query.
The three pillars of observability
Logging is one of three complementary tools:
- Logs - discrete events ("order 42 failed").
- Metrics - numbers over time (requests/sec, error rate, memory use).
- Traces - the path of a single request across services (where did the time go?).
Metrics and health checks
Spring Boot Actuator exposes metrics and a /health endpoint out of the box.
Tools like Micrometer, Prometheus, and Grafana collect and visualize
metrics so you can watch trends and get alerted before users notice a problem.
Quick check
Which log level should you use for an event that failed and needs attention?
Key takeaways
- Logs are a timestamped record - your window into a running system.
- Use SLF4J + Logback with parameterized messages (log.info("{}", x)), not System.out.println.
- Log levels (ERROR, WARN, INFO, DEBUG, TRACE) control verbosity per environment.
- Never log secrets or personal data; redact sensitive fields.
- Structured (JSON) logs are searchable at scale.
- Observability has three pillars: logs (events), metrics (numbers over time), and traces (request paths).
Finally, let's get your app out the door: packaging and deployment.