As the question, maybe some people feel that doing this is a bit unnecessary, but personally feel the necessity of this is still some. For nothing but to save a few seconds of search time. Overall, there will be some minor improvements in the development and debugging of micro-services, which is also a kind of optimization for convenient development partners. A good framework is optimized bit by bit. No more nonsense, talk about the general idea and finally give a realization. We need to get the SkyWalking service address and traceId. The idea is that these two steps seem simple

Show your code Maven dependencies. Please feel free to use the header


      
<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 - the SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.qimo.trace</groupId>
    <artifactId>omsa-trace</artifactId>
    <packaging>jar</packaging>
    <dependencies>
    	<! -- trace related packages -->
        <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>
        <! -- Config prompt generate 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>
Copy the code

Define the address skywalkingUrl for the attribute oap_UI

package com.qimo.trace;

import org.springframework.boot.context.properties.ConfigurationProperties;

/ * * *@Description TODO
 * @AuthorYao Zhongjie #80998699 *@Date2021/6/20 struck * /
@ConfigurationProperties(prefix = "omsa.trace")
public class OmsaTraceProperties {
    
    private String skywalkingUrl="http://";
    
    public String getSkywalkingUrl(a) {
        return skywalkingUrl;
    }
    
    public void setSkywalkingUrl(String skywalkingUrl) {
        this.skywalkingUrl = skywalkingUrl; }}Copy the code

Define interceptor to head plug traceId and skywalkingUrl splicing the address of the final effect is http://127.0.0.1:10800/trace? TraceId = 0 a0cb455e8bf44718a70589e5818d5f9. 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
 * @AuthorYao Zhongjie #80998699 *@Date2021/6/20 declare * /
public class OmsaTraceHeaderInterceptor extends HandlerInterceptorAdapter {
    
    @Autowired
    OmsaTraceProperties omsaTraceProperties;
    
    public OmsaTraceHeaderInterceptor(a) {
        super(a); }@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; }}Copy the code

We use @enable * to load the function of the package

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
 * @AuthorYao Zhongjie #80998699 *@Date2021/6/21 0:20 * /
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnableOmsaTrace {
    
    String[] includePatterns() default {"/ / * * * *"};
    
    String[] excludePatterns() default {"/**/*.js"."/**/*.css"."/**/*.html"};

    
}

Copy the code

Write the 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
 * @AuthorYao Zhongjie #80998699 *@Date2021/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);
        
        returnbasePackages; }}Copy the code

3. Write a Configuration bean

package com.qimo.trace.configuration;

import com.qimo.trace.OmsaTraceHeaderInterceptor;
import org.springframework.context.annotation.Bean;

/ * * *@Description TODO
 * @AuthorYao Zhongjie #80998699 *@Date2021/6/20 23:57 * /
public class OmsaTraceConfiguration {
    
    @Bean(OmsaTraceConst.OMSA_TRACE_HEADER_INTERCEPTOR_BEAN_NAME)
    public OmsaTraceHeaderInterceptor omsaTraceHeaderInterceptor(a){
        return newOmsaTraceHeaderInterceptor(); }}Copy the code

Write selectort to collect beans 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
 * @AuthorYao Zhongjie #80998699 *@Date2021/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(newString[importList.size()]); }}Copy the code

Modify annotations to 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
 * @AuthorYao Zhongjie #80998699 *@Date2021/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"};

    
}

Copy the code

Of course, at the same time you also need to have skyWalking server and agent, it is very simple to pull one directly from dockerHub, the version of the above package is 8.2.0, I directly pull a 8.2.0 server, directly use docker-compose.

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
Copy the code

Introduce the current package again with a Springboot-demo project. Try annotating @enableomsatrace on the startup class

@SpringBootApplication
@EnableOmsaTrace
public class OmsaDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(OmsaDemoApplication.class,args);
    }
Copy the code

Of course, you need to configure logback because we only do logback here. If you want to use other logging frameworks, you need to replace the top layer of the dependency layer with the logback-spring configuration:


      
<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">
        <! - - - >
        <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">
        <! - - - >
        <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>
        <! -- Scroll Strategy -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <! -- -- -- > path
            <fileNamePattern>log/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <! -- Divide files over 100M -->
            <maxFileSize>100MB</maxFileSize>
        </rollingPolicy>
    </appender>
    <! -- Specify the most basic log output level -->
    <root level="info">
        <appender-ref ref="consoleLog"/>
        <appender-ref ref="fileLog"/>
    </root>
</configuration>
Copy the code

I’ll 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
 * @AuthorYao Zhongjie #80998699 *@Date2021/6/21 1:18 * /
@RestController
public class TraceTestController {
    Logger log= LoggerFactory.getLogger(TraceTestController.class);
    
    @GetMapping("/trace")
    public String trace(a){
        log.info(TraceContext.traceId());
        returnTraceContext.traceId(); }}Copy the code

Your SkyWalking address on the application. Properties configuration

Server port = 7777 logging. Level. The root = info omsa. Trace. Skywalking - url = HTTP: / / http://127.0.0.1:10800/trace? traceId=@{traceId}Copy the code

The access effect is as followsCopy the link to access directly