完善 skywalking 组件的集成

This commit is contained in:
YunaiV 2021-04-26 01:35:05 +08:00
parent 81b1f3751a
commit e351cdf785
13 changed files with 159 additions and 130 deletions

View File

@ -196,6 +196,11 @@
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>${skywalking.version}</version>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-opentracing</artifactId>
<version>${skywalking.version}</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>

View File

@ -1,10 +1,15 @@
package cn.iocoder.dashboard.framework.tracer.config;
import cn.iocoder.dashboard.framework.tracer.core.annotation.BizTracingAop;
import cn.iocoder.dashboard.framework.tracer.core.aop.BizTraceAspect;
import cn.iocoder.dashboard.framework.tracer.core.filter.TraceFilter;
import cn.iocoder.dashboard.framework.web.core.enums.FilterOrderEnum;
import io.opentracing.Tracer;
import org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -14,21 +19,38 @@ import org.springframework.context.annotation.Configuration;
* @author mashu
*/
@Configuration
@ConditionalOnClass({BizTracingAop.class})
@EnableConfigurationProperties(BizTracerProperties.class)
@ConditionalOnClass({BizTraceAspect.class})
@EnableConfigurationProperties(TracerProperties.class)
@ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true)
public class TracerAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public BizTracerProperties bizTracerProperties() {
return new BizTracerProperties();
public TracerProperties bizTracerProperties() {
return new TracerProperties();
}
@Bean
@ConditionalOnMissingBean
public BizTracingAop bizTracingAop() {
return new BizTracingAop();
public BizTraceAspect bizTracingAop() {
return new BizTraceAspect();
}
@Bean
@ConditionalOnMissingBean
public Tracer tracer() {
return new SkywalkingTracer();
}
/**
* 创建 TraceFilter 过滤器响应 header 设置 traceId
*/
@Bean
public FilterRegistrationBean<TraceFilter> traceFilter() {
FilterRegistrationBean<TraceFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new TraceFilter());
registrationBean.setOrder(FilterOrderEnum.TRACE_FILTER);
return registrationBean;
}
}

View File

