Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
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();
}
}