You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为Log4j未捕获的STDERR输出异常添加时间戳

给未捕获异常的STDERR输出添加时间戳的实现方案

你的思路完全没问题!用自定义PrintStream来给未被Log4j捕获的System.err输出加时间戳,确实是解决这类问题的有效方案。不过你给出的代码片段有点不完整,我帮你补全并优化一下,确保能稳定实现需求:

完整代码实现

1. 自定义PrintStream类 (MyPrintStream.java)

这个类负责给所有System.err的输出前缀加上格式化的时间戳:

import java.io.PrintStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class MyPrintStream extends PrintStream {
    // 统一时间格式,你可以根据需求调整
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

    public MyPrintStream(PrintStream originalStream) {
        super(originalStream);
    }

    // 重写字符串类型的println方法
    @Override
    public void println(String content) {
        super.printf("[%s] %s%n", getCurrentTime(), content);
    }

    // 重写对象类型的println方法,覆盖异常栈追踪的输出场景
    @Override
    public void println(Object obj) {
        super.printf("[%s] %s%n", getCurrentTime(), obj);
    }

    // 重写基础print方法,确保所有输出都带上时间戳
    @Override
    public void print(String content) {
        super.printf("[%s] %s", getCurrentTime(), content);
    }

    @Override
    public void print(Object obj) {
        super.printf("[%s] %s", getCurrentTime(), obj);
    }

    // 封装时间获取逻辑,方便统一修改
    private String getCurrentTime() {
        return LocalDateTime.now().format(TIME_FORMATTER);
    }
}

2. 主类调用示例 (Main.java)

在应用启动时替换默认的System.err为自定义实现:

public class Main {
    public static void main(String[] args) {
        // 替换System.err,保留原输出目的地的同时添加时间戳
        System.setErr(new MyPrintStream(System.err));
        
        // 模拟未捕获的NullPointerException,测试时间戳输出
        Integer i = null;
        String str = i.toString();
    }
}

关键细节说明

  • 重写多个输出方法:未捕获异常的栈追踪会调用不同的print/println方法,只重写部分方法可能导致某些输出缺失时间戳,所以尽量覆盖常用的输出重载。
  • 时间格式化:用Java 8+的LocalDateTime和DateTimeFormatter是线程安全且更简洁的选择,避免了旧Date类的线程安全问题。
  • 保留原输出目的地:构造自定义PrintStream时传入原System.err,这样原本重定向到其他文件的STDERR输出不会被改变,只是内容前多了时间戳。

额外优化建议

如果希望把这些未捕获的异常也统一纳入Log4j的日志管理(而不是单独的文件),可以直接在自定义PrintStream中调用Log4j的日志接口,利用Log4j自带的时间戳和日志归档能力:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.PrintStream;

public class MyPrintStream extends PrintStream {
    private static final Logger ERROR_LOGGER = LogManager.getLogger("UncaughtExceptionLogger");

    public MyPrintStream(PrintStream originalStream) {
        super(originalStream);
    }

    @Override
    public void println(String content) {
        ERROR_LOGGER.error(content); // 写入Log4j的错误日志
        super.println(content); // 可选:保留原STDERR输出
    }

    @Override
    public void println(Object obj) {
        ERROR_LOGGER.error(obj.toString());
        super.println(obj);
    }
}

内容的提问来源于stack exchange,提问作者Skartt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:48:26