Java结构化错误日志核心是可解析、可检索、可关联,需通过LogstashEncoder输出JSON、MDC注入上下文、定义错误实体、AOP/全局异常处理器兜底实现。

Java 中记录结构化错误日志,核心是让日志内容可解析、可检索、可关联,而不是只输出一串难以提取信息的字符串。这在微服务或AI Agent等复杂场景中尤为关键——比如模型调用失败时,你不仅要知道“报错了”,还要快速定位是超时、认证失败、还是JSON解析异常,同时能和请求ID、用户ID、traceId对上。
用 SLF4J + Logback 输出 JSON 格式日志
结构化的第一步是格式统一。Logback 默认输出文本,但通过 logstash-logback-encoder 可以直接输出标准 JSON:
- 在
pom.xml中引入依赖:<dependency><br> <groupId>net.logstash.logback</groupId><br> <artifactId>logstash-logback-encoder</artifactId><br></dependency>
- 在
logback-spring.xml中配置 JSON encoder:<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><br> <encoder class="net.logstash.logback.encoder.LogstashEncoder"/><br> <file>logs/error.json</file><br></appender>
- 这样每次
logger.error("调用模型失败", e)就会生成包含@timestamp、level、message、stack_trace、thread_name等字段的 JSON 行,便于 Logstash 或 Filebeat 后续采集。
在异常处理中主动注入上下文字段
单纯靠 encoder 不够,很多关键业务上下文(如 request ID、user ID、model name、prompt id)不会自动出现。你需要在 catch 块里显式传入:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 使用
MDC(Mapped Diagnostic Context)绑定线程级变量:MDC.put("request_id", requestId);<br>MDC.put("user_id", userId);<br>MDC.put("model", "qwen2.5");<br>logger.error("LLM 调用失败", e); - 确保 MDC 在整个请求链路中透传(比如 Spring MVC 的拦截器、WebFilter 中初始化并清理);
- Logback 配置中启用 MDC 字段:
<encoder class="net.logstash.logback.encoder.LogstashEncoder"><br> <includeContext>true</includeContext><br></encoder>
为不同异常类型定义结构化错误码与语义字段
避免所有异常都记成一个模糊的 “Exception occurred”。建议按场景建模错误实体,再序列化进日志:
立即学习“Java免费学习笔记(深入)”;
- 定义标准化错误对象,例如:
public record LlmError(String code, String model, int statusCode,<br> String promptTruncated, boolean isRateLimited) {} - 在 catch 中构造并记录:
var error = new LlmError("MODEL_TIMEOUT", "deepseek-v3", 0, false, false);<br>logger.error("{}", error, e); - LogstashEncoder 会自动把 record 字段扁平展开为 JSON 层级,最终日志里就有
code、model、status_code等独立字段,支持 Kibana 精确筛选或告警规则匹配。
结合 AOP 或统一异常处理器做兜底增强
不是所有异常都出现在 try-catch 里。Spring 的 @ControllerAdvice 是集中补充结构化信息的好位置:
- 捕获全局异常后,从当前请求提取 traceId、method、path、body 摘要;
- 把原始异常堆栈、HTTP 状态码、业务错误码、甚至模型返回的截断响应片段,一并塞进 MDC 或作为结构化参数输出;
- 特别适合处理 RAG 流程中“向量库查询成功但 LLM 返回空”这类复合异常,能一次记录多个环节的状态。

















