For example, some people may think it's a little superfluous to do this, but I personally feel that this is still necessary. Nothing else, just to save a few seconds of search time. Overall, there will be some minor improvements in the development and debugging of microservices, which is also an optimization to facilitate the development of small partners. A good framework is optimized bit by bit. No more nonsense. Let's talk about the overall idea first, and finally give a realization.
1. First, we need to operate the head. We can move our hands and feet in the interceptor or filter
2. You need to get the service address and traceId of skywalking
The idea is that these two steps look very simple
show your code
maven dependence, Baotou please feel free
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>omsa-all</artifactId> <groupId>com.qimo</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.qimo.trace</groupId> <artifactId>omsa-trace</artifactId> <packaging>jar</packaging> <dependencies> <!-- trace Related package --> <dependency> <groupId>org.apache.skywalking</groupId> <artifactId>apm-toolkit-trace</artifactId> <version>8.2.0</version> </dependency> <!-- trace and logback Integrated package--> <dependency> <groupId>org.apache.skywalking</groupId> <artifactId>apm-toolkit-logback-1.x</artifactId> <version>8.2.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.5.RELEASE</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot</artifactId> <version>2.1.3.RELEASE</version> </dependency> <!--Configuration prompt generation package--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <version>2.1.3.RELEASE</version> <optional>true</optional> </dependency> </dependencies> </project>
Define attribute oap_ui address skywalkingUrl
package com.qimo.trace; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @Description TODO * @Author Yao Zhongjie #80998699 * @Date 2021/6/20 23:51 */ @ConfigurationProperties(prefix = "omsa.trace") public class OmsaTraceProperties { private String skywalkingUrl="http://"; public String getSkywalkingUrl() { return skywalkingUrl; } public void setSkywalkingUrl(String skywalkingUrl) { this.skywalkingUrl = skywalkingUrl; } }
Define the address where the interceptor splices traceid and skywalkingUrl to the head. The final effect is this http://127.0.0.1:10800/trace?traceId=0a0cb455e8bf44718a70589e5818d5f9.66.16242401437190001
package com.qimo.trace; import com.qimo.trace.configuration.OmsaTraceConst; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.skywalking.apm.toolkit.trace.TraceContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; /** * @Description TODO * @Author Yao Zhongjie #80998699 * @Date 2021/6/20 23:36 */ public class OmsaTraceHeaderInterceptor extends HandlerInterceptorAdapter { @Autowired OmsaTraceProperties omsaTraceProperties; public OmsaTraceHeaderInterceptor() { super(); } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String traceId=TraceContext.traceId(); if (StringUtils.isEmpty(traceId)){ traceId=OmsaTraceConst.NULL_TRACE_ID; } response.setHeader(OmsaTraceConst.OMSA_TRACE_VISIT_URL_KEY, omsaTraceProperties.getSkywalkingUrl().replace("@{traceId}",traceId)); return true; } }
The above code has completed the function, and the rest is the loading of bean s
Here we use a @ Enable * function to load this package
1. Declaration annotation
package com.qimo.trace.annotation; import com.qimo.trace.OmsaTraceProperties; import com.qimo.trace.configuration.OmsaTraceConfigurationImportSelector; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Import; /** * @Description TODO * @Author Yao Zhongjie #80998699 * @Date 2021/6/21 0:20 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface EnableOmsaTrace { String[] includePatterns() default {"/**/**"}; String[] excludePatterns() default {"/**/*.js", "/**/*.css", "/**/*.html"}; }
2. Write registrar configuration bean
package com.qimo.trace.configuration; import com.qimo.trace.annotation.EnableOmsaTrace; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; import org.springframework.web.servlet.handler.MappedInterceptor; /** * @Description TODO * @Author Yao Zhongjie #80998699 * @Date 2021/6/21 0:23 */ public class OmsaTraceBeanRegistrar implements ImportBeanDefinitionRegistrar { public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { String[] includePatterns = getAnnotationAttributesValue(importingClassMetadata, "includePatterns"); String[] excludePatterns = getAnnotationAttributesValue(importingClassMetadata, "excludePatterns"); GenericBeanDefinition beanDefinition = new GenericBeanDefinition(); beanDefinition.setBeanClass(MappedInterceptor.class); beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, includePatterns); beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(1, excludePatterns); beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(2, new RuntimeBeanReference( OmsaTraceConst.OMSA_TRACE_HEADER_INTERCEPTOR_BEAN_NAME)); BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry); } private String[] getAnnotationAttributesValue(AnnotationMetadata metadata, String attribute) { AnnotationAttributes attributes = AnnotationAttributes.fromMap( metadata.getAnnotationAttributes(EnableOmsaTrace.class.getName())); String[] basePackages = attributes.getStringArray(attribute); return basePackages; } }
3. Write Configuration bean
package com.qimo.trace.configuration; import com.qimo.trace.OmsaTraceHeaderInterceptor; import org.springframework.context.annotation.Bean; /** * @Description TODO * @Author Yao Zhongjie #80998699 * @Date 2021/6/20 23:57 */ public class OmsaTraceConfiguration { @Bean(OmsaTraceConst.OMSA_TRACE_HEADER_INTERCEPTOR_BEAN_NAME) public OmsaTraceHeaderInterceptor omsaTraceHeaderInterceptor(){ return new OmsaTraceHeaderInterceptor(); } }
4. Write selectort to collect the bean s that need to be loaded
package com.qimo.trace.configuration; import java.util.ArrayList; import java.util.List; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; /** * @Description TODO * @Author Yao Zhongjie #80998699 * @Date 2021/6/21 0:22 */ public class OmsaTraceConfigurationImportSelector implements ImportSelector { public String[] selectImports(AnnotationMetadata annotationMetadata) { List<String> importList=new ArrayList<String>(); importList.add(OmsaTraceConfiguration.class.getName()); importList.add(OmsaTraceBeanRegistrar.class.getName()); return importList.toArray(new String[importList.size()]); } }
Modify annotation and import selector and properties
package com.qimo.trace.annotation; import com.qimo.trace.OmsaTraceProperties; import com.qimo.trace.configuration.OmsaTraceConfigurationImportSelector; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Import; /** * @Description TODO * @Author Yao Zhongjie #80998699 * @Date 2021/6/21 0:20 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @EnableConfigurationProperties(OmsaTraceProperties.class) @Import(OmsaTraceConfigurationImportSelector.class) @Documented public @interface EnableOmsaTrace { String[] includePatterns() default {"/**/**"}; String[] excludePatterns() default {"/**/*.js", "/**/*.css", "/**/*.html"}; }
Package and release, and then build a related demo project. Of course, you also need to have skywalking server and agent. It's very simple to pull one directly from the dockerhub. The version of the above package is 8.2.0. Then I'll pull an 8.2.0 server directly and use docker compose directly.
version: "3.1" services: oap: image: apache/skywalking-oap-server:8.2.0-es7 restart: always ports: - 11800:11800 - 12800:12800 oap_ui: image: apache/skywalking-ui:8.2.0 restart: always environment: SW_OAP_ADDRESS: "oap:12800" ports: - 10800:8080
Start another springboot demo project, introduce the current package, and annotate @ EnableOmsaTrace on the startup class
@SpringBootApplication @EnableOmsaTrace public class OmsaDemoApplication { public static void main(String[] args) { SpringApplication.run(OmsaDemoApplication.class,args); }
Of course, you also need to configure logback, because we only do logback here. If you want to use other logging frameworks, you need to replace the top dependency package with the related framework dependency
The configuration of logback spring is as follows: randomly extract one.
<?xml version="1.0" encoding="utf-8"?> <configuration> <jmxConfigurator/> <property name="log_pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS Z} [%tid] [%thread] %-5level %logger{50}:%line %msg%n"></property> <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender"> <!--code--> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <!--Display format--> <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${log_pattern}</pattern> </layout> </encoder> </appender> <appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--code--> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <!--Display format--> <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${log_pattern}</pattern> </layout> </encoder> <!--Rolling strategy --> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!--route --> <fileNamePattern>log/%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!--More than 100 M Sub document--> <maxFileSize>100MB</maxFileSize> </rollingPolicy> </appender> <!--Specifies the most basic log output level--> <root level="info"> <appender-ref ref="consoleLog"/> <appender-ref ref="fileLog"/> </root> </configuration>
Write a simple controller
package com.qimo.omsa.demo.trace; import org.apache.skywalking.apm.toolkit.trace.TraceContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @Description TODO * @Author Yao Zhongjie #80998699 * @Date 2021/6/21 1:18 */ @RestController public class TraceTestController { Logger log= LoggerFactory.getLogger(TraceTestController.class); @GetMapping("/trace") public String trace(){ log.info(TraceContext.traceId()); return TraceContext.traceId(); } }
application. Configure your skywalking address in properties
server.port=7777 logging.level.root=info omsa.trace.skywalking-url=http://127.0.0.1:10800/trace?traceId=@{traceId}
The access effect is as follows
Copy link direct access