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

GCP Cloud Run中Spring Trace ID与Span ID日志配置问题咨询

问题解答

需求可行性确认

两个需求均可以实现:

  1. 能够将Trace ID和Span ID直接嵌入到日志消息内容中
  2. 可以恢复Spring Boot默认的控制台日志格式,同时保留Stackdriver的日志分组能力

当前自定义LoggingEnhancer的问题

你的实现存在几个关键问题:

  • 调用builder.build()后修改生成的LogEntry实例不会影响原builder状态(build()返回的是不可变新实例),后续builder.setPayload(jsonPayload)操作实际无效
  • 从logEntry.getTrace()获取的是带GCP项目前缀的完整路径,业务日志通常只需要纯Trace ID部分
  • 依赖logEntry.getSpanId()可能为空,因为父类TraceIdLoggingEnhancer可能还未将Trace/Span上下文设置到builder中
  • 重复实现两个enhanceLogEntry方法,实际仅需重写带ILoggingEvent的版本即可(LoggingAppender主要调用该重载方法)

正确实现方案

1. 修复自定义LoggingEnhancer

直接从当前Trace上下文获取ID,修改原始日志消息,无需通过builder构建后的实例操作:

@Component
public class NukTraceIdLoggingEnhancer extends TraceIdLoggingEnhancer {

    @Override
    public void enhanceLogEntry(LogEntry.Builder builder, ILoggingEvent loggingEvent) {
        super.enhanceLogEntry(builder, loggingEvent);
        
        // 从Trace上下文直接获取ID,比从builder读取更可靠
        TraceContext traceContext = TraceContextHolder.getCurrentTraceContext();
        if (traceContext != null) {
            String fullTraceId = traceContext.getTraceId();
            // 提取纯Trace ID(去掉GCP默认的projects/{project-id}/traces/前缀)
            String cleanTraceId = fullTraceId.substring(fullTraceId.lastIndexOf('/') + 1);
            String spanId = traceContext.getSpanId();
            
            // 修改原始日志消息,嵌入Trace和Span ID
            String enhancedMessage = String.format("[trace=%s, span=%s] %s", cleanTraceId, spanId, loggingEvent.getMessage());
            loggingEvent.setMessage(enhancedMessage);
        }
    }
}

2. 恢复Spring Boot默认控制台日志格式

调整logback配置,同时保留控制台输出和Stackdriver输出,确保控制台使用Spring默认格式:

<configuration>
    <!-- 引入Spring Boot默认日志配置 -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
    
    <!-- 自定义Stackdriver Appender配置 -->
    <property name="STACKDRIVER_LOG_NAME" value="${STACKDRIVER_LOG_NAME:-spring.log}"/>
    <property name="STACKDRIVER_LOG_FLUSH_LEVEL" value="${STACKDRIVER_LOG_FLUSH_LEVEL:-WARN}"/>

    <appender name="MY_STACKDRIVER" class="com.google.cloud.spring.logging.LoggingAppender">
        <log>${STACKDRIVER_LOG_NAME}</log>
        <loggingEventEnhancer>abc.configuration.NukTraceIdLoggingEnhancer</loggingEventEnhancer>
        <flushLevel>INFO</flushLevel>
        <!-- 配置结构化日志包含元数据字段 -->
        <includeTraceId>true</includeTraceId>
        <includeSpanId>true</includeSpanId>
        <includeLevel>true</includeLevel>
        <includeThreadName>true</includeThreadName>
        <includeLoggerName>true</includeLoggerName>
    </appender>

    <!-- 根日志输出:同时指向控制台和Stackdriver -->
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="MY_STACKDRIVER"/>
    </root>
</configuration>

关键说明

  • 保留<appender-ref ref="CONSOLE"/>即可恢复Spring Boot默认控制台日志格式,包含线程名、日志级别、应用名等信息
  • Stackdriver Appender通过includeXXX参数确保结构化日志中保留线程名、Span ID等元数据,同时通过自定义增强器将Trace/Span ID嵌入日志文本
  • 从TraceContextHolder获取ID更可靠,避免builder阶段数据未初始化的问题
  • 清理Trace ID前缀让日志内容更简洁易读

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:56:21