Why Most Developers Fail at Logging and How to Master It

This article reveals common logging pitfalls that cause silent failures, explains three levels of logging maturity from rookie to expert, and provides concrete Java code examples, structured‑logging techniques, MDC usage, and automated alerting to turn logs into a powerful observability tool.

dbaplus Community
dbaplus Community
dbaplus Community
Why Most Developers Fail at Logging and How to Master It

Introduction

During a holiday, the author noticed a disk‑space alert caused by oversized log files, prompting a reflection on how logging—an everyday task for developers—can easily become a hidden source of serious problems if mishandled.

Act 1: Rookie Logging Pitfalls

New engineers often log without purpose, leading to three typical issues:

Exception swallowed : The catch block discards the exception without stack trace, making debugging impossible.

No key information : Log messages like log.info("111") or log.info("Reached here") provide no context such as order ID or user.

Vague error messages : Messages like "OrderService #order process error!" lack details about which order or user triggered the error.

Example of a problematic snippet:

@Service
public class OrderService {
    public void processOrder(OrderDTO order) {
        try {
            // ...50 lines of business logic...
            // Potential NPE when order.getCustomer() returns null
            String customerName = order.getCustomer().getName();
            log.info("OrderService start process order..."); // no useful info
            // ...more logic...
        } catch (Exception e) {
            // Exception swallowed
            log.error("OrderService #order process error!");
        }
    }
}

Act 2: The Three Levels of Logging Maturity

Level 1 – P4 Rookie: "Graffiti" Logging

Uses System.out.println() or e.printStackTrace().

Logs arbitrary strings without structure.

Often concatenates strings (e.g., "value=" + var), causing performance loss.

Consequences: performance killers, lost information, and logs that cannot be aggregated.

Level 2 – P5 Intermediate: "Business Ledger" Logging

Code still misses key details and proper exception propagation:

@Service
public class OrderService {
    public void createOrder(OrderDTO order) {
        try {
            // ...business logic...
            String userName = null;
            userName.toLowerCase(); // NPE
        } catch (Exception e) {
            // No log, just rethrow vague BizException
            throw new BizException("Create order failed");
        }
    }
}

@RestController
public class OrderController {
    @Autowired
    private OrderService orderService;

    @PostMapping("/orders")
    public void createOrder(@RequestBody OrderDTO order) {
        try {
            orderService.createOrder(order);
        } catch (BizException e) {
            log.error("Failed to handle create order request!", e);
        }
    }
}

Issues: logs only state "order creation failed" without the root cause, and missing trace IDs make correlation across services impossible.

Level 3 – P6/P7 Expert: "Sky‑Net" Logging

Experts focus on observability and diagnosability:

Structured logging : output JSON with fields like event, order_id, user_id, error.

Context is king : Use MDC to attach trace_id to every log entry.

Log as a bomb : Avoid logging huge objects; sample high‑frequency logs.

Example of structured log:

log.error("{\"event\":\"order_creation_failed\",\"order_id\":\"{}\",\"user_id\":\"{}\",\"error\":\"{}\"}", orderId, userId, e.getMessage());

MDC interceptor example:

public class TraceInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String traceId = UUID.randomUUID().toString();
        MDC.put("trace_id", traceId);
        return true;
    }
}

With MDC, a later log automatically includes the trace ID:

log.error("Order failed, orderId: {}", orderId); // trace_id added implicitly

Act 3: The Ultimate Mature Logging System

A mature system provides three core capabilities:

Global visibility : Correlate requests across micro‑services using trace_id to build a complete call chain.

Right‑sized data presentation : Store logs in concise JSON (timestamp, trace_id, span_id, error_code) and apply retention policies (e.g., 7‑day or 1 GB size limits) to avoid disk‑space bombs.

Proactive automated response : Detect error‑rate spikes, trigger alerts (e.g., via DingTalk), and optionally launch auto‑remediation scripts such as isolating faulty nodes or rolling back configurations.

The evolution from passive record‑keeping to an active guardian reflects an engineer’s growth in system mastery.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Observabilityloggingstructured loggingbest-practicesmdcerror-handling
dbaplus Community
Written by

dbaplus Community

Enterprise-level professional community for Database, BigData, and AIOps. Daily original articles, weekly online tech talks, monthly offline salons, and quarterly XCOPS&DAMS conferences—delivered by industry experts.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.