Why Ignoring Non‑Critical Alerts Is Safe When Core Services Are Monitored

The author explains that when core business modules are properly monitored with structured logs and dedicated alert groups, a flood of non‑critical alerts can be ignored, shares a lightweight Java StructuredLog utility, and outlines best practices for real‑time monitoring and log standardization.

samdeepthink
samdeepthink
samdeepthink
Why Ignoring Non‑Critical Alerts Is Safe When Core Services Are Monitored

On the morning of July 28, 2026 the author received many alert messages in a DingTalk group but remained calm because none of the core business modules reported alerts, illustrating that reliable monitoring of core services lets teams ignore unrelated noise.

The author stresses that every core module must have its own monitoring setup; any issue in a core module must be detected immediately. He enforces a rule that each core module has a dedicated DingTalk alert group, for example an "order" alert group and an "inventory" alert group.

To support this practice he standardizes log output with a concise Java utility class StructuredLog. The class builds JSON‑formatted log entries, provides fluent methods for common fields (userId, shopId, etc.), and supports four log levels (INFO, WARN, ERROR, DEBUG). The full source code is shown below.

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Structured log utility class
 *
 * Usage example:
 * // method 1: pass logger (recommended, correct class name)
 * StructuredLog.info(log)
 *     .userId("123")
 *     .shopId(456)
 *     .log();
 *
 * // method 2: no logger (convenient, class name is StructuredLog)
 * StructuredLog.info()
 *     .userId("123")
 *     .shopId(456)
 *     .log();
 *
 * @author linsongbin
 */
@Slf4j
public class StructuredLog {
    private final Map<String, Object> fields = new LinkedHashMap<>();
    private final LogLevel level;
    private final Logger logger;
    private String message;
    private Throwable throwable;

    private enum LogLevel { INFO, WARN, ERROR, DEBUG }

    private StructuredLog(LogLevel level, Logger logger) {
        this.level = level;
        this.logger = logger;
    }

    public static StructuredLog info(Logger logger) { return new StructuredLog(LogLevel.INFO, logger); }
    public static StructuredLog info() { return new StructuredLog(LogLevel.INFO, log); }
    public static StructuredLog warn(Logger logger) { return new StructuredLog(LogLevel.WARN, logger); }
    public static StructuredLog warn() { return new StructuredLog(LogLevel.WARN, log); }
    public static StructuredLog error(Logger logger) { return new StructuredLog(LogLevel.ERROR, logger); }
    public static StructuredLog error() { return new StructuredLog(LogLevel.ERROR, log); }
    public static StructuredLog debug(Logger logger) { return new StructuredLog(LogLevel.DEBUG, logger); }
    public static StructuredLog debug() { return new StructuredLog(LogLevel.DEBUG, log); }

    public StructuredLog message(String message) { this.message = message; return this; }
    public StructuredLog exception(Throwable throwable) { this.throwable = throwable; return this; }
    public StructuredLog put(String key, Object value) { if (key != null && value != null) { fields.put(key, value); } return this; }

    // ======== business field shortcuts ========
    public StructuredLog userId(String userId) { return put("userId", userId); }
    public StructuredLog userName(String userName) { return put("userName", userName); }
    public StructuredLog shopId(Integer shopId) { return put("shopId", shopId); }
    public StructuredLog shopName(String shopName) { return put("shopName", shopName); }
    public StructuredLog docsId(Long docsId) { return put("docsId", docsId); }
    public StructuredLog docsNo(String docsNo) { return put("docsNo", docsNo); }
    public StructuredLog moduleCode(String moduleCode) { return put("moduleCode", moduleCode); }
    public StructuredLog moduleName(String moduleName) { return put("moduleName", moduleName); }
    public StructuredLog eventCode(String eventCode) { return put("eventCode", eventCode); }
    public StructuredLog eventName(String eventName) { return put("eventName", eventName); }
    public StructuredLog scenario(String scenario) { return put("scenario", scenario); }
    public StructuredLog status(String status) { return put("status", status); }
    public StructuredLog count(Integer count) { return put("count", count); }
    public StructuredLog costTime(Long costTime) { return put("costTime", costTime); }

    public void log() {
        String logContent = buildLogContent();
        switch (level) {
            case INFO:
                if (throwable != null) { logger.info(logContent, throwable); } else { logger.info(logContent); }
                break;
            case WARN:
                if (throwable != null) { logger.warn(logContent, throwable); } else { logger.warn(logContent); }
                break;
            case ERROR:
                if (throwable != null) { logger.error(logContent, throwable); } else { logger.error(logContent); }
                break;
            case DEBUG:
                if (throwable != null) { logger.debug(logContent, throwable); } else { logger.debug(logContent); }
                break;
        }
    }

    private String buildLogContent() {
        StringBuilder sb = new StringBuilder();
        if (message != null && !message.isEmpty()) { sb.append(message).append(" || "); }
        sb.append(JSON.toJSONString(fields));
        return sb.toString();
    }
}

Using the utility is straightforward; the author shows a chaining example that sets a message, exception, scenario, module code, module name, event details, shop name, document number, an additional custom field, and finally calls log() to emit the structured entry.

StructuredLog.error(log)
    .message("门店过时未下单")
    .exception(e)
    .scenario("系统自动下单")
    .moduleCode("order")
    .moduleName("订货单")
    .eventCode("autoCreateOrder")
    .eventName("系统自动下单")
    .shopName("xxx门店")
    .docsNo(docsNo)
    .put("shopId", 1)
    .log();

When an error log contains a module code, the corresponding DingTalk group receives an alert, enabling rapid response to critical issues while non‑core alerts can be reviewed later.

The author concludes with three practical recommendations: (1) technical leaders must ensure real‑time monitoring of core modules to minimize loss; (2) logs must be structured to avoid ad‑hoc entries; (3) avoid a single large monitoring group and instead create one alert group per core module. Programmers protect themselves by starting with real‑time monitoring.

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.

javamonitoringbackend developmentstructured loggingDingTalklog standardizationalert groups
samdeepthink
Written by

samdeepthink

Knowledge Planet: Old Dock's Tech Chronicles Zhihu: SamDeepThinking A technical manager who still codes heavily on the front line. From junior developer to tech lead, then tech manager, now leading the whole front‑ and back‑end development team—leveling up along the way. I have some insights on programming, career development, and tech management.

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.