All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dahua.eco.base.spring.http.log.TraceLogHelper Maven / Gradle / Ivy

package com.dahua.eco.base.spring.http.log;

import com.alibaba.fastjson.JSONObject;
import com.dahua.eco.base.spring.http.log.domain.LogContent;
import com.dahua.eco.base.spring.http.log.domain.SpanInfo;
import com.dahua.eco.base.spring.utils.UuidUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.text.MessageFormat;
import java.util.List;

public class TraceLogHelper {
    private static final ThreadLocal headLogHolder = new ThreadLocal();

    // 请求头 traceId 属性名称
    public static final String HEADER_NAME_TRACE_ID = "X-TraceID";

    // 请求头 spanId 属性名称
    public static final String HEADER_NAME_SPAN_ID = "X-SpanID";

    // 请求头 ErrorCode 属性名称
    public final static String HEADER_NAME_ERROR_CODE = "ErrorCode";

    // 请求头 X-Forwarded-For 属性名称
    public final static String HEADER_NAME_FORWARDED_FOR = "X-Forwarded-For";

    // 请求头 User-Client 属性名称
    public final static String HEADER_NAME_USER_CLIENT = "User-Client";

    // 请求头 User-Id 属性名称
    public final static String HEADER_NAME_USER_ID = "User-Id";

    // 初始化 sequence
    public static final String INIT_SEQUENCE_VALUE = "001";

    // 跟踪日志输出对象
    private static Logger traceLogger = LoggerFactory.getLogger("trace-logger");
    private static Logger infoLogger = LoggerFactory.getLogger(TraceLogHelper.class);


    /**
     * 记录追踪日志
     *
     * @param content 日志内容
     * @param args 占位符参数
     */
    public static void recordTraceLog(String content, Object... args) {
        traceLogger.info(content, args);
    }

