提交 c89296c0 编写于 作者: zlt2000's avatar zlt2000

优化日志全链路追踪增加spanId和parentId

上级 9ce4f653
package com.central.log.config;
package com.central.log;
import com.central.log.properties.AuditLogProperties;
import com.central.log.properties.LogDbProperties;
......@@ -6,6 +6,7 @@ import com.central.log.properties.TraceProperties;
import com.zaxxer.hikari.HikariConfig;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
......@@ -14,6 +15,7 @@ import org.springframework.context.annotation.Configuration;
* @author zlt
* @date 2019/8/13
*/
@ComponentScan
@EnableConfigurationProperties({TraceProperties.class, AuditLogProperties.class})
public class LogAutoConfigure {
/**
......
......@@ -16,6 +16,7 @@ import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
......@@ -33,6 +34,7 @@ import java.time.LocalDateTime;
*/
@Slf4j
@Aspect
@Component
@ConditionalOnClass({HttpServletRequest.class, RequestContextHolder.class})
public class AuditLogAspect {
@Value("${spring.application.name}")
......
......@@ -12,6 +12,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
......@@ -26,6 +27,7 @@ import javax.sql.DataSource;
* Github: https://github.com/zlt2000
*/
@Slf4j
@Service
@ConditionalOnProperty(name = "zlt.audit-log.log-type", havingValue = "db")
@ConditionalOnClass(JdbcTemplate.class)
public class DbAuditServiceImpl implements IAuditService {
......
......@@ -4,6 +4,7 @@ import com.central.log.model.Audit;
import com.central.log.service.IAuditService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import java.time.format.DateTimeFormatter;
......@@ -17,6 +18,7 @@ import java.time.format.DateTimeFormatter;
* Github: https://github.com/zlt2000
*/
@Slf4j
@Service
@ConditionalOnProperty(name = "zlt.audit-log.log-type", havingValue = "logger", matchIfMissing = true)
public class LoggerAuditServiceImpl implements IAuditService {
private static final String MSG_PATTERN = "{}|{}|{}|{}|{}|{}|{}|{}";
......
package com.central.log.trace;
import cn.hutool.core.util.StrUtil;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.springframework.util.StringUtils;
/**
* dubbo过滤器,传递traceId
......@@ -25,22 +25,25 @@ public class DubboTraceFilter implements Filter {
boolean isProviderSide = RpcContext.getContext().isProviderSide();
if (isProviderSide) { //服务提供者逻辑
String traceId = invocation.getAttachment(MDCTraceUtils.KEY_TRACE_ID);
if (StringUtils.isEmpty(traceId)) {
MDCTraceUtils.addTraceId();
String spanId = invocation.getAttachment(MDCTraceUtils.KEY_SPAN_ID);
if (StrUtil.isEmpty(traceId)) {
MDCTraceUtils.addTrace();
} else {
MDCTraceUtils.putTraceId(traceId);
MDCTraceUtils.putTrace(traceId, spanId);
}
} else { //服务消费者逻辑
String traceId = MDCTraceUtils.getTraceId();
if (!StringUtils.isEmpty(traceId)) {
if (StrUtil.isNotEmpty(traceId)) {
String spanId = MDCTraceUtils.getSpanId();
invocation.setAttachment(MDCTraceUtils.KEY_TRACE_ID, traceId);
invocation.setAttachment(MDCTraceUtils.KEY_SPAN_ID, spanId);
}
}
try {
return invoker.invoke(invocation);
} finally {
if (isProviderSide) {
MDCTraceUtils.removeTraceId();
MDCTraceUtils.removeTrace();
}
}
}
......
......@@ -4,6 +4,7 @@ import com.central.log.properties.TraceProperties;
import feign.RequestInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
......@@ -17,8 +18,9 @@ import javax.annotation.Resource;
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Configuration
@ConditionalOnClass(value = {RequestInterceptor.class})
public class FeignTraceInterceptor {
public class FeignTraceConfig {
@Resource
private TraceProperties traceProperties;
......@@ -29,7 +31,9 @@ public class FeignTraceInterceptor {
//传递日志traceId
String traceId = MDCTraceUtils.getTraceId();
if (!StringUtils.isEmpty(traceId)) {
String spanId = MDCTraceUtils.getSpanId();
template.header(MDCTraceUtils.TRACE_ID_HEADER, traceId);
template.header(MDCTraceUtils.SPAN_ID_HEADER, spanId);
}
}
};
......
package com.central.log.trace;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import org.slf4j.MDC;
import java.util.UUID;
......@@ -18,11 +20,27 @@ public class MDCTraceUtils {
* 追踪id的名称
*/
public static final String KEY_TRACE_ID = "traceId";
/**
* 块id的名称
*/
public static final String KEY_SPAN_ID = "spanId";
/**
* 父块id的名称
*/
public static final String KEY_PARENT_ID = "parentId";
/**
* 日志链路追踪id信息头
*/
public static final String TRACE_ID_HEADER = "x-traceId-header";
/**
* 日志链路块id信息头
*/
public static final String SPAN_ID_HEADER = "x-spanId-header";
/**
* 日志链路父块id信息头
*/
public static final String PARENT_ID_HEADER = "x-parentId-header";
/**
* filter的优先级,值越低越优先
......@@ -32,15 +50,19 @@ public class MDCTraceUtils {
/**
* 创建traceId并赋值MDC
*/
public static void addTraceId() {
MDC.put(KEY_TRACE_ID, createTraceId());
public static void addTrace() {
String traceId = createTraceId();
MDC.put(KEY_TRACE_ID, traceId);
MDC.put(KEY_SPAN_ID, traceId);
}
/**
* 赋值MDC
*/
public static void putTraceId(String traceId) {
public static void putTrace(String traceId, String spanId) {
MDC.put(KEY_TRACE_ID, traceId);
MDC.put(KEY_PARENT_ID, spanId);
MDC.put(KEY_SPAN_ID, createTraceId());
}
/**
......@@ -49,18 +71,26 @@ public class MDCTraceUtils {
public static String getTraceId() {
return MDC.get(KEY_TRACE_ID);
}
/**
* 获取MDC中的spanId值
*/
public static String getSpanId() {
return MDC.get(KEY_SPAN_ID);
}
/**
* 清除MDC的值
*/
public static void removeTraceId() {
public static void removeTrace() {
MDC.remove(KEY_TRACE_ID);
MDC.remove(KEY_SPAN_ID);
MDC.remove(KEY_PARENT_ID);
}
/**
* 创建traceId
*/
public static String createTraceId() {
return UUID.randomUUID().toString().replace("-", "").toUpperCase();
return RandomUtil.randomString(16);
}
}
......@@ -3,6 +3,7 @@ package com.central.log.trace;
import com.central.log.properties.TraceProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
......@@ -22,6 +23,7 @@ import java.io.IOException;
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Component
@ConditionalOnClass(value = {HttpServletRequest.class, OncePerRequestFilter.class})
@Order(value = MDCTraceUtils.FILTER_ORDER)
public class WebTraceFilter extends OncePerRequestFilter {
......@@ -38,14 +40,15 @@ public class WebTraceFilter extends OncePerRequestFilter {
FilterChain filterChain) throws IOException, ServletException {
try {
String traceId = request.getHeader(MDCTraceUtils.TRACE_ID_HEADER);
String spanId = request.getHeader(MDCTraceUtils.SPAN_ID_HEADER);
if (StringUtils.isEmpty(traceId)) {
MDCTraceUtils.addTraceId();
MDCTraceUtils.addTrace();
} else {
MDCTraceUtils.putTraceId(traceId);
MDCTraceUtils.putTrace(traceId, spanId);
}
filterChain.doFilter(request, response);
} finally {
MDCTraceUtils.removeTraceId();
MDCTraceUtils.removeTrace();
}
}
}
......@@ -2,9 +2,4 @@ org.springframework.context.ApplicationContextInitializer=\
com.central.log.config.TtlMDCAdapterInitializer
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.central.log.config.LogAutoConfigure,\
com.central.log.service.impl.LoggerAuditServiceImpl,\
com.central.log.service.impl.DbAuditServiceImpl,\
com.central.log.aspect.AuditLogAspect,\
com.central.log.trace.WebTraceFilter,\
com.central.log.trace.FeignTraceInterceptor
com.central.log.LogAutoConfigure
\ No newline at end of file
......@@ -18,8 +18,8 @@
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="[${APP_NAME}:${ServerIP}:${ServerPort}] %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%level){blue} %clr(${PID}){magenta} %clr([%X{traceId}]){yellow} %clr([%thread]){orange} %clr(%-40.40logger{39}){cyan} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" />
<property name="CONSOLE_LOG_PATTERN_NO_COLOR" value="[${APP_NAME}:${ServerIP}:${ServerPort}] %d{yyyy-MM-dd HH:mm:ss.SSS} %level ${PID} [%X{traceId}] [%thread] %-40.40logger{39} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" />
value="[${APP_NAME}:${ServerIP}:${ServerPort}] %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%level){blue} %clr(${PID}){magenta} %clr([%X{traceId},%X{spanId},%X{parentId}]){yellow} %clr([%thread]){orange} %clr(%-40.40logger{39}){cyan} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" />
<property name="CONSOLE_LOG_PATTERN_NO_COLOR" value="[${APP_NAME}:${ServerIP}:${ServerPort}] %d{yyyy-MM-dd HH:mm:ss.SSS} %level ${PID} [%X{traceId},%X{spanId},%X{parentId}] [%thread] %-40.40logger{39} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" />
<!-- 控制台日志 -->
<appender name="StdoutAppender" class="ch.qos.logback.core.ConsoleAppender">
......
package com.central.gateway.filter;
import cn.hutool.core.util.IdUtil;
import com.central.common.constant.CommonConstant;
import com.central.log.properties.TraceProperties;
import org.slf4j.MDC;
import com.central.log.trace.MDCTraceUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
......@@ -31,10 +29,13 @@ public class TraceFilter implements GlobalFilter, Ordered {
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (traceProperties.getEnable()) {
//链路追踪id
String traceId = IdUtil.fastSimpleUUID();
MDC.put(CommonConstant.LOG_TRACE_ID, traceId);
MDCTraceUtils.addTrace();
ServerHttpRequest serverHttpRequest = exchange.getRequest().mutate()
.headers(h -> h.add(CommonConstant.TRACE_ID_HEADER, traceId))
.headers(h -> {
h.add(MDCTraceUtils.TRACE_ID_HEADER, MDCTraceUtils.getTraceId());
h.add(MDCTraceUtils.SPAN_ID_HEADER, MDCTraceUtils.getSpanId());
})
.build();
ServerWebExchange build = exchange.mutate().request(serverHttpRequest).build();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册