Catalog

Pre knowledge

Before we enter the writing process , I suggest you take a moment to learn about javaagent( This is a JDK 5 One of the things introduced , It's better to understand how it works ); in addition ,Skywalking Yes byte-buddy( A library for dynamically manipulating binary code ), So it's better to be familiar with .

Of course, it doesn't matter if you don't know , Generally, it doesn't affect your play Skywalking.

The term

Span: Can be understood as a method call , A call to a block , Or once RPC/ Database access . As long as it is a program access with a full time cycle , Can be regarded as a span.SkyWalking Span An important attribute in an object

attribute name remarks
component Components The component name of the plug-in , Such as :Lettuce, See :ComponentsDefine.Class.
tag label k-v structure , Key tags ,key See :Tags.Class.
peer Peer resources For topological graphs , if DB Components , Need to record cluster information .
operationName Operation name if span=0,operationName The drop-down list that will be searched .
layer Show The link page shows , See SpanLayer.Class.

Trace: Call chain , By belonging to Span To the implicit definition of . One Trace Can be thought of as one by more than one Span Composed of directed acyclic graphs (DAG chart ), stay SkyWalking Link module you can see ,Trace There are more than one that belongs to it trace segment form .

Trace segment:Segment yes SkyWalking A concept in , It should include a single OS All scopes of each request in the process , It's usually a language based single thread . By more than one belonging to this thread operation Span form .

TIPS

Skywalking These terms and Spring Cloud Sleuth similar , Learn from Google Dapper. I am here 《Spring Cloud Alibaba Microservices from entry to advanced 》 In this course, the implementation principle of call chain is analyzed in detail , And make a popular analogy with the database , This article will not be repeated .

The core API

See http://www.itmuch.com/books/skywalking/guides/Java-Plugin-Development-Guide.html The article has a very detailed description .

actual combat

This article is to monitor org.apache.commons.lang3.StringUtils.replace For example , Hand in hand to teach you to write Skywalking plug-in unit .

rely on

First , Create a Maven project ,Pom.xml as follows .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?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">
<modelVersion>4.0.0</modelVersion>

<groupId>com.itmuch.skywalking</groupId>
<artifactId>apm-string-replace-plugin</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>

<properties>
<skywalking.version>6.6.0</skywalking.version>
<shade.package>org.apache.skywalking.apm.dependencies</shade.package>
<shade.net.bytebuddy.source>net.bytebuddy</shade.net.bytebuddy.source>
<shade.net.bytebuddy.target>${shade.package}.${shade.net.bytebuddy.source}</shade.net.bytebuddy.target>
</properties>

<dependencies>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-agent-core</artifactId>
<version>${skywalking.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-util</artifactId>
<version>${skywalking.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<createDependencyReducedPom>true</createDependencyReducedPom>
<createSourcesJar>true</createSourcesJar>
<shadeSourcesContent>true</shadeSourcesContent>
<relocations>
<relocation>
<pattern>${shade.net.bytebuddy.source}</pattern>
<shadedPattern>${shade.net.bytebuddy.target}</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

This Pom.xml in , In addition to the following dependencies , Everything else has to be copied , No matter what framework you develop Skywalking plug-in unit , Otherwise, the plug-in cannot be built normally !!

1
2
3
4
5
6
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
<scope>provided</scope>
</dependency>

To write Instrumentation class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class StringReplaceInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
@Override
protected ClassMatch enhanceClass() {
// Specify the class you want to monitor
return NameMatch.byName("org.apache.commons.lang3.StringUtils");
}

@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}

@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
// Specify the instance method you want to monitor , Each instance method corresponds to a InstanceMethodsInterceptPoint
return new InstanceMethodsInterceptPoint[0];
}

@Override
public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
// Specify the static method you want to monitor , Each method corresponds to a StaticMethodsInterceptPoint
return new StaticMethodsInterceptPoint[]{
new StaticMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
// Static method name
return ElementMatchers.named("replace");
}

@Override
public String getMethodsInterceptor() {
// The static method's monitor interceptor class name full path
return "com.itmuch.skywalking.plugin.stringreplace.StringReplaceInterceptor";
}

@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
}