@ -10,5 +10,5 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
*/
@ConfigurationProperties("yudao.tracer")
@Data
public class BizTracerProperties {
public class TracerProperties {
}

View File

@ -10,7 +10,7 @@ import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface BizTracing {
public @interface BizTrace {
/**
* 业务编号 tag
@ -21,6 +21,11 @@ public @interface BizTracing {
*/
String TYPE_TAG = "biz.type";
/**
* @return 操作名
*/
String operationName() default "";
/**
* @return 业务编号
*/

View File

@ -1,32 +0,0 @@
package cn.iocoder.dashboard.framework.tracer.core.annotation;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.dashboard.util.sping.SpElUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.toolkit.trace.ActiveSpan;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
/**
* 业务链路AOP切面
*
* @author mashu
*/
@Aspect
@Slf4j
public class BizTracingAop {
@Around(value = "@annotation(bizTracing)")
public void tagBizInfo(ProceedingJoinPoint joinPoint, BizTracing bizTracing) {
String bizId = (String) SpElUtil.analysisSpEl(bizTracing.id(), joinPoint);
String bizType = (String) SpElUtil.analysisSpEl(bizTracing.type(), joinPoint);
if (StrUtil.isBlankIfStr(bizId)) {
log.error("empty biz: bizId[{}], bizType[{}].", bizId, bizType);
return;
}
log.info("accept biz: bizId[{}], bizType[{}].", bizId, bizType);
ActiveSpan.tag(BizTracing.ID_TAG, bizId);
ActiveSpan.tag(BizTracing.TYPE_TAG, bizType);
}
}

View File

@ -0,0 +1,65 @@
package cn.iocoder.dashboard.framework.tracer.core.aop;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.dashboard.framework.tracer.core.annotation.BizTrace;
import cn.iocoder.dashboard.util.sping.SpElUtil;
import io.opentracing.Span;
import io.opentracing.Tracer;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import javax.annotation.Resource;
/**
* {@link BizTrace} 切面记录业务链路
*
* @author mashu
*/
@Aspect
@Slf4j
public class BizTraceAspect {
private static final String BIZ_OPERATION_NAME_PREFIX = "Biz/";
@Resource
private Tracer tracer;
@Around(value = "@annotation(trace)")
public Object around(ProceedingJoinPoint joinPoint, BizTrace trace) throws Throwable {
// 创建 span
String operationName = getOperationName(joinPoint, trace);
Span span = tracer.buildSpan(operationName).startManual();
try {
// 执行原有方法
return joinPoint.proceed();
} finally {
// 设置 Span biz 属性
setBizTag(span, joinPoint, trace);
// 完成 Span
span.finish();
}
}
private String getOperationName(ProceedingJoinPoint joinPoint, BizTrace trace) {
// 自定义操作名
if (StrUtil.isNotEmpty(trace.operationName())) {
return BIZ_OPERATION_NAME_PREFIX + trace.operationName();
}
// 默认操作名使用方法名
return BIZ_OPERATION_NAME_PREFIX
+ joinPoint.getSignature().getDeclaringType().getSimpleName()
+ "/" + joinPoint.getSignature().getName();
}
private void setBizTag(Span span, ProceedingJoinPoint joinPoint, BizTrace trace) {
try {
span.setTag(BizTrace.TYPE_TAG, StrUtil.toString(SpElUtil.analysisSpEl(trace.type(), joinPoint)));
span.setTag(BizTrace.ID_TAG, StrUtil.toString(SpElUtil.analysisSpEl(trace.id(), joinPoint)));
} catch (Exception ex) {
log.error("[around][解析 bizType 与 bizId 发生异常]", ex);
}
}
}

View File

@ -0,0 +1,33 @@
package cn.iocoder.dashboard.framework.tracer.core.filter;
import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Trace 过滤器打印 traceId header 中返回
*
* @author 芋道源码
*/
public class TraceFilter extends OncePerRequestFilter {
/**
* Header - 链路追踪编号
*/
private static final String HEADER_NAME_TRACE_ID = "trace-id";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 设置响应 traceId
response.addHeader(HEADER_NAME_TRACE_ID, TracerUtils.getTraceId());
// 继续过滤
chain.doFilter(request, response);
}
}

View File

@ -2,8 +2,6 @@ package cn.iocoder.dashboard.framework.tracer.core.util;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
import java.util.UUID;
/**
* 链路追踪工具类
*
@ -18,10 +16,8 @@ public class TracerUtils {
}
/**
* 获得链路追踪编号
* <p>
* 直接返回skywalking 的TraceId 如果不存在的话为空字符串""
* <p>
* 获得链路追踪编号直接返回 SkyWalking TraceId
* 如果不存在的话为空字符串
*
* @return 链路追踪编号
*/

View File

@ -1,42 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package cn.iocoder.dashboard.framework.tracer.skywalking;
import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils;
/**
* Created by mashu on 2021/3/6.
*/
public class LocalLogbackPatternConverter extends ClassicConverter {
/**
* 作为默认的方式, {@link TracerUtils}中获取traceId,
* 需要用这个去替代logback的Layout,
* 同时避免了sky-walking agent生效的情况下仍然输出定值的问题.
*
* @param iLoggingEvent the event
* @return the traceId: UUID, or the real traceId.
*/
@Override
public String convert(ILoggingEvent iLoggingEvent) {
return TracerUtils.getTraceId();
}
}

View File

@ -1,37 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package cn.iocoder.dashboard.framework.tracer.skywalking;
import ch.qos.logback.classic.PatternLayout;
/**
* Based on the logback-component convert register mechanism,
* register {@link LocalLogbackPatternConverter} as a new convert, match to "tid".
* You can use "%tid" in logback config file, "Pattern" section.
* If sky-walking agent is not active mode, it will use UUID as tid.
* <p>
* logback 的转换组件,为tid 添加占位符的转换器
* Created by mashu on 2021/3/6.
*/
public class TraceIdPatternLogbackLayout extends PatternLayout {
static {
defaultConverterMap.put("tid", LocalLogbackPatternConverter.class.getName());
}
}

View File

@ -9,6 +9,7 @@ public interface FilterOrderEnum {
int CORS_FILTER = Integer.MIN_VALUE;
int TRACE_FILTER = CORS_FILTER + 1;
int REQUEST_BODY_CACHE_FILTER = Integer.MIN_VALUE + 500;

View File

@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.auth;
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
import cn.iocoder.dashboard.common.pojo.CommonResult;
import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
import cn.iocoder.dashboard.framework.tracer.core.annotation.BizTrace;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthLoginRespVO;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO;
@ -58,6 +59,7 @@ public class SysAuthController {
@GetMapping("/get-permission-info")
@ApiOperation("获取登陆用户的权限信息")
@BizTrace(id = "1", type = "'user'")
public CommonResult<SysAuthPermissionInfoRespVO> getPermissionInfo() {
// 获得用户信息
SysUserDO user = userService.getUser(getLoginUserId());

View File

@ -1,11 +1,13 @@
<configuration>   
<configuration>  
 
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">     
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="cn.iocoder.dashboard.framework.tracer.skywalking.TraceIdPatternLogbackLayout">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>%d{ISO8601} | %tid | %thread | %-5level | %msg%n</pattern>
</layout>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>./logs/ruoyi-vue-pro-%d{yyyy-MM-dd_HH}.log</FileNamePattern>
@ -20,13 +22,20 @@
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>10</queueSize>
<appender-ref ref="FILE"/>
</appender>
<!-- skywalking grpc 日志收集 8.4.0版本开始支持 -->
<appender name="GRPC" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n</Pattern>
</layout>
</encoder>s
</appender>
<springProfile name="dev">
@ -35,12 +44,14 @@
<appender-ref ref="ASYNC"/>
</logger>
</springProfile>
<springProfile name="local">
<logger name="cn.iocoder.dashboard" level="INFO" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="GRPC"/>
</logger>
</springProfile>
<springProfile name="default">
<logger name="cn.iocoder.dashboard" level="INFO" additivity="false">
<appender-ref ref="STDOUT"/>
@ -48,7 +59,7 @@
</logger>
</springProfile>
<root level="DEBUG">      
<root level="INFO">      
<appender-ref ref="STDOUT"/>   
<appender-ref ref="ASYNC"/> 
</root>
@ -56,4 +67,4 @@
<logger name="cn.iocoder.dashboard" level="INFO">
<appender-ref ref="STDOUT"/>
</logger>
</configuration>
</configuration>