Standardizing Log Formats and Using traceId for Efficient Debugging in Backend Services

To improve debugging speed and reduce issue resolution time, the article recommends defining a unified LogObject structure with fields such as eventName, traceId, msg, costTime, request, and response, using JSON serialization, and discusses adding traceId, consolidating request/response logs, and implementation examples in Java.

Top Architect
Top Architect
Top Architect
Standardizing Log Formats and Using traceId for Efficient Debugging in Backend Services

In daily development, inadequate logging makes locating issues difficult and prolongs bug resolution, especially for high‑impact bugs where every second counts.

The article proposes a unified log format by defining a LogObject class with fields such as eventName, traceId, msg, costTime, userId, request, response, others, etc., and demonstrates how to serialize it to JSON.

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;

public class LogObject {
    @JsonProperty(index = 1)
    private String eventName;
    @JsonProperty(index = 2)
    private String traceId;
    @JsonProperty(index = 3)
    private String msg;
    @JsonProperty(index = 4)
    private long costTime;
    @JsonProperty(index = 6)
    private Integer userId;
    @JsonProperty(index = 7)
    private Object others;
    @JsonProperty(index = 8)
    private Object request;
    @JsonProperty(index = 9)
    private Object response;
    // getters and setters omitted for brevity
}

Using a fluent (chain) style makes setting fields concise:

long endTime = System.currentTimeMillis();
LogObject logObject = new LogObject();
logObject.setEventName(methodName)
    .setMsg(msg)
    .setTraceId(traceId)
    .setUserId(backendId)
    .setRequest(request)
    .setResponse(response)
    .setCostTime(endTime - beginTime);
LOGGER.info(JSON.toJSONString(logObject));

It is recommended to place request and response data in the same log entry to keep context together, illustrated with a sample JSON log.

{
    "eventName":"createOrder",
    "traceId":"createOrder_1574923602015",
    "msg":"success",
    "costTime":317,
    "request":{ ... },
    "response":{ ... }
}

Two implementation approaches are discussed: a straightforward try‑catch‑finally block that logs at the end of each method, and a more sophisticated AOP with ThreadLocal to capture traceId automatically.

Adding a traceId to each request enables correlation across multiple micro‑services (e.g., marketing, order, payment). Sample logs from each service show the same traceId, allowing a simple grep to retrieve the entire call chain.

long beginTime = System.currentTimeMillis();
String traceId = "createOrder_" + beginTime;

Finally, the article notes that while AOP introduces some overhead, the explicit try‑catch‑finally method may be preferable for high‑throughput services where performance is critical.

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.

BackendDebuggingtraceid
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

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.