The Logs You Write Are Slowing Down Your System: How Engineers from Junior to Expert Handle Logging

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.

---

Read Original

Open in WeChat

---

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.

Read more