The Logs You Write Are Slowing Down Your System: How Engineers from Junior to Expert Handle Logging
Lao A's Code Teahouse Vol.1 — Logging: The “Small” Thing Most Programmers Get Wrong
Hello everyone, I’m Lao A.
---
A Holiday Wake-up Call
During the National Day holiday, I was lazily sprawled on a beach chair, sipping a cold beer, enjoying the breeze — pure bliss.
Suddenly, my phone lit up with alerts in the company monitoring group: "Disk space insufficient".
Out of curiosity, I checked. The culprit? Log files so huge they had completely filled the disk. A colleague explained: “We forgot to mount the ops platform’s auto-cleanup script for this log file.” He deleted some old logs, and usage returned to normal.
That incident reminded me: logging may feel trivial — every programmer does it — yet small oversights can cascade into major system issues. In fact, many developers (even in big tech) don’t treat logging seriously. This is a cognitive bias: ignoring small problems until they blow up.
Today, let’s dive into logging mistakes, so you can avoid turning your log files into time bombs.
---
Act One: Common Newbie Logging Pitfalls
Over the years, my colleagues and I have explored the full minefield of logging errors.
Especially fresh recruits — their logging is random and often disastrous.
---
Pitfall #1: Logging Into the Void
A colleague, fresh out of school — let’s call him Xiao Zhang — encountered a sporadic bug:
> "A-ge, in SLS I only found: `order process error!` — I have no idea which user, order, or code caused it! No alert triggered, no clues!"
Here’s the simplified pseudocode exposing the issue:
@Service
public class OrderService {
public void processOrder(OrderDTO order) {
try {
// edge case: order.getCustomer() may be null -> NPE
String customerName = order.getCustomer().getName();
log.info("OrderService start process order..."); // No key info
} catch (Exception e) {
log.error("OrderService#order process error!"); // Exception swallowed
}
}
}---
Mistake 1: Swallowing Exceptions
No stack trace, no cause recorded — critical evidence erased.
It’s like cleaning a crime scene before the detective arrives.
---
Mistake 2: Missing Business Identifiers
`OrderService#order process error!` — meaningless without context like orderId, userId, productId.
When thousands of orders flood in, this is a needle-in-a-haystack search.
---
Mistake 3: Missing Error Details
What went wrong? NPE, timeout, RPC failure? The log doesn’t say.
> Lesson: Without evidence, debugging cannot succeed.
---
Act Two: The Three Levels of Logging Maturity
Do Xiao Zhang’s mistakes look familiar?
Logging evolves through three maturity levels — each with strengths and hidden dangers.
---
Level 1: P4 Beginner — "I Was Here" Graffiti
Behaviors:
- Random `System.out.println()` everywhere
- Nonsense logs like `info("111")`
- String concatenation without guard clauses
Hidden Dangers:
- Performance hits: String concat runs even with logging turned off
- Evidence loss: Only logs `e.getMessage()`, never stack trace
- Not usable for analysis: No levels/config, can’t integrate with SLS/ELK
---
Level 2: P5 Intermediate — Business Diary
By P5, devs begin structured Services, but still mishandle exceptions:
@Service
public class OrderService {
public void createOrder(OrderDTO order) {
try {
String userName = null;
userName.toLowerCase(); // NPE
} catch (Exception e) {
throw new BizException("Order creation failed");
}
}
}@RestController
public class OrderController {
@PostMapping("/orders")
public void createOrder(@RequestBody OrderDTO order) {
try {
orderService.createOrder(order);
} catch (BizException e) {
log.error("Failed to process create order request!", e);
}
}
}Danger: Root cause thrown away — replaced by vague business message.
---
Level 3: P6/P7 Expert — Logs as SkyNet
Mindset: Logs aren’t just records — they are part of observability. Experts want a black box recorder for the system.
---
Principle 1: Structured Logging
Output JSON instead of plain text:
log.error("{"event":"order_failed", "order_id":"{}", "user_id":"{}", "error":"{}"}",
orderId, userId, e.getMessage());This enables precise queries like: “ERROR logs in last hour for payment processor where user_id=123”.
---
Principle 2: Context with MDC
Attach context (e.g., `trace_id`) to every log in a request flow:
MDC.put("trace_id", traceId);Interceptor example:
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
String traceId = UUID.randomUUID().toString();
MDC.put("trace_id", traceId);
return true;
}---
Principle 3: Avoid Log Bombs
Do not log massive objects or excessive frequency. Use sampling for high-volume info logs.
---
Expert Fix for Level 2 Mistake
try {
// core logic
} catch (Exception e) {
log.error("Order creation exception! orderId: {}", order.getId(), e);
throw new BizException("Order creation failed", e);
}---
Act Three: Building a Mature Logging System
A truly mature logging system should provide:
- Global Perspective — Correlate logs across microservices via `trace_id`
- Just-Right Data — Structured, essential fields; avoid redundancy
- Proactive Response — Trigger alerts or remediation scripts
---
Final Reflection:
An engineer’s logging ability mirrors their control over the system. From random prints to global observability, each stage unlocks new power — the difference between flailing in the dark and diagnosing issues in minutes.
---
---
Would you like me to prepare a quick-reference checklist of these logging best practices so you can adopt them immediately in your projects? That could make this guide even more actionable.