Write interceptors

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class StringReplaceInterceptor implements StaticMethodsAroundInterceptor {
@Override
public void beforeMethod(Class aClass, Method method, Object[] argumentsTypes, Class<?>[] classes, MethodInterceptResult methodInterceptResult) {
// establish span( Start of monitoring ), It's essentially going to ThreadLocal Set the value in the object
AbstractSpan span = ContextManager.createLocalSpan("replace");

/*
* You can use ComponentsDefine Tool class specifies Skywalking Officially supported components
* You can also new OfficialComponent perhaps Component
* But in the Skywalking Will not be recognized on the console of , It will only show N/A
*/
span.setComponent(ComponentsDefine.TOMCAT);

span.tag(new StringTag(1000, "params"), argumentsTypes[0].toString());
// Specifies the layer,layer It's an enumeration.
span.setLayer(SpanLayer.CACHE);
}

@Override
public Object afterMethod(Class aClass, Method method, Object[] objects, Class<?>[] classes, Object o) {
String retString = (String) o;
// Activate span, It's essentially reading ThreadLocal object
AbstractSpan span = ContextManager.activeSpan();
// Status code , Write at will ,Tags It's also a Skywalking Tool class of , It is used to operate conveniently tag
Tags.STATUS_CODE.set(span, "20000");

// stop it span( The end of monitoring ), It's essentially cleaning up ThreadLocal object
ContextManager.stopSpan();
return retString;
}

@Override
public void handleMethodException(Class aClass, Method method, Object[] objects, Class<?>[] classes, Throwable throwable) {
AbstractSpan activeSpan = ContextManager.activeSpan();

// Log
activeSpan.log(throwable);
activeSpan.errorOccurred();
}
}

Writing configuration files

establish resources/skywalking-plugin.def , The contents are as follows :

1
2
3
4
# Key=value In the form of 
# key Write casually ;value yes Instrumentation Class package name class name full path
my-string-replace-
plugin=org.apache.skywalking.apm.plugin.stringreplace.define.StringReplaceInstrumentation

structure

1
mvn clean install

After building , To target Directory , find JAR package ( Not origin-xxx.jar 、 Not xxx-source.jar ), Throw it agent/plugins In the catalogue , You can start .

Plug in debugging

Plug ins may not be written in one step , Sometimes you may report something wrong . If you want to Debug Own plug-ins , Then you need to put your plug-in code and access Java Agent Project ( That is, you have configured -javaagent Projects started ) Throw it in the same workspace , You can play like this :

  • Use IDEA, Open access Java Agent Project
  • find File->New->Module from Exisiting Sources…, Introduce your plug-in source code .

IDEA

Test and monitor the effect

Find a way to connect you to Java Agent Project , Call to the following code

1
2
String replace = StringUtils.replace("oldString", "old","replaced");
System.out.println(replace);

 Monitoring effect display

after , You can see the following figure :

At the end

This article just gives a simple example , Explain how to write plug-ins . in general , Plug in writing is still very smooth , The level of pure code , It's rare to see a pit ; But search all kinds of search engines , There's not a single article on the handle … And there is no article on how dependency can be introduced 、Maven How to introduce plug-ins . So I have to refer to Skywalking How to write the official plug-in , Introduce dependencies and Maven Plug in , This one took a little time .

Besides , If you want to really master and master skywalking Plug in writing , The best way , Or read the official plug-in code , See :https://github.com/apache/skywalking/tree/master/apm-sniffer/apm-sdk-plugin , Just pick two and you'll know how to play . The plug-in code I refer to in the learning process is :

  • apm-feign-default-http-9.x-plugin
  • apm-jdbc-commons

Reference documents

Related articles