springboot integrates skywalking to add the interface link to the responeHeader

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

Keywords: Microservices

Added by noon on Fri, 28 Jan 2022 04:13:42 +0200