    /**
     * 记录追踪日志
     * 

* 追加格式为:[TraceLogHelper:recordTraceLogInfo:69][http-nio-8090-exec-2][ERROR][TRACE=8554478608dd4da993e724eea6a16f5f:002][SEQ=001][SPAN=0][ErrorCode=99125021] {}" *追加格式为:[0903 18:56:58.153][源文件:行号] TID 线程号 [LEVEL][TRACE=12DG4DD454G5G43][P-SPAN=7SD8F7S8D7FS8DF8SD][SPAN=S98DF9S8DF98SD9F8S9DF8][ErrorCode=301] custom-log-content * @param logContent */ public static void recordTraceLog(LogContent logContent) { String contentTemplate = ""; if (LogContent.LOG_LEVEL_ERROR.equalsIgnoreCase(logContent.getLevel())) { // contentTemplate = "[{}:{}:{}][{}][{}][TRACE={}][SEQ={}][SPAN={}][ErrorCode={}] {}"; contentTemplate = "[{}:{}:{}][{}][{}][TRACE={}][P-SPAN={}][SPAN={}][ErrorCode={}] {}"; traceLogger.error( contentTemplate, logContent.getClassName(), logContent.getMethodName(), logContent.getLineNumber(), logContent.getThreadName(), logContent.getLevel(), logContent.getTraceInfo().getTraceId(), // logContent.getTraceInfo().getSequence(), logContent.getSpanInfo().getpSpanId(), logContent.getSpanInfo().getSpanId(), logContent.getErrorCode(), logContent.getDesc()); contentTemplate = "[{}:{}:{}][{}][{}][TRACE={}][P-SPAN={}][SPAN={}][ErrorCode={}]"; infoLogger.error( contentTemplate, logContent.getClassName(), logContent.getMethodName(), logContent.getLineNumber(), logContent.getThreadName(), logContent.getLevel(), logContent.getTraceInfo().getTraceId(), // logContent.getTraceInfo().getSequence(), logContent.getSpanInfo().getpSpanId(), logContent.getSpanInfo().getSpanId(), logContent.getErrorCode()); } else { // contentTemplate = "[{}:{}:{}][{}][{}][TRACE={}][SEQ={}][SPAN={}] {}"; contentTemplate = "[{}:{}:{}][{}][{}][TRACE={}][P-SPAN={}][SPAN={}] {}"; traceLogger.info( contentTemplate, logContent.getClassName(), logContent.getMethodName(), logContent.getLineNumber(), logContent.getThreadName(), logContent.getLevel(), logContent.getTraceInfo().getTraceId(), // logContent.getTraceInfo().getSequence(), logContent.getSpanInfo().getpSpanId(), logContent.getSpanInfo().getSpanId(), logContent.getDesc()); infoLogger.info( contentTemplate, logContent.getClassName(), logContent.getMethodName(), logContent.getLineNumber(), logContent.getThreadName(), logContent.getLevel(), logContent.getTraceInfo().getTraceId(), // logContent.getTraceInfo().getSequence(), logContent.getSpanInfo().getpSpanId(), logContent.getSpanInfo().getSpanId()); } } /** * 生成新的 trace-info * * @return */ public static TraceInfo generateNewTraceInfo() { TraceInfo traceInfo = new TraceInfo(); traceInfo.setTraceId(UuidUtil.generateUUID()); traceInfo.setSequence(TraceLogHelper.INIT_SEQUENCE_VALUE); traceInfo.setSequenceInt(Integer.parseInt(TraceLogHelper.INIT_SEQUENCE_VALUE)); return traceInfo; } /** * 生成新的span-info * * @return */ public static SpanInfo generateNewSpanInfo() { SpanInfo spanInfo = new SpanInfo(); spanInfo.setSpanId(UuidUtil.generateUUID()); return spanInfo; } /** * 生成下一步的 trace-info 对象,主要是将 seqence 加 1 递增 * * @param traceInfo * @return */ public static TraceInfo generateNextTraceTag(TraceInfo traceInfo) { if (traceInfo == null || StringUtils.isEmpty(traceInfo.getTraceId()) || StringUtils.isEmpty(traceInfo.getSequence()) ) { return null; } String newSequence = String.format("%03d", traceInfo.getSequenceInt() + 1); TraceInfo nextTraceInfo = new TraceInfo(traceInfo.getTraceId(), newSequence); return nextTraceInfo; } /** * 生成下一步的 span-info 对象,主要是将 原spanId 添加到pSpanId * * @param traceInfo * @return */ public static SpanInfo generateNextSpanTag(SpanInfo spanInfo,String newSpanId) { if (spanInfo == null ) { return null; } if(StringUtils.isEmpty(newSpanId)) { newSpanId = UuidUtil.generateUUID(); } String pSpanId = spanInfo.getSpanId(); SpanInfo nextTraceInfo = new SpanInfo(pSpanId, newSpanId); return nextTraceInfo; } /** * 生成下一步的traceId,主要是将 seqence 加 1 递增 * * @param traceId * @return */ public static String generateNextTraceTag(String traceId) { if (StringUtils.isEmpty(traceId)) { return ""; } String[] elements = traceId.split(":"); if (elements == null || elements.length < 2) { return ""; } String requestId = elements[0]; String sequence = elements[1]; int sequenceInt = Integer.parseInt(sequence); String newSequence = String.format("%03d", sequenceInt + 1); return MessageFormat.format("{0}:{1}", requestId, newSequence); } /** * 添加日志追踪信息到请求中 *

* 如果 header 中已经有 trace-info,则直接返回,如果没有,优先使用参数中传入的 requestTraceInfo,如为空,则创建新的 * * @param httpHeaders * @param requestTraceInfo * @return */ public static TraceInfo addTraceInfo2Header(HttpHeaders httpHeaders, TraceInfo requestTraceInfo) { // 请求头中没有 traceId,则创建新的 if (httpHeaders == null||null==httpHeaders.get(HEADER_NAME_TRACE_ID)) { httpHeaders = headLogHolder.get(); if(httpHeaders==null) { httpHeaders = new HttpHeaders(); } } List traceInfoList = httpHeaders.get(HEADER_NAME_TRACE_ID); if (CollectionUtils.isEmpty(traceInfoList) || StringUtils.isEmpty(traceInfoList.get(0))) { if (requestTraceInfo == null) { requestTraceInfo = generateNewTraceInfo(); } httpHeaders.add(HEADER_NAME_TRACE_ID, requestTraceInfo.getTraceString()); headLogHolder.set(httpHeaders); return requestTraceInfo; } else { String traceIdString = traceInfoList.get(0); headLogHolder.set(httpHeaders); return TraceLogParser.getTraceInfo(traceIdString); } } /** * @Title: addSpanInfo2Header * @Description: 添加日志追踪信息到请求中如果 header 中已经有 span-info,则直接返回,如果没有,优先使用参数中传入的 requestSpanInfo,如为空,则创建新的 * @param @param httpHeaders * @param @param requestSpanInfo * @param @return 设定文件 * @return SpanInfo 返回类型 * @throws */ public static SpanInfo addSpanInfo2Header(HttpHeaders httpHeaders, SpanInfo requestSpanInfo) { // 请求头中没有 spanId,则创建新的 if (httpHeaders == null||null==httpHeaders.get(HEADER_NAME_SPAN_ID)) { httpHeaders = headLogHolder.get(); if(httpHeaders==null) { httpHeaders = new HttpHeaders(); } } List spanInfoList = httpHeaders.get(HEADER_NAME_SPAN_ID); if (CollectionUtils.isEmpty(spanInfoList) || StringUtils.isEmpty(spanInfoList.get(0))) { if (requestSpanInfo == null) { requestSpanInfo = generateNewSpanInfo(); } httpHeaders.add(HEADER_NAME_SPAN_ID, JSONObject.toJSONString(requestSpanInfo)); headLogHolder.set(httpHeaders); return requestSpanInfo; } else {// 如果请求头中有老的spanId则生成新spanid将老的放入pSpanId中 String spanIdString = spanInfoList.get(0); SpanInfo spanInfo= TraceLogParser.getSpanInfo(spanIdString); // String newSpanId = UuidUtil.generateUUID(); // SpanInfo nextSpanInfo = TraceLogHelper.generateNextSpanTag(spanInfo, newSpanId); // if (nextSpanInfo == null) { // 生成失败,则不做spanId的更新 // nextSpanInfo = spanInfo; // } headLogHolder.set(httpHeaders); return spanInfo; } } /** * 从 header 中获取日志追踪信息 * * @param httpHeaders */ public static TraceInfo getTraceInfoFromHeader(HttpHeaders httpHeaders) { if (httpHeaders != null) { List values = httpHeaders.get(HEADER_NAME_ERROR_CODE); if (!CollectionUtils.isEmpty(values)) { return TraceLogParser.getTraceInfo(values.get(0)); } } return null; } /** * 添加错误编码到响应中 * * @param errorCode * @param response */ public static void addErrorCode2Response(String errorCode, HttpServletResponse response) { if (StringUtils.isEmpty(errorCode)) { return; } if (response != null) { response.setHeader(HEADER_NAME_ERROR_CODE, errorCode); } } /** * 从响应中获取错误编码 * * @param response */ public static String getErrorCodeFromResponse(HttpServletResponse response) { if (response != null) { return response.getHeader(HEADER_NAME_ERROR_CODE); } return ""; } /** * @Title: getLocalThreadLogHead * @Description: 获得线程内的请求头(内含请求头 traceId和 spanId信息如果空则没有被生成过) * @param @return 设定文件 * @return HttpHeaders 返回类型 * @throws */ public static HttpHeaders getLocalThreadLogHead() { return headLogHolder.get(); } /** * @Title: setLocalThreadLogHead * @Description: 设置线程内的请求头(内含请求头 traceId和 spanId信息如果空则没有被生成过) * @param @param httpHeaders 设定文件 * @return void 返回类型 * @throws */ public static void setLocalThreadLogHead(HttpHeaders httpHeaders) { headLogHolder.set(httpHeaders); } /** * @Title: removeLocalThreadLogHead * @Description: TODO方法描述:(这里用一句话描述这个方法的作用) * @param 设定文件 * @return void 返回类型 * @throws */ public static void removeLocalThreadLogHead() { headLogHolder.remove(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy