diff --git a/src/main/java/cn/iocoder/dashboard/framework/tracer/core/ITrace.java b/src/main/java/cn/iocoder/dashboard/framework/tracer/core/ITrace.java new file mode 100644 index 000000000..483b408db --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/tracer/core/ITrace.java @@ -0,0 +1,16 @@ +package cn.iocoder.dashboard.framework.tracer.core; + +/** + * 用于扩展获取traceId的场景,需要装载到Spring bean容器中. + * + * @author 麻薯 + */ +public interface ITrace { + + /** + * 用于接入三方traceId + * + * @return traceId + */ + String getTraceId(); +} diff --git a/src/main/java/cn/iocoder/dashboard/framework/tracer/core/util/TracerUtils.java b/src/main/java/cn/iocoder/dashboard/framework/tracer/core/util/TracerUtils.java index 777c273cb..a9f85be41 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/tracer/core/util/TracerUtils.java +++ b/src/main/java/cn/iocoder/dashboard/framework/tracer/core/util/TracerUtils.java @@ -1,6 +1,8 @@ package cn.iocoder.dashboard.framework.tracer.core.util; import cn.hutool.core.util.StrUtil; +import cn.iocoder.dashboard.framework.tracer.core.ITrace; +import cn.iocoder.dashboard.util.bean.SpringUtil; import org.apache.skywalking.apm.toolkit.trace.TraceContext; import java.util.UUID; @@ -12,26 +14,62 @@ import java.util.UUID; */ public class TracerUtils { + /** + * 私有化构造方法 + */ + private TracerUtils() { + } + /** * 获得链路追踪编号 - * + *

* 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。 - * + *

* 默认情况下,我们使用 Apache SkyWalking 的 traceId 作为链路追踪编号。当然,可能会存在并未引入 Skywalking 的情况,此时使用 UUID 。 * * @return 链路追踪编号 */ public static String getTraceId() { + // 通过自定义扩展的tracer产生traceId, 在Spring容器加载完成前会获取不到对应的Bean + ITrace tracer = null; + try { + tracer = getTracer(); + } catch (Throwable ignore) { + } + if (null != tracer) { + try { + return tracer.getTraceId(); + } catch (Throwable ignored) { + } + } // 通过 SkyWalking 获取链路编号 try { String traceId = TraceContext.traceId(); if (StrUtil.isNotBlank(traceId)) { return traceId; } - } catch (Throwable ignore) {} + } catch (Throwable ignore) { + } // TODO 芋艿 多次调用会问题 - // TODO 麻薯 定义一个给外部扩展的接口,默认在未接入Skywalking时,输出UUID + return defaultTraceId(); + } + + /** + * 从Spring 容器中获取 ITrace 类,返回可以为null + * + * @return ITrace + */ + private static ITrace getTracer() { + return SpringUtil.getBean(ITrace.class); + } + + /** + * 默认生成TraceId规则为UUID + * + * @return UUID + */ + private static String defaultTraceId() { return "UUID:" + UUID.randomUUID().toString(); } diff --git a/src/main/java/cn/iocoder/dashboard/util/bean/SpringUtil.java b/src/main/java/cn/iocoder/dashboard/util/bean/SpringUtil.java new file mode 100644 index 000000000..4cbfb4e36 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/util/bean/SpringUtil.java @@ -0,0 +1,83 @@ +package cn.iocoder.dashboard.util.bean; + +import org.springframework.beans.BeansException; + +import org.springframework.beans.factory.NoSuchBeanDefinitionException; + +import org.springframework.context.ApplicationContext; + +import org.springframework.context.ApplicationContextAware; + +import org.springframework.stereotype.Component; + + +@Component +public class SpringUtil implements ApplicationContextAware { + + /** + * Spring context + */ + private static ApplicationContext applicationContext = null; + + public void setApplicationContext(ApplicationContext context) throws BeansException { + if (applicationContext == null) { + applicationContext = context; + } + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + public static void setAppCtx(ApplicationContext webAppCtx) { + if (webAppCtx != null) { + applicationContext = webAppCtx; + } + } + + + /** + * 拿到ApplicationContext对象实例后就可以手动获取Bean的注入实例对象 + */ + public static T getBean(Class clazz) { + return getApplicationContext() == null ? null : getApplicationContext().getBean(clazz); + } + + + public static T getBean(String name, Class clazz) throws ClassNotFoundException { + return getApplicationContext() == null ? null : getApplicationContext() .getBean(name, clazz); + } + + + public static final Object getBean(String beanName) { + return getApplicationContext() == null ? null : getApplicationContext() .getBean(beanName); + } + + + public static final Object getBean(String beanName, String className) throws ClassNotFoundException { + Class clz = Class.forName(className); + return getApplicationContext() == null ? null : getApplicationContext() .getBean(beanName, clz.getClass()); + + } + + + public static boolean containsBean(String name) { + return getApplicationContext() == null ? null : getApplicationContext() .containsBean(name); + } + + + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { + return getApplicationContext() == null ? null : getApplicationContext() .isSingleton(name); + } + + + public static Class getType(String name) throws NoSuchBeanDefinitionException { + return getApplicationContext() == null ? null : getApplicationContext() .getType(name); + } + + + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { + return getApplicationContext() == null ? null : getApplicationContext() .getAliases(name); + } + +} \ No newline at end of file