提交 2fa75f9b 编写于 作者: P pengys5

Merge remote-tracking branch 'origin/feature/3.0' into feature/collector

......@@ -15,6 +15,7 @@ SkyWalking: Large-Scale Distributed Systems Tracing Infrastructure, also known D
# News
* sky-walking v3.0 iteration begins... The top 2 important features are: [`Update the trace-structure`](https://github.com/wu-sheng/sky-walking/issues/83) and [`Analyze trace, and bring metric/analytic/cause up`](https://github.com/wu-sheng/sky-walking/issues/84)
* See feature codes at [branch feature/3.0](https://github.com/wu-sheng/sky-walking/tree/feature/3.0)
* The new UI release on [wu-sheng/sky-walking-ui](https://github.com/wu-sheng/sky-walking-ui)
# Abstract
* An open source Large-Scale Distributed Systems Tracing Infrastructure, also known a ditributed tracer.
......
......@@ -15,7 +15,7 @@ import java.nio.ByteBuffer;
* Created by wusheng on 2016/12/20.
*/
public class SkyWalkingTracer implements Tracer {
private static String TRACE_HEAD_NAME = "SkyWalking-TRACING-NAME";
private static String TRACE_HEAD_NAME = "SW-TRACING-NAME";
public static Tracer INSTANCE = new SkyWalkingTracer();
......
......@@ -12,8 +12,6 @@
<modules>
<module>skywalking-trace</module>
<module>skywalking-logging</module>
<module>skywalking-health-report</module>
<module>skywalking-util</module>
</modules>
......
<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>skywalking-commons</artifactId>
<groupId>com.a.eye</groupId>
<version>3.0-2017</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>skywalking-health-report</artifactId>
<packaging>jar</packaging>
<name>skywalking-health-report</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>com.a.eye</groupId>
<artifactId>skywalking-logging-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
package com.a.eye.skywalking.health.report;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class HealthCollector extends Thread {
private static ILog logger = LogManager.getLogger(HealthCollector.class);
private static Map<String, HeathReading> heathReadings = new ConcurrentHashMap<String, HeathReading>();
private static final long DEFAULT_REPORT_INTERVAL = 60 * 1000;
private final long reportInterval;
private String reporterName;
private HealthCollector(String reporterName) {
this(DEFAULT_REPORT_INTERVAL);
this.reporterName = reporterName;
}
private HealthCollector(long reportInterval) {
super("HealthCollector");
this.setDaemon(true);
this.reportInterval = reportInterval;
}
public static void init(String reporterName) {
new HealthCollector(reporterName).start();
}
public static HeathReading getCurrentHeathReading(String extraId) {
String id = getId(extraId);
if (!heathReadings.containsKey(id)) {
synchronized (heathReadings) {
if (!heathReadings.containsKey(id)) {
if (heathReadings.keySet().size() > 5000) {
logger.warn("use HealthCollector illegal. There is an overflow trend of Server Health Collector Report Data.");
}else {
heathReadings.put(id, new HeathReading(id));
}
}
}
}
return heathReadings.get(id);
}
private static String getId(String extraId) {
return "T:" + Thread.currentThread().getName() + "(" + Thread.currentThread().getId() + ")" + (extraId == null ? "" : ",extra:" + extraId);
}
@Override
public void run() {
while (true) {
try {
Map<String, HeathReading> heathReadingsSnapshot = heathReadings;
heathReadings = new ConcurrentHashMap<String, HeathReading>();
String[] keyList = heathReadingsSnapshot.keySet().toArray(new String[0]);
Arrays.sort(keyList);
StringBuilder log = new StringBuilder();
log.append("\n---------" + reporterName + " Health Report---------\n");
for (String key : keyList) {
log.append(heathReadingsSnapshot.get(key)).append("\n");
}
log.append("------------------------------------------------\n");
logger.info(log.toString());
try {
Thread.sleep(reportInterval);
} catch (InterruptedException e) {
}
} catch (Throwable t) {
logger.error("HealthCollector report error.", t);
}
}
}
}
package com.a.eye.skywalking.health.report;
import java.util.HashMap;
import java.util.Map;
public class HeathReading {
public static final String ERROR = "[ERROR]";
public static final String WARNING = "[WARNING]";
public static final String INFO = "[INFO]";
private String id;
private Map<String, HeathDetailData> datas = new HashMap<String, HeathDetailData>();
/**
* 健康读数,只应该在工作线程中创建
*/
public HeathReading(String id) {
this.id = id;
}
public void updateData(String key, String message) {
updateData(key, message, new Object[0]);
}
public void updateData(String key, String newData, Object... arguments) {
if (datas.containsKey(key)) {
datas.get(key).updateData(newData, arguments);
} else {
datas.put(key, new HeathDetailData(newData, arguments));
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("id<").append(this.id).append(">\n");
for (Map.Entry<String, HeathDetailData> data : datas.entrySet()) {
sb.append(data.getKey()).append(data.getValue().toString()).append("\n");
}
datas = new HashMap<String, HeathReading.HeathDetailData>();
return sb.toString();
}
class HeathDetailData {
private String data;
private long statusTime;
HeathDetailData(String initialData) {
this(initialData, new Object[0]);
}
HeathDetailData(String initialData, Object[] arguments) {
data = initialData;
if (arguments.length > 0)
data = String.format(initialData, arguments);
statusTime = System.currentTimeMillis();
}
void updateData(String newData, Object... arguments) {
data = newData;
if (arguments.length > 0)
data = String.format(newData, arguments);
statusTime = System.currentTimeMillis();
}
String getData() {
return data;
}
long getStatusTime() {
return statusTime;
}
@Override
public String toString() {
return data + "(t:" + statusTime + ")";
}
}
}
<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>skywalking-commons</artifactId>
<groupId>com.a.eye</groupId>
<version>3.0-2017</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>skywalking-logging</artifactId>
<packaging>pom</packaging>
<name>skywalking-logging</name>
<url>http://maven.apache.org</url>
<modules>
<module>skywalking-logging-api</module>
<module>skywalking-logging-impl-log4j2</module>
</modules>
</project>
<?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>skywalking-logging</artifactId>
<groupId>com.a.eye</groupId>
<version>3.0-2017</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>skywalking-logging-api</artifactId>
</project>
<?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>skywalking-logging</artifactId>
<groupId>com.a.eye</groupId>
<version>3.0-2017</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>skywalking-logging-impl-log4j2</artifactId>
<dependencies>
<dependency>
<groupId>com.a.eye</groupId>
<artifactId>skywalking-logging-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.2</version>
</dependency>
</dependencies>
</project>
package com.a.eye.skywalking.api.logging.impl.log4j2;
import com.a.eye.skywalking.api.logging.api.ILog;
import org.apache.logging.log4j.Logger;
/**
* Created by wusheng on 2016/11/11.
*/
public class Log4j2Logger implements ILog {
private Logger logger;
public Log4j2Logger(Logger logger) {
this.logger = logger;
}
@Override
public void info(String message) {
logger.info(message);
}
@Override
public void info(String message, Object... arguments) {
logger.info(message, arguments);
}
@Override
public void warn(String format, Object... arguments) {
logger.warn(format, arguments);
}
@Override
public void warn(String format, Object arguments, Throwable e) {
logger.warn(format, arguments, e);
}
@Override
public void error(String message, Throwable e) {
logger.error(message, e);
}
@Override
public void error(String message, Object argument, Throwable e) {
logger.error(message, argument, e);
}
@Override
public boolean isDebugEnable() {
return logger.isDebugEnabled();
}
@Override
public boolean isInfoEnable() {
return logger.isInfoEnabled();
}
@Override
public boolean isWarnEnable() {
return logger.isWarnEnabled();
}
@Override
public boolean isErrorEnable() {
return logger.isErrorEnabled();
}
@Override
public void debug(String format) {
logger.debug(format);
}
@Override
public void debug(String format, Object... arguments) {
logger.debug(format, arguments);
}
@Override
public void error(String format) {
logger.error(format);
}
}
package com.a.eye.skywalking.api.logging.impl.log4j2;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogResolver;
import org.apache.logging.log4j.LogManager;
/**
* Created by wusheng on 2016/11/11.
*/
public class Log4j2Resolver implements LogResolver {
@Override
public ILog getLogger(Class<?> clazz) {
return new Log4j2Logger(LogManager.getLogger(clazz));
}
}
......@@ -12,11 +12,6 @@
<artifactId>skywalking-trace</artifactId>
<dependencies>
<dependency>
<groupId>com.a.eye</groupId>
<artifactId>skywalking-logging-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.a.eye</groupId>
<artifactId>skywalking-util</artifactId>
......
......@@ -87,22 +87,40 @@ public class TraceSegment implements ISerializable<SegmentMessage> {
/**
* Establish the link between this segment and its parents.
* When {@param primaryOnly} is true;
* The first time, you {@link #ref(TraceSegmentRef)} to parent, it is affirmed as {@link #primaryRef}.
* And others are affirmed as {@link #refs}.
*
* @param refSegment {@link TraceSegmentRef}
* @param primaryOnly if true, set {@param refSegment} to {@link #primaryRef} only.
*/
public void ref(TraceSegmentRef refSegment) {
if (primaryRef == null) {
primaryRef = refSegment;
} else {
if (refs == null) {
refs = new LinkedList<TraceSegmentRef>();
public void ref(TraceSegmentRef refSegment, boolean primaryOnly) {
if(primaryOnly){
if (primaryRef == null) {
primaryRef = refSegment;
}
}else {
if (primaryRef == null) {
primaryRef = refSegment;
} else {
if (refs == null) {
refs = new LinkedList<TraceSegmentRef>();
}
refs.add(refSegment);
}
refs.add(refSegment);
}
}
/**
* Set to {@link #primaryRef} only,
* based on {@link #ref(TraceSegmentRef, boolean)}
*
* @param refSegment {@link TraceSegmentRef}
*/
public void ref(TraceSegmentRef refSegment){
ref(refSegment, true);
}
/**
* After {@link Span} is finished, as be controller by "skywalking-api" module,
* notify the {@link TraceSegment} to archive it.
......@@ -140,6 +158,9 @@ public class TraceSegment implements ISerializable<SegmentMessage> {
}
public List<TraceSegmentRef> getRefs() {
if(refs == null){
return null;
}
return Collections.unmodifiableList(refs);
}
......
......@@ -7,7 +7,7 @@ import com.a.eye.skywalking.trace.Span;
*
* Created by wusheng on 2017/2/17.
*/
public class BooleanTag extends AbstractTag<Boolean>{
public class BooleanTag extends AbstractTag<Boolean> {
public BooleanTag(String key) {
super(key);
}
......@@ -18,8 +18,8 @@ public class BooleanTag extends AbstractTag<Boolean>{
}
/**
* Get a tag value, type of {@link Boolean}.
* After akka-message/serialize, all tags values are type of {@link String}, convert to {@link Boolean}, if necessary.
* Get a tag value, type of {@link Boolean}. After akka-message/serialize, all tags values are type of {@link
* String}, convert to {@link Boolean}, if necessary.
*
* @param span
* @return tag value
......@@ -27,9 +27,11 @@ public class BooleanTag extends AbstractTag<Boolean>{
@Override
public Boolean get(Span span) {
Object tagValue = span.getTag(super.key);
if(tagValue instanceof Boolean){
if (tagValue == null) {
return null;
} else if (tagValue instanceof Boolean) {
return (Boolean)tagValue;
}else {
} else {
return Boolean.valueOf(tagValue.toString());
}
}
......
......@@ -27,7 +27,9 @@ public class IntTag extends AbstractTag<Integer> {
@Override
public Integer get(Span span) {
Object tagValue = span.getTag(super.key);
if(tagValue instanceof Integer){
if (tagValue == null) {
return null;
} else if(tagValue instanceof Integer){
return (Integer)tagValue;
}else {
return Integer.valueOf(tagValue.toString());
......
......@@ -26,7 +26,9 @@ public class ShortTag extends AbstractTag<Short> {
*/
@Override public Short get(Span span) {
Object tagValue = span.getTag(super.key);
if(tagValue instanceof Short){
if (tagValue == null) {
return null;
} else if(tagValue instanceof Short){
return (Short)tagValue;
}else {
return Short.valueOf(tagValue.toString());
......
......@@ -24,17 +24,17 @@ public class TraceSegmentTestCase {
TraceSegmentRef ref1 = new TraceSegmentRef();
ref1.setTraceSegmentId("parent_trace_0");
ref1.setSpanId(1);
segment.ref(ref1);
segment.ref(ref1, false);
TraceSegmentRef ref2 = new TraceSegmentRef();
ref2.setTraceSegmentId("parent_trace_1");
ref2.setSpanId(5);
segment.ref(ref2);
segment.ref(ref2, false);
TraceSegmentRef ref3 = new TraceSegmentRef();
ref3.setTraceSegmentId("parent_trace_1");
ref3.setSpanId(5);
segment.ref(ref3);
segment.ref(ref3, false);
Assert.assertEquals(ref1, segment.getPrimaryRef());
Assert.assertEquals(ref2, segment.getRefs().get(0));
......@@ -75,21 +75,21 @@ public class TraceSegmentTestCase {
ref1.setSpanId(1);
ref1.setApplicationCode("REMOTE_APP");
ref1.setPeerHost("10.2.3.16:8080");
segment.ref(ref1);
segment.ref(ref1, false);
TraceSegmentRef ref2 = new TraceSegmentRef();
ref2.setTraceSegmentId("parent_trace_1");
ref2.setSpanId(5);
ref2.setApplicationCode("REMOTE_APP");
ref2.setPeerHost("10.2.3.16:8080");
segment.ref(ref2);
segment.ref(ref2, false);
TraceSegmentRef ref3 = new TraceSegmentRef();
ref3.setTraceSegmentId("parent_trace_1");
ref3.setSpanId(5);
ref3.setApplicationCode("REMOTE_APP");
ref3.setPeerHost("10.2.3.16:8080");
segment.ref(ref3);
segment.ref(ref3, false);
Span span1 = new Span(1, "/serviceA");
Tags.SPAN_LAYER.asHttp(span1);
......
......@@ -17,13 +17,20 @@ public final class StringUtil {
}
int length = strings.length - 1;
for (final String s : strings) {
if (s == null) {
continue;
}
length += s.length();
}
final StringBuilder sb = new StringBuilder(length);
sb.append(strings[0]);
if (strings[0] != null) {
sb.append(strings[0]);
}
for (int i = 1; i < strings.length; ++i) {
if (!isEmpty(strings[i])) {
sb.append(delimiter).append(strings[i]);
} else {
sb.append(delimiter);
}
}
return sb.toString();
......
package com.a.eye.skywalking.api.util;
import java.util.Properties;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* Created by wusheng on 2017/2/27.
*/
public class ConfigInitializerTest {
@Test
public void testInitialize() throws IllegalAccessException {
Properties properties = new Properties();
properties.put("Level1Object.strAttr".toLowerCase(), "stringValue");
properties.put("Level1Object.Level2Object.intAttr".toLowerCase(), "1000");
properties.put("Level1Object.Level2Object.longAttr".toLowerCase(), "1000");
properties.put("Level1Object.Level2Object.booleanAttr".toLowerCase(), "true");
ConfigInitializer.initialize(properties, TestPropertiesObject.class);
Assert.assertEquals("stringValue", TestPropertiesObject.Level1Object.strAttr);
Assert.assertEquals(1000, TestPropertiesObject.Level1Object.Level2Object.intAttr);
Assert.assertEquals(1000L, TestPropertiesObject.Level1Object.Level2Object.longAttr);
Assert.assertEquals(true, TestPropertiesObject.Level1Object.Level2Object.booleanAttr);
}
@Test
public void testInitializeWithUnsupportedConfig() throws IllegalAccessException {
Properties properties = new Properties();
properties.put("Level1Object.noExistAttr".toLowerCase(), "stringValue");
ConfigInitializer.initialize(properties, TestPropertiesObject.class);
Assert.assertNull(TestPropertiesObject.Level1Object.strAttr);
}
@Before
public void clear(){
TestPropertiesObject.Level1Object.strAttr = null;
TestPropertiesObject.Level1Object.Level2Object.intAttr = 0;
TestPropertiesObject.Level1Object.Level2Object.longAttr = 0;
TestPropertiesObject.Level1Object.Level2Object.booleanAttr = false;
}
public static class TestPropertiesObject {
public static class Level1Object {
public static String strAttr = null;
public static class Level2Object {
public static int intAttr = 0;
public static long longAttr;
public static boolean booleanAttr;
}
}
}
}
package com.a.eye.skywalking.api.util;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by wusheng on 2017/2/27.
*/
public class StringUtilTest {
@Test
public void testIsEmpty(){
Assert.assertTrue(StringUtil.isEmpty(null));
Assert.assertTrue(StringUtil.isEmpty(""));
Assert.assertFalse(StringUtil.isEmpty(" "));
Assert.assertFalse(StringUtil.isEmpty("A String"));
}
@Test
public void testJoin(){
Assert.assertNull(StringUtil.join('.'));
Assert.assertEquals("Single part.", StringUtil.join('.', "Single part."));
Assert.assertEquals("part1.part2.p3", StringUtil.join('.', "part1", "part2", "p3"));
}
}
......@@ -4,11 +4,11 @@ import com.a.eye.skywalking.agent.junction.SkyWalkingEnhanceMatcher;
import com.a.eye.skywalking.api.conf.Config;
import com.a.eye.skywalking.api.conf.SnifferConfigInitializer;
import com.a.eye.skywalking.api.logging.EasyLogResolver;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.logging.ILog;
import com.a.eye.skywalking.api.logging.LogManager;
import com.a.eye.skywalking.api.plugin.AbstractClassEnhancePluginDefine;
import com.a.eye.skywalking.api.plugin.PluginBootstrap;
import com.a.eye.skywalking.api.plugin.PluginDefineCategory;
import com.a.eye.skywalking.api.plugin.PluginFinder;
import com.a.eye.skywalking.api.plugin.PluginException;
import net.bytebuddy.agent.builder.AgentBuilder;
......@@ -26,8 +26,8 @@ import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.not;
/**
* The main entrance of sky-waking agent.
* It bases on javaagent mechanism.
* The main entrance of sky-waking agent,
* based on javaagent mechanism.
*
* @author wusheng
*/
......@@ -51,11 +51,11 @@ public class SkyWalkingAgent {
initConfig();
final PluginDefineCategory pluginDefineCategory = PluginDefineCategory.category(new PluginBootstrap().loadPlugins());
final PluginFinder pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins());
new AgentBuilder.Default().type(enhanceClassMatcher(pluginDefineCategory).and(not(isInterface()))).transform(new AgentBuilder.Transformer() {
new AgentBuilder.Default().type(enhanceClassMatcher(pluginFinder).and(not(isInterface()))).transform(new AgentBuilder.Transformer() {
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader) {
AbstractClassEnhancePluginDefine pluginDefine = pluginDefineCategory.findPluginDefine(typeDescription.getTypeName());
AbstractClassEnhancePluginDefine pluginDefine = pluginFinder.find(typeDescription.getTypeName());
return pluginDefine.define(typeDescription.getTypeName(), builder);
}
}).with(new AgentBuilder.Listener() {
......@@ -82,12 +82,12 @@ public class SkyWalkingAgent {
/**
* Get the enhance target classes matcher.
*
* @param pluginDefineCategory
* @param pluginFinder
* @param <T>
* @return class matcher.
*/
private static <T extends NamedElement> ElementMatcher.Junction<T> enhanceClassMatcher(PluginDefineCategory pluginDefineCategory) {
return new SkyWalkingEnhanceMatcher<T>(pluginDefineCategory);
private static <T extends NamedElement> ElementMatcher.Junction<T> enhanceClassMatcher(PluginFinder pluginFinder) {
return new SkyWalkingEnhanceMatcher<T>(pluginFinder);
}
private static String generateLocationPath() {
......
package com.a.eye.skywalking.agent.junction;
import com.a.eye.skywalking.api.plugin.PluginDefineCategory;
import com.a.eye.skywalking.api.plugin.PluginFinder;
import net.bytebuddy.description.NamedElement;
/**
......@@ -11,14 +11,14 @@ import net.bytebuddy.description.NamedElement;
*/
public class SkyWalkingEnhanceMatcher<T extends NamedElement> extends AbstractJunction<T> {
private final PluginDefineCategory pluginDefineCategory;
private final PluginFinder pluginFinder;
public SkyWalkingEnhanceMatcher(PluginDefineCategory pluginDefineCategory) {
this.pluginDefineCategory = pluginDefineCategory;
public SkyWalkingEnhanceMatcher(PluginFinder pluginFinder) {
this.pluginFinder = pluginFinder;
}
@Override
public boolean matches(T target) {
return pluginDefineCategory.findPluginDefine(target.getActualName()) != null ? true : false;
return pluginFinder.exist(target.getActualName());
}
}
......@@ -20,7 +20,6 @@
</properties>
<dependencies>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
......@@ -36,16 +35,6 @@
<artifactId>disruptor</artifactId>
<version>3.3.6</version>
</dependency>
<dependency>
<groupId>com.a.eye</groupId>
<artifactId>skywalking-health-report</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.a.eye</groupId>
<artifactId>skywalking-logging-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
......
......@@ -7,5 +7,5 @@ public class Constants {
* This is the version, which will be the first segment of traceid.
* Ref {@link TraceIdGenerator#generate()}
*/
public static String SDK_VERSION = "302017";
public final static String SDK_VERSION = "302017";
}
package com.a.eye.skywalking.api.conf;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.logging.ILog;
import com.a.eye.skywalking.api.logging.LogManager;
import com.a.eye.skywalking.api.util.ConfigInitializer;
import com.a.eye.skywalking.api.util.StringUtil;
......@@ -11,7 +11,7 @@ import java.io.InputStream;
import java.util.Properties;
public class SnifferConfigInitializer {
private static ILog logger = LogManager.getLogger(SnifferConfigInitializer.class);
private static ILog logger = LogManager.getLogger(SnifferConfigInitializer.class);
public static void initialize() {
InputStream configFileStream;
......@@ -32,24 +32,34 @@ public class SnifferConfigInitializer {
logger.error("Failed to read the config file, sky-walking api run in default config.", e);
}
}
Config.SkyWalking.USERNAME = System.getProperty("username");
Config.SkyWalking.APPLICATION_CODE = System.getProperty("applicationCode");
Config.SkyWalking.SERVERS = System.getProperty("servers");
if(StringUtil.isEmpty(Config.SkyWalking.USERNAME)){
String username = System.getProperty("username");
if (!StringUtil.isEmpty(username)) {
Config.SkyWalking.USERNAME = username;
}
String applicationCode = System.getProperty("applicationCode");
if (!StringUtil.isEmpty(applicationCode)) {
Config.SkyWalking.APPLICATION_CODE = applicationCode;
}
String servers = System.getProperty("servers");
if(!StringUtil.isEmpty(servers)) {
Config.SkyWalking.SERVERS = servers;
}
if (StringUtil.isEmpty(Config.SkyWalking.USERNAME)) {
throw new ExceptionInInitializerError("'-Dusername=' is missing.");
}
if(StringUtil.isEmpty(Config.SkyWalking.APPLICATION_CODE)){
if (StringUtil.isEmpty(Config.SkyWalking.APPLICATION_CODE)) {
throw new ExceptionInInitializerError("'-DapplicationCode=' is missing.");
}
if(StringUtil.isEmpty(Config.SkyWalking.SERVERS)){
if (StringUtil.isEmpty(Config.SkyWalking.SERVERS)) {
throw new ExceptionInInitializerError("'-Dservers=' is missing.");
}
}
private static InputStream fetchAuthFileInputStream() {
try {
return new FileInputStream(Config.SkyWalking.AGENT_BASE_PATH + File.separator + "/sky-walking.config");
return new FileInputStream(Config.SkyWalking.AGENT_BASE_PATH + File.separator + "sky-walking.config");
} catch (Exception e) {
logger.warn("sky-walking.config is missing, use default config.");
return null;
......
......@@ -53,6 +53,25 @@ public enum ContextManager implements TracerContextListener {
get().extract(carrier);
}
/**
* @see {@link TracerContext#extract(ContextCarrier)}
*/
public void multiExtract(ContextCarrier carrier){
get().extract(carrier);
}
/**
* @return the {@link TraceSegment#traceSegmentId} if exist. Otherwise, "N/A".
*/
public String getTraceSegmentId(){
TracerContext segment = CONTEXT.get();
if(segment == null){
return "N/A";
}else{
return segment.getTraceSegmentId();
}
}
public Span createSpan(String operationName) {
return get().createSpan(operationName);
}
......
......@@ -88,6 +88,13 @@ public final class TracerContext {
stopSpan(span, System.currentTimeMillis());
}
/**
* @return the current trace segment id.
*/
String getTraceSegmentId(){
return segment.getTraceSegmentId();
}
public void stopSpan(Span span, Long endTime){
Span lastSpan = peek();
if (lastSpan == span) {
......@@ -128,12 +135,30 @@ public final class TracerContext {
* ContextCarrier#deserialize(String)} called.
*/
public void extract(ContextCarrier carrier) {
if(carrier.isValid()) {
this.segment.ref(getRef(carrier));
}
}
/**
* Ref this {@link ContextCarrier} to this {@link TraceSegment}, and support multi-extract for supporting batch process, like MQ.
*
* @param carrier holds the snapshot, if get this {@link ContextCarrier} from remote, make sure {@link
* ContextCarrier#deserialize(String)} called.
*/
public void multiExtract(ContextCarrier carrier){
if(carrier.isValid()) {
this.segment.ref(getRef(carrier), false);
}
}
private TraceSegmentRef getRef(ContextCarrier carrier){
TraceSegmentRef ref = new TraceSegmentRef();
ref.setTraceSegmentId(carrier.getTraceSegmentId());
ref.setSpanId(carrier.getSpanId());
ref.setApplicationCode(carrier.getApplicationCode());
ref.setPeerHost(carrier.getPeerHost());
this.segment.ref(ref);
return ref;
}
/**
......
package com.a.eye.skywalking.api.logging;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogResolver;
/**
* Created by wusheng on 2016/11/26.
*/
......
package com.a.eye.skywalking.api.logging;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.util.LoggingUtil;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
......@@ -34,7 +31,7 @@ public class EasyLogger implements ILog {
}
if (e != null) {
WriterFactory.getLogWriter().writeError(LoggingUtil.fetchThrowableStack(e));
WriterFactory.getLogWriter().writeError(ThrowableFormatter.format(e));
}
}
......@@ -76,18 +73,13 @@ public class EasyLogger implements ILog {
logger(WARN, replaceParam(format, arguments), null);
}
@Override
public void warn(String format, Object arguments, Throwable e) {
logger(WARN, replaceParam(format, arguments), e);
}
@Override
public void error(String format, Throwable e) {
logger(ERROR, format, e);
}
@Override
public void error(String format, Object arguments, Throwable e) {
public void error(Throwable e, String format, Object... arguments) {
logger(ERROR, replaceParam(format, arguments), e);
}
......
package com.a.eye.skywalking.api.logging.api;
package com.a.eye.skywalking.api.logging;
/**
* The Log interface.
......@@ -14,11 +14,9 @@ public interface ILog {
void warn(String format, Object... arguments);
void warn(String format, Object arguments, Throwable e);
void error(String format, Throwable e);
void error(String format, Object arguments, Throwable e);
void error(Throwable e, String format, Object... arguments);
boolean isDebugEnable();
......
package com.a.eye.skywalking.api.logging.api;
package com.a.eye.skywalking.api.logging;
/**
* {@link LogResolver} just do only one thing: return the {@link ILog} implementation.
......
package com.a.eye.skywalking.api.logging.api;
package com.a.eye.skywalking.api.logging;
/**
......@@ -7,8 +7,10 @@ package com.a.eye.skywalking.api.logging.api;
* <p>
* Created by xin on 2016/11/10.
*/
public class NoopLogger implements ILog {
public static final ILog INSTANCE = new NoopLogger();
public enum NoopLogger implements ILog {
INSTANCE {
};
@Override
public void info(String message) {
......@@ -25,20 +27,11 @@ public class NoopLogger implements ILog {
}
@Override
public void warn(String format, Object arguments, Throwable e) {
}
@Override
public void error(String format, Throwable e) {
}
@Override
public void error(String format, Object argument, Throwable e) {
}
@Override
public boolean isDebugEnable() {
return false;
......@@ -73,4 +66,9 @@ public class NoopLogger implements ILog {
public void error(String format) {
}
@Override
public void error(Throwable e, String format, Object... arguments) {
}
}
......@@ -3,7 +3,6 @@ package com.a.eye.skywalking.api.logging;
import com.a.eye.skywalking.api.conf.Config;
import com.a.eye.skywalking.api.util.LoggingUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
......@@ -97,15 +96,15 @@ public class SyncFileWriter implements IWriter {
try {
File file = new File(Config.Logging.LOG_DIR_NAME, Config.Logging.SYSTEM_ERROR_LOG_FILE_NAME);
fileOutputStream = new FileOutputStream(file, true);
fileOutputStream.write(("Failed to init sync File Writer.\n" + LoggingUtil.fetchThrowableStack(e)).getBytes());
fileOutputStream.write(("Failed to init sync File Writer.\n" + ThrowableFormatter.format(e)).getBytes());
} catch (Exception e1) {
System.err.print(LoggingUtil.fetchThrowableStack(e1));
System.err.print(ThrowableFormatter.format(e1));
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e1) {
System.err.print(LoggingUtil.fetchThrowableStack(e1));
System.err.print(ThrowableFormatter.format(e1));
}
}
}
......
package com.a.eye.skywalking.api.util;
package com.a.eye.skywalking.api.logging;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
......@@ -6,8 +6,8 @@ import java.io.IOException;
/**
* Created by xin on 16-6-24.
*/
public class LoggingUtil {
public static String fetchThrowableStack(Throwable e) {
public class ThrowableFormatter {
public static String format(Throwable e) {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
e.printStackTrace(new java.io.PrintWriter(buf, true));
String expMessage = buf.toString();
......
......@@ -3,9 +3,6 @@ package com.a.eye.skywalking.api.logging;
import com.a.eye.skywalking.api.conf.Config;
public class WriterFactory {
private WriterFactory(){
}
public static IWriter getLogWriter(){
if (Config.SkyWalking.IS_PREMAIN_MODE){
return SyncFileWriter.instance();
......
package com.a.eye.skywalking.api.plugin;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.logging.ILog;
import com.a.eye.skywalking.api.logging.LogManager;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassEnhancePluginDefine;
import com.a.eye.skywalking.api.util.StringUtil;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.pool.TypePool;
import net.bytebuddy.pool.TypePool.Resolution;
/**
......@@ -16,6 +17,8 @@ import net.bytebuddy.pool.TypePool.Resolution;
public abstract class AbstractClassEnhancePluginDefine {
private static ILog logger = LogManager.getLogger(AbstractClassEnhancePluginDefine.class);
private TypePool classTypePool;
/**
* Main entrance of enhancing the class.
*
......@@ -40,7 +43,7 @@ public abstract class AbstractClassEnhancePluginDefine {
String[] witnessClasses = witnessClasses();
if (witnessClasses != null) {
for (String witnessClass : witnessClasses) {
Resolution witnessClassResolution = PluginBootstrap.CLASS_TYPE_POOL.describe(witnessClass);
Resolution witnessClassResolution = classTypePool.describe(witnessClass);
if (!witnessClassResolution.isResolved()) {
logger.warn("enhance class {} by plugin {} is not working. Because witness class {} is not existed.", transformClassName, interceptorDefineClassName,
witnessClass);
......@@ -85,4 +88,8 @@ public abstract class AbstractClassEnhancePluginDefine {
protected String[] witnessClasses() {
return new String[] {};
}
public void setClassTypePool(TypePool classTypePool) {
this.classTypePool = classTypePool;
}
}
package com.a.eye.skywalking.api.plugin;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.logging.ILog;
import com.a.eye.skywalking.api.logging.LogManager;
import net.bytebuddy.pool.TypePool;
import java.net.URL;
......@@ -18,32 +18,30 @@ import java.util.List;
public class PluginBootstrap {
private static ILog logger = LogManager.getLogger(PluginBootstrap.class);
public static TypePool CLASS_TYPE_POOL = null;
/**
* load all plugins.
* @return plugin definition list.
*/
public List<AbstractClassEnhancePluginDefine> loadPlugins() {
CLASS_TYPE_POOL = TypePool.Default.ofClassPath();
TypePool classTypePool = TypePool.Default.ofClassPath();
PluginResourcesResolver resolver = new PluginResourcesResolver();
List<URL> resources = resolver.getResources();
if (resources == null || resources.size() == 0) {
logger.info("no plugin files (skywalking-plugin.properties) found, continue to start application.");
return new ArrayList<AbstractClassEnhancePluginDefine>();
return new ArrayList<>();
}
for (URL pluginUrl : resources) {
try {
PluginCfg.CFG.load(pluginUrl.openStream());
PluginCfg.INSTANCE.load(pluginUrl.openStream());
} catch (Throwable t) {
logger.error("plugin [{}] init failure.", new Object[] {pluginUrl}, t);
logger.error(t, "plugin [{}] init failure.", pluginUrl);
}
}
List<String> pluginClassList = PluginCfg.CFG.getPluginClassList();
List<String> pluginClassList = PluginCfg.INSTANCE.getPluginClassList();
List<AbstractClassEnhancePluginDefine> plugins = new ArrayList<AbstractClassEnhancePluginDefine>();
for (String pluginClassName : pluginClassList) {
......@@ -51,9 +49,10 @@ public class PluginBootstrap {
logger.debug("loading plugin class {}.", pluginClassName);
AbstractClassEnhancePluginDefine plugin =
(AbstractClassEnhancePluginDefine) Class.forName(pluginClassName).newInstance();
plugin.setClassTypePool(classTypePool);
plugins.add(plugin);
} catch (Throwable t) {
logger.error("loade plugin [{}] failure.", new Object[] {pluginClassName}, t);
logger.error(t, "loade plugin [{}] failure.", pluginClassName);
}
}
......
......@@ -9,13 +9,11 @@ import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class PluginCfg {
public final static PluginCfg CFG = new PluginCfg();
public enum PluginCfg {
INSTANCE;
private List<String> pluginClassList = new ArrayList<String>();
private PluginCfg(){}
void load(InputStream input) throws IOException{
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
......
......@@ -5,16 +5,15 @@ import java.util.List;
import java.util.Map;
/**
* Just category the plugins.
* Change the store structure from {@link List} to {@link Map}
* The <code>PluginFinder</code> represents a finder , which assist to find the one
* from the given {@link AbstractClassEnhancePluginDefine} list, by name match.
*
* @author wusheng
*/
public class PluginDefineCategory {
public class PluginFinder {
private final Map<String, AbstractClassEnhancePluginDefine> pluginDefineMap = new HashMap<String, AbstractClassEnhancePluginDefine>();
private static PluginDefineCategory pluginDefineCategory;
private final Map<String, AbstractClassEnhancePluginDefine> exactClassEnhancePluginDefineMapping = new HashMap<String, AbstractClassEnhancePluginDefine>();
private PluginDefineCategory(List<AbstractClassEnhancePluginDefine> plugins) {
public PluginFinder(List<AbstractClassEnhancePluginDefine> plugins) {
for (AbstractClassEnhancePluginDefine plugin : plugins) {
String enhanceClassName = plugin.enhanceClassName();
......@@ -22,22 +21,19 @@ public class PluginDefineCategory {
continue;
}
exactClassEnhancePluginDefineMapping.put(enhanceClassName, plugin);
pluginDefineMap.put(enhanceClassName, plugin);
}
}
public static PluginDefineCategory category(List<AbstractClassEnhancePluginDefine> plugins) {
if (pluginDefineCategory == null) {
pluginDefineCategory = new PluginDefineCategory(plugins);
public AbstractClassEnhancePluginDefine find(String enhanceClassName) {
if (pluginDefineMap.containsKey(enhanceClassName)) {
return pluginDefineMap.get(enhanceClassName);
}
return pluginDefineCategory;
}
public AbstractClassEnhancePluginDefine findPluginDefine(String enhanceClassName) {
if (exactClassEnhancePluginDefineMapping.containsKey(enhanceClassName)) {
return exactClassEnhancePluginDefineMapping.get(enhanceClassName);
}
throw new PluginException("Can not find plugin:" + enhanceClassName);
}
return null;
public boolean exist(String enhanceClassName){
return pluginDefineMap.containsKey(enhanceClassName);
}
}
package com.a.eye.skywalking.api.plugin;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.logging.ILog;
import com.a.eye.skywalking.api.logging.LogManager;
import java.io.IOException;
import java.net.URL;
......
package com.a.eye.skywalking.api.plugin;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.logging.ILog;
import com.a.eye.skywalking.api.logging.LogManager;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
......
package com.a.eye.skywalking.api.plugin.bytebuddy;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.ParameterList;
import net.bytebuddy.matcher.ElementMatcher;
/**
......@@ -39,8 +40,9 @@ public class ArgumentTypeNameMatch implements ElementMatcher<MethodDescription>
*/
@Override
public boolean matches(MethodDescription target) {
if (target.getParameters().size() > index) {
return target.getParameters().get(index).getType().asErasure().getName().equals(argumentTypeName);
ParameterList<?> parameters = target.getParameters();
if (parameters.size() > index) {
return parameters.get(index).getType().asErasure().getName().equals(argumentTypeName);
}
return false;
......
package com.a.eye.skywalking.api.plugin.interceptor.enhance;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.logging.ILog;
import com.a.eye.skywalking.api.logging.LogManager;
import com.a.eye.skywalking.api.plugin.interceptor.loader.InterceptorInstanceLoader;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
......
package com.a.eye.skywalking.api.plugin.interceptor.enhance;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.logging.ILog;
import com.a.eye.skywalking.api.logging.LogManager;
import com.a.eye.skywalking.api.plugin.AbstractClassEnhancePluginDefine;
import com.a.eye.skywalking.api.plugin.PluginException;
import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint;
......
package com.a.eye.skywalking.api.plugin.interceptor.enhance;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.logging.ILog;
import com.a.eye.skywalking.api.logging.LogManager;
import com.a.eye.skywalking.api.plugin.interceptor.loader.InterceptorInstanceLoader;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import net.bytebuddy.implementation.bind.annotation.*;
......@@ -55,7 +55,7 @@ public class ClassInstanceMethodsInterceptor {
try {
interceptor.beforeMethod(instanceContext, interceptorContext, result);
} catch (Throwable t) {
logger.error("class[{}] before method[{}] intercept failue:{}", new Object[] {obj.getClass(), method.getName(), t.getMessage()}, t);
logger.error(t,"class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
}
Object ret = null;
......@@ -69,14 +69,14 @@ public class ClassInstanceMethodsInterceptor {
try {
interceptor.handleMethodException(t, instanceContext, interceptorContext);
} catch (Throwable t2) {
logger.error("class[{}] handle method[{}] exception failue:{}", new Object[] {obj.getClass(), method.getName(), t2.getMessage()}, t2);
logger.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
}
throw t;
} finally {
try {
ret = interceptor.afterMethod(instanceContext, interceptorContext, ret);
} catch (Throwable t) {
logger.error("class[{}] after method[{}] intercept failue:{}", new Object[] {obj.getClass(), method.getName(), t.getMessage()}, t);
logger.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
}
}
return ret;
......
package com.a.eye.skywalking.api.plugin.interceptor.enhance;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.logging.ILog;
import com.a.eye.skywalking.api.logging.LogManager;
import com.a.eye.skywalking.api.plugin.interceptor.loader.InterceptorInstanceLoader;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.Origin;
......@@ -55,7 +55,7 @@ public class ClassStaticMethodsInterceptor {
try {
interceptor.beforeMethod(interceptorContext, result);
} catch (Throwable t) {
logger.error("class[{}] before static method[{}] intercept failue:{}", new Object[] {clazz, method.getName(), t.getMessage()}, t);
logger.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName());
}
......@@ -70,14 +70,14 @@ public class ClassStaticMethodsInterceptor {
try {
interceptor.handleMethodException(t, interceptorContext);
} catch (Throwable t2) {
logger.error("class[{}] handle static method[{}] exception failue:{}", new Object[] {clazz, method.getName(), t2.getMessage()}, t2);
logger.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage());
}
throw t;
} finally {
try {
ret = interceptor.afterMethod(interceptorContext, ret);
} catch (Throwable t) {
logger.error("class[{}] after static method[{}] intercept failue:{}", new Object[] {clazz, method.getName(), t.getMessage()}, t);
logger.error(t,"class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage());
}
}
return ret;
......
package com.a.eye.skywalking.api.plugin.interceptor.enhance;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.logging.ILog;
import com.a.eye.skywalking.api.logging.LogManager;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.FieldProxy;
......
package com.a.eye.skywalking.api.plugin.interceptor.loader;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.logging.ILog;
import com.a.eye.skywalking.api.logging.LogManager;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
......
......@@ -3,8 +3,6 @@ package com.a.eye.skywalking.api.queue;
import com.a.eye.skywalking.api.conf.Config;
import com.a.eye.skywalking.api.context.TracerContext;
import com.a.eye.skywalking.api.context.TracerContextListener;
import com.a.eye.skywalking.health.report.HealthCollector;
import com.a.eye.skywalking.health.report.HeathReading;
import com.a.eye.skywalking.trace.TraceSegment;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
......@@ -24,8 +22,6 @@ public enum TraceSegmentProcessQueue implements TracerContextListener {
try {
TraceSegmentHolder data = this.buffer.get(sequence);
data.setValue(traceSegment);
HealthCollector.getCurrentHeathReading("TraceSegmentProcessQueue").updateData(HeathReading.INFO, "receive finished traceSegment.");
} finally {
this.buffer.publish(sequence);
}
......@@ -36,7 +32,7 @@ public enum TraceSegmentProcessQueue implements TracerContextListener {
RingBuffer<TraceSegmentHolder> buffer;
TraceSegmentProcessQueue() {
disruptor = new Disruptor<TraceSegmentHolder>(TraceSegmentHolder.Factory.INSTANCE, Config.Disruptor.BUFFER_SIZE, DaemonThreadFactory.INSTANCE);
disruptor = new Disruptor<>(TraceSegmentHolder.Factory.INSTANCE, Config.Disruptor.BUFFER_SIZE, DaemonThreadFactory.INSTANCE);
buffer = disruptor.getRingBuffer();
}
......
package com.a.eye.skywalking.api.conf;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by wusheng on 2017/2/28.
*/
public class ConstantsTest {
@Test
public void testSDKVersion(){
Assert.assertEquals("302017", Constants.SDK_VERSION);
}
}
package com.a.eye.skywalking.api.conf;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Test;
/**
* @author wusheng
*/
public class SnifferConfigInitializerTest {
@Test
public void testInitialize(){
Config.SkyWalking.IS_PREMAIN_MODE = false;
SnifferConfigInitializer.initialize();
Assert.assertEquals("testUser", Config.SkyWalking.USERNAME);
Assert.assertEquals("crmApp", Config.SkyWalking.APPLICATION_CODE);
Assert.assertEquals("127.0.0.1:8080", Config.SkyWalking.SERVERS);
Assert.assertNotNull(Config.Disruptor.BUFFER_SIZE);
Assert.assertNotNull(Config.Logging.LOG_DIR_NAME);
Assert.assertNotNull(Config.Logging.LOG_FILE_NAME);
Assert.assertNotNull(Config.Logging.MAX_LOG_FILE_LENGTH);
Assert.assertNotNull(Config.Logging.SYSTEM_ERROR_LOG_FILE_NAME);
}
@Test(expected = ExceptionInInitializerError.class)
public void testErrorInitialize(){
Config.SkyWalking.IS_PREMAIN_MODE = true;
SnifferConfigInitializer.initialize();
}
@AfterClass
public static void reset(){
Config.SkyWalking.IS_PREMAIN_MODE = false;
}
}
package com.a.eye.skywalking.api.logging;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by wusheng on 2017/2/28.
*/
public class EasyLogResolverTest {
@Test
public void testGetLogger(){
Assert.assertTrue(new EasyLogResolver().getLogger(EasyLogResolverTest.class) instanceof EasyLogger);
}
}
package com.a.eye.skywalking.api.logging;
import com.a.eye.skywalking.api.conf.Config;
import java.io.PrintStream;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.times;
/**
* Created by wusheng on 2017/2/28.
*/
public class EasyLoggerTest {
private static PrintStream outRef;
private static PrintStream errRef;
@BeforeClass
public static void initAndHoldOut(){
outRef = System.out;
errRef = System.err;
}
@Test
public void testLog(){
Config.SkyWalking.IS_PREMAIN_MODE = false;
PrintStream output = Mockito.mock(PrintStream.class);
System.setOut(output);
PrintStream err = Mockito.mock(PrintStream.class);
System.setErr(err);
EasyLogger logger = new EasyLogger(EasyLoggerTest.class);
Assert.assertTrue(logger.isDebugEnable());
Assert.assertTrue(logger.isInfoEnable());
Assert.assertTrue(logger.isWarnEnable());
Assert.assertTrue(logger.isErrorEnable());
logger.debug("hello world");
logger.debug("hello {}", "world");
logger.info("hello world");
logger.info("hello {}", "world");
logger.warn("hello {}", "world");
logger.warn("hello world");
logger.error("hello world");
logger.error("hello world", new NullPointerException());
logger.error(new NullPointerException(),"hello {}", "world");
Mockito.verify(output,times(4))
.println(anyString());
Mockito.verify(err,times(7))
.println(anyString());
}
@AfterClass
public static void reset(){
System.setOut(outRef);
System.setErr(errRef);
}
}
package com.a.eye.skywalking.api.logging;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.powermock.api.support.membermodification.MemberModifier;
/**
* Created by wusheng on 2017/2/27.
*/
public class LogManagerTest {
@Test
public void testGetLogger() {
final TestLogger logger = new TestLogger();
LogManager.setLogResolver(new LogResolver() {
@Override
public ILog getLogger(Class<?> clazz) {
return logger;
}
});
Assert.assertEquals(logger, LogManager.getLogger(LogManagerTest.class));
}
@Test
public void testGetNoopLogger(){
ILog logger = LogManager.getLogger(LogManagerTest.class);
Assert.assertEquals(NoopLogger.INSTANCE, logger);
}
@Before
@After
public void clear() throws IllegalAccessException {
MemberModifier.field(LogManager.class, "resolver").set(null, null);
}
public class TestLogger implements ILog {
@Override public void info(String format) {
}
@Override public void info(String format, Object... arguments) {
}
@Override public void warn(String format, Object... arguments) {
}
@Override public void error(String format, Throwable e) {
}
@Override public void error(Throwable e, String format, Object... arguments) {
}
@Override public boolean isDebugEnable() {
return false;
}
@Override public boolean isInfoEnable() {
return false;
}
@Override public boolean isWarnEnable() {
return false;
}
@Override public boolean isErrorEnable() {
return false;
}
@Override public void debug(String format) {
}
@Override public void debug(String format, Object... arguments) {
}
@Override public void error(String format) {
}
}
}
package com.a.eye.skywalking.api.logging;
import org.junit.Assert;
import org.junit.Test;
import static com.a.eye.skywalking.api.logging.NoopLogger.INSTANCE;
/**
* Created by wusheng on 2017/2/27.
*/
public class NoopLoggerTest {
@Test
public void testOnNothing(){
Assert.assertFalse(INSTANCE.isDebugEnable());
Assert.assertFalse(INSTANCE.isInfoEnable());
Assert.assertFalse(INSTANCE.isErrorEnable());
Assert.assertFalse(INSTANCE.isWarnEnable());
INSTANCE.debug("Any string");
INSTANCE.debug("Any string", new Object[0]);
INSTANCE.info("Any string");
INSTANCE.info("Any string", new Object[0]);
INSTANCE.warn("Any string", new Object[0]);
INSTANCE.warn("Any string", new Object[0], new NullPointerException());
INSTANCE.error("Any string");
INSTANCE.error("Any string", new NullPointerException());
}
}
package com.a.eye.skywalking.api.logging;
import java.io.PrintStream;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.times;
/**
* Created by wusheng on 2017/2/28.
*/
public class STDOutWriterTest {
private static PrintStream outRef;
private static PrintStream errRef;
@BeforeClass
public static void initAndHoldOut(){
outRef = System.out;
errRef = System.err;
}
@Test
public void testWrite(){
PrintStream mockStream = Mockito.mock(PrintStream.class);
System.setOut(mockStream);
STDOutWriter writer = new STDOutWriter();
writer.write("hello");
Mockito.verify(mockStream,times(1)).println(anyString());
}
@Test
public void testWriteError(){
PrintStream mockStream = Mockito.mock(PrintStream.class);
System.setErr(mockStream);
STDOutWriter writer = new STDOutWriter();
writer.writeError("hello");
Mockito.verify(mockStream,times(1)).println(anyString());
}
@AfterClass
public static void reset(){
System.setOut(outRef);
System.setErr(errRef);
}
}
package com.a.eye.skywalking.api.logging;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by wusheng on 2017/2/28.
*/
public class ThrowableFormatterTest {
@Test
public void testFormat(){
NullPointerException exception = new NullPointerException();
String formatLines = ThrowableFormatter.format(exception);
String[] lines = formatLines.split("\n");
Assert.assertEquals("java.lang.NullPointerException", lines[0]);
Assert.assertEquals("\tat com.a.eye.skywalking.api.logging.ThrowableFormatterTest.testFormat(ThrowableFormatterTest.java:12)", lines[1]);
}
}
package com.a.eye.skywalking.api.logging;
import com.a.eye.skywalking.api.conf.Config;
import java.io.PrintStream;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
/**
* Created by wusheng on 2017/2/28.
*/
public class WriterFactoryTest {
private static PrintStream errRef;
@BeforeClass
public static void initAndHoldOut(){
errRef = System.err;
}
/**
* During this test case,
* reset {@link System#out} to a Mock object, for avoid a console system.error.
*/
@Test
public void testGetLogWriter(){
Config.SkyWalking.IS_PREMAIN_MODE = true;
PrintStream mockStream = Mockito.mock(PrintStream.class);
System.setErr(mockStream);
Assert.assertEquals(SyncFileWriter.instance(), WriterFactory.getLogWriter());
Config.SkyWalking.IS_PREMAIN_MODE = false;
Assert.assertTrue(WriterFactory.getLogWriter() instanceof STDOutWriter);
}
@AfterClass
public static void reset(){
Config.SkyWalking.IS_PREMAIN_MODE = false;
System.setErr(errRef);
}
}
package com.a.eye.skywalking.api.plugin;
import net.bytebuddy.dynamic.DynamicType;
/**
* Created by wusheng on 2017/2/27.
*/
public class MockAbstractClassEnhancePluginDefine extends AbstractClassEnhancePluginDefine {
@Override
protected DynamicType.Builder<?> enhance(String enhanceOriginClassName,
DynamicType.Builder<?> newClassBuilder) throws PluginException {
return newClassBuilder;
}
@Override
protected String enhanceClassName() {
return "NotExistClass";
}
}
package com.a.eye.skywalking.api.plugin;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
/**
* @author wusheng
*/
public class PluginBootstrapTest {
@Test
public void testLoadPlugins(){
PluginBootstrap bootstrap = new PluginBootstrap();
List<AbstractClassEnhancePluginDefine> defines = bootstrap.loadPlugins();
Assert.assertEquals(1, defines.size());
Assert.assertEquals(MockAbstractClassEnhancePluginDefine.class, defines.get(0).getClass());
}
}
package com.a.eye.skywalking.api.plugin;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.powermock.api.support.membermodification.MemberModifier;
/**
* Created by wusheng on 2017/2/27.
*/
public class PluginCfgTest {
@Test
public void testLoad() throws IOException {
String data = "com.test.classA\r\ncom.test.ClassB";
final byte[] dataBytes = data.getBytes();
PluginCfg.INSTANCE.load(new InputStream() {
int index = 0;
@Override
public int read() throws IOException {
if (index == dataBytes.length) {
return -1;
}
return dataBytes[index++];
}
});
List<String> list = PluginCfg.INSTANCE.getPluginClassList();
Assert.assertEquals(2, list.size());
Assert.assertEquals("com.test.classA", list.get(0));
Assert.assertEquals("com.test.ClassB", list.get(1));
}
@Before
@After
public void clear() throws IllegalAccessException {
MemberModifier.field(PluginCfg.class, "pluginClassList").set(PluginCfg.INSTANCE, new ArrayList<String>());
}
}
package com.a.eye.skywalking.api.plugin;
import java.util.ArrayList;
import net.bytebuddy.dynamic.DynamicType;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by wusheng on 2017/2/27.
*/
public class PluginFinderTest {
@Test
public void testFind(){
ArrayList<AbstractClassEnhancePluginDefine> defines = new ArrayList<>();
defines.add(new NewTestPlugin());
defines.add(new NewTestPlugin2());
PluginFinder finder = new PluginFinder(defines);
Assert.assertNotNull(finder.find("test.NewClass"));
Assert.assertTrue(finder.exist("test.NewClass"));
}
@Test(expected = PluginException.class)
public void testCanNotFind(){
ArrayList<AbstractClassEnhancePluginDefine> defines = new ArrayList<>();
defines.add(new NewTestPlugin());
PluginFinder finder = new PluginFinder(defines);
finder.find("test.NewClass2");
}
public class NewTestPlugin extends AbstractClassEnhancePluginDefine{
@Override
protected DynamicType.Builder<?> enhance(String enhanceOriginClassName,
DynamicType.Builder<?> newClassBuilder) throws PluginException {
return newClassBuilder;
}
@Override protected String enhanceClassName() {
return "test.NewClass";
}
}
public class NewTestPlugin2 extends AbstractClassEnhancePluginDefine{
@Override
protected DynamicType.Builder<?> enhance(String enhanceOriginClassName,
DynamicType.Builder<?> newClassBuilder) throws PluginException {
return newClassBuilder;
}
@Override protected String enhanceClassName() {
return null;
}
}
}
package com.a.eye.skywalking.api.plugin;
import org.junit.Assert;
import org.junit.Test;
/**
* @author wusheng
*/
public class PluginResourcesResolverTest {
@Test
public void testGetResources(){
PluginResourcesResolver resolver = new PluginResourcesResolver();
Assert.assertTrue(resolver.getResources().size() > 0);
}
}
package com.a.eye.skywalking.api.plugin.bytebuddy;
import org.junit.Test;
/**
* Created by wusheng on 2017/2/28.
*/
public class AllObjectDefaultMethodsMatchTest {
@Test
public void testMatches(){
}
}
package com.a.eye.skywalking.api.plugin.bytebuddy;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.ParameterDescription;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import static org.mockito.Mockito.when;
/**
* @author wusheng
*/
public class ArgumentTypeNameMatchTest {
@Test
public void testMatches() throws IllegalAccessException {
MethodDescription methodDescription = Mockito.mock(MethodDescription.class, Mockito.RETURNS_DEEP_STUBS);
ParameterDescription parameterDescription = Mockito.mock(ParameterDescription.class, Mockito.RETURNS_DEEP_STUBS);
when(methodDescription.getParameters().get(0)).thenReturn(parameterDescription);
when(methodDescription.getParameters().size()).thenReturn(1);
when(parameterDescription.getType().asErasure().getName()).thenReturn("com.a.eye.TestClass");
ArgumentTypeNameMatch matcher = ((ArgumentTypeNameMatch)ArgumentTypeNameMatch.takesArgumentWithType(0, "com.a.eye.TestClass"));
Assert.assertTrue(matcher.matches(methodDescription));
ArgumentTypeNameMatch matcher2 = ((ArgumentTypeNameMatch)ArgumentTypeNameMatch.takesArgumentWithType(0, "com.a.eye.TestClass2"));
Assert.assertFalse(matcher2.matches(methodDescription));
}
@Test
public void testMatchesWithNoParameters(){
MethodDescription methodDescription = Mockito.mock(MethodDescription.class, Mockito.RETURNS_DEEP_STUBS);
ParameterDescription parameterDescription = Mockito.mock(ParameterDescription.class, Mockito.RETURNS_DEEP_STUBS);
when(methodDescription.getParameters().size()).thenReturn(0);
ArgumentTypeNameMatch matcher2 = ((ArgumentTypeNameMatch)ArgumentTypeNameMatch.takesArgumentWithType(0, "com.a.eye.TestClass"));
Assert.assertFalse(matcher2.matches(methodDescription));
}
}
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d [%t](%F:%L) %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
\ No newline at end of file
skywalking.username = testUser
skywalking.application_code = crmApp
skywalking.servers = 127.0.0.1:8080
TestInterceptorDefine
TestMatcherDefine
com.a.eye.skywalking.api.plugin.MockAbstractClassEnhancePluginDefine
......@@ -27,7 +27,7 @@ import com.alibaba.dubbo.rpc.RpcContext;
*/
public class DubboInterceptor implements InstanceMethodsAroundInterceptor {
public static final String ATTACHMENT_NAME_OF_CONTEXT_DATA = "contextData";
public static final String ATTACHMENT_NAME_OF_CONTEXT_DATA = "SWTraceContext";
public static final String DUBBO_COMPONENT = "Dubbo";
/**
......
......@@ -89,7 +89,7 @@ public class DubboInterceptorTest {
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertConsumerSpan(traceSegment.getSpans().get(0));
testParam.assertSelf("0", "127.0.0.1");
testParam.assertSelf("127.0.0.1");
}
});
}
......
......@@ -14,11 +14,9 @@ public class RequestParamForTestBelow283 extends SWBaseBean {
/**
* This method assert that {@link SWBaseBean#getTraceContext()} if it's not null and context data
* will end with the expect span id.
*
* @param expectSpanId expect span id
*/
public void assertSelf(String expectSpanId, String expectHost) {
public void assertSelf(String expectHost) {
assertNotNull(getTraceContext());
assertThat(getTraceContext(), endsWith(expectSpanId + "|" + expectHost));
assertThat(getTraceContext(), endsWith(expectHost));
}
}
......@@ -23,7 +23,8 @@ import org.apache.http.StatusLine;
* @author zhangxin
*/
public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterceptor {
public static final String HEADER_NAME_OF_CONTEXT_DATA = "SKYWALKING_CONTEXT_DATA";
public static final String HEADER_NAME_OF_CONTEXT_DATA = "SWTraceContext";
private static final String COMPONENT_NAME = "Http";
@Override
public void beforeMethod(EnhancedClassInstanceContext context,
......@@ -40,6 +41,7 @@ public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterc
Tags.PEER_PORT.set(span, httpHost.getPort());
Tags.PEER_HOST.set(span, httpHost.getHostName());
Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT);
Tags.COMPONENT.set(span, COMPONENT_NAME);
Tags.URL.set(span, generateURL(httpHost, httpRequest));
Tags.SPAN_LAYER.asHttp(span);
......@@ -79,6 +81,7 @@ public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterc
@Override
public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext) {
Tags.ERROR.set(ContextManager.INSTANCE.activeSpan(), true);
ContextManager.INSTANCE.activeSpan().log(t);
}
......
package com.a.eye.skywalking.plugin.httpClient.v4;
import com.a.eye.skywalking.api.context.TracerContext;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext;
import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener;
import com.a.eye.skywalking.sniffer.mock.context.SegmentAssert;
import com.a.eye.skywalking.trace.LogData;
import com.a.eye.skywalking.trace.Span;
import com.a.eye.skywalking.trace.TraceSegment;
import com.a.eye.skywalking.trace.tag.Tags;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.RequestLine;
import org.apache.http.StatusLine;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(PowerMockRunner.class)
@PrepareForTest(HttpHost.class)
public class HttpClientExecuteInterceptorTest {
private HttpClientExecuteInterceptor httpClientExecuteInterceptor;
private MockTracerContextListener mockTracerContextListener;
@Mock
private EnhancedClassInstanceContext classInstanceContext;
@Mock
private InstanceMethodInvokeContext instanceMethodInvokeContext;
@Mock
private HttpHost httpHost;
@Mock
private HttpRequest request;
@Mock
private HttpResponse httpResponse;
@Mock
private StatusLine statusLine;
@Before
public void setUp() throws Exception {
mockTracerContextListener = new MockTracerContextListener();
httpClientExecuteInterceptor = new HttpClientExecuteInterceptor();
PowerMockito.mock(HttpHost.class);
when(statusLine.getStatusCode()).thenReturn(200);
when(instanceMethodInvokeContext.allArguments()).thenReturn(new Object[]{httpHost, request});
when(httpResponse.getStatusLine()).thenReturn(statusLine);
when(httpHost.getHostName()).thenReturn("127.0.0.1");
when(httpHost.getSchemeName()).thenReturn("http");
when(request.getRequestLine()).thenReturn(new RequestLine() {
@Override
public String getMethod() {
return "GET";
}
@Override
public ProtocolVersion getProtocolVersion() {
return new ProtocolVersion("http", 1, 1);
}
@Override
public String getUri() {
return "/test-web/test";
}
});
when(httpHost.getPort()).thenReturn(8080);
TracerContext.ListenerManager.add(mockTracerContextListener);
}
@Test
public void testHttpClient() {
httpClientExecuteInterceptor.beforeMethod(classInstanceContext, instanceMethodInvokeContext, null);
httpClientExecuteInterceptor.afterMethod(classInstanceContext, instanceMethodInvokeContext, httpResponse);
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertHttpSpan(traceSegment.getSpans().get(0));
verify(request, times(1)).setHeader(anyString(), anyString());
}
});
}
@Test
public void testStatusCodeNotEquals200() {
when(statusLine.getStatusCode()).thenReturn(500);
httpClientExecuteInterceptor.beforeMethod(classInstanceContext, instanceMethodInvokeContext, null);
httpClientExecuteInterceptor.afterMethod(classInstanceContext, instanceMethodInvokeContext, httpResponse);
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertHttpSpan(traceSegment.getSpans().get(0));
assertThat(Tags.ERROR.get(traceSegment.getSpans().get(0)), is(true));
verify(request, times(1)).setHeader(anyString(), anyString());
}
});
}
@Test
public void testHttpClientWithException() {
httpClientExecuteInterceptor.beforeMethod(classInstanceContext, instanceMethodInvokeContext, null);
httpClientExecuteInterceptor.handleMethodException(new RuntimeException(), classInstanceContext, instanceMethodInvokeContext);
httpClientExecuteInterceptor.afterMethod(classInstanceContext, instanceMethodInvokeContext, httpResponse);
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertHttpSpan(span);
assertThat(Tags.ERROR.get(span), is(true));
assertHttpSpanErrorLog(span.getLogs());
verify(request, times(1)).setHeader(anyString(), anyString());
}
private void assertHttpSpanErrorLog(List<LogData> logs) {
assertThat(logs.size(), is(1));
LogData logData = logs.get(0);
assertThat(logData.getFields().size(), is(4));
}
});
}
private void assertHttpSpan(Span span) {
assertThat(span.getOperationName(), is("/test-web/test"));
assertThat(Tags.COMPONENT.get(span), is("Http"));
assertThat(Tags.PEER_HOST.get(span), is("127.0.0.1"));
assertThat(Tags.PEER_PORT.get(span), is(8080));
assertThat(Tags.URL.get(span), is("http://127.0.0.1:8080/test-web/test"));
assertThat(Tags.SPAN_KIND.get(span), is(Tags.SPAN_KIND_CLIENT));
}
@After
public void tearDown() throws Exception {
TracerContext.ListenerManager.remove(mockTracerContextListener);
}
}
\ No newline at end of file
......@@ -26,6 +26,7 @@ public class CallableStatementTracing {
Tags.DB_TYPE.set(span, "sql");
Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
Tags.DB_STATEMENT.set(span, sql);
Tags.SPAN_LAYER.asDB(span);
Tags.COMPONENT.set(span, connectInfo.getDBType());
if (!StringUtil.isEmpty(connectInfo.getHosts())) {
Tags.PEERS.set(span, connectInfo.getHosts());
......
......@@ -27,6 +27,7 @@ public class ConnectionTracing {
Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
Tags.DB_STATEMENT.set(span, sql);
Tags.COMPONENT.set(span, connectInfo.getDBType());
Tags.SPAN_LAYER.asDB(span);
if (!StringUtil.isEmpty(connectInfo.getHosts())) {
Tags.PEERS.set(span, connectInfo.getHosts());
} else {
......
......@@ -32,6 +32,7 @@ public class PreparedStatementTracing {
Tags.PEER_PORT.set(span, connectInfo.getPort());
Tags.PEER_HOST.set(span, connectInfo.getHost());
}
Tags.SPAN_LAYER.asDB(span);
return exec.exe(realStatement, sql);
} catch (SQLException e) {
Span span = ContextManager.INSTANCE.activeSpan();
......
......@@ -315,4 +315,5 @@ public class SWConnection implements Connection {
return realConnection.getNetworkTimeout();
}
}
......@@ -26,6 +26,7 @@ public class StatementTracing {
Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
Tags.DB_STATEMENT.set(span, sql);
Tags.COMPONENT.set(span, connectInfo.getDBType());
Tags.SPAN_LAYER.asDB(span);
if (!StringUtil.isEmpty(connectInfo.getHosts())) {
Tags.PEERS.set(span, connectInfo.getHosts());
} else {
......
package com.a.eye.skywalking.plugin.jdbc;
import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener;
import com.a.eye.skywalking.trace.LogData;
import com.a.eye.skywalking.trace.Span;
import com.a.eye.skywalking.trace.tag.Tags;
import org.hamcrest.CoreMatchers;
import java.sql.SQLException;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public abstract class AbstractStatementTest {
protected MockTracerContextListener mockTracerContextListener;
protected void assertDBSpanLog(LogData logData) {
assertThat(logData.getFields().size(), is(4));
assertThat(logData.getFields().get("event"), CoreMatchers.<Object>is("error"));
assertEquals(logData.getFields().get("error.kind"), SQLException.class.getName());
assertNull(logData.getFields().get("message"));
}
protected void assertDBSpan(Span span, String exceptOperationName, String exceptDBStatement) {
assertDBSpan(span, exceptOperationName);
assertThat(Tags.DB_STATEMENT.get(span), is(exceptDBStatement));
}
protected void assertDBSpan(Span span, String exceptOperationName) {
assertThat(span.getOperationName(), is(exceptOperationName));
assertThat(Tags.COMPONENT.get(span), is("Mysql"));
assertThat(Tags.DB_INSTANCE.get(span), is("test"));
assertTrue(Tags.SPAN_LAYER.isDB(span));
}
}
package com.a.eye.skywalking.plugin.jdbc;
import com.a.eye.skywalking.api.context.TracerContext;
import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener;
import com.a.eye.skywalking.sniffer.mock.context.SegmentAssert;
import com.a.eye.skywalking.trace.TraceSegment;
import com.mysql.cj.api.jdbc.JdbcConnection;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.util.HashMap;
import java.util.Properties;
import java.util.concurrent.Executor;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class SWConnectionTest extends AbstractStatementTest {
@Mock
private com.mysql.cj.jdbc.PreparedStatement mysqlPreparedStatement;
@Mock
private JdbcConnection jdbcConnection;
@Mock
private Executor executor;
@Mock
private Savepoint savepoint;
private SWConnection swConnection;
private SWConnection multiHostConnection;
@Before
public void setUp() throws Exception {
mockTracerContextListener = new MockTracerContextListener();
swConnection = new SWConnection("jdbc:mysql://127.0.0.1:3306/test", new Properties(), jdbcConnection);
multiHostConnection = new SWConnection("jdbc:mysql://127.0.0.1:3306,127.0.0.1:3309/test", new Properties(), jdbcConnection);
TracerContext.ListenerManager.add(mockTracerContextListener);
when(jdbcConnection.prepareStatement(anyString())).thenReturn(mysqlPreparedStatement);
}
@Test
public void testCommit() throws SQLException {
PreparedStatement preparedStatement = swConnection.prepareStatement("SELECT * FROM test");
swConnection.commit();
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/commit");
}
});
}
@Test
public void testMultiHostCommit() throws SQLException {
PreparedStatement preparedStatement = swConnection.prepareStatement("SELECT * FROM test", new String[]{"1"});
multiHostConnection.commit();
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/commit");
}
});
}
@Test(expected = SQLException.class)
public void testCommitWithException() throws SQLException {
PreparedStatement preparedStatement = swConnection.prepareStatement("SELECT * FROM test", new int[]{1});
doThrow(new SQLException()).when(jdbcConnection).commit();
try {
swConnection.commit();
} finally {
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/commit");
assertDBSpanLog(traceSegment.getSpans().get(0).getLogs().get(0));
}
});
}
}
@Test
public void testRollBack() throws SQLException {
PreparedStatement preparedStatement = swConnection.prepareStatement("SELECT * FROM test", 1, 1);
swConnection.rollback();
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/rollback");
}
});
}
@Test
public void testMultiHostRollBack() throws SQLException {
PreparedStatement preparedStatement = swConnection.prepareStatement("SELECT * FROM test", 1, 1, 1);
multiHostConnection.rollback();
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/rollback");
}
});
}
@Test(expected = SQLException.class)
public void testRollBackWithException() throws SQLException {
doThrow(new SQLException()).when(jdbcConnection).rollback();
swConnection.rollback();
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/rollback");
}
});
}
@Test
public void testRollBackWithSavePoint() throws SQLException {
swConnection.rollback(savepoint);
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/rollback to savepoint");
}
});
}
@Test
public void testMultiHostRollBackWithSavePoint() throws SQLException {
multiHostConnection.rollback(savepoint);
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/rollback to savepoint");
}
});
}
@Test(expected = SQLException.class)
public void testRollBackWithSavePointWithException() throws SQLException {
doThrow(new SQLException()).when(jdbcConnection).rollback(any(Savepoint.class));
swConnection.rollback(savepoint);
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/rollback to savepoint");
assertDBSpanLog(traceSegment.getSpans().get(0).getLogs().get(0));
}
});
}
@Test
public void testClose() throws SQLException {
swConnection.close();
swConnection.clearWarnings();
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/close");
}
});
}
@Test
public void testMultiHostClose() throws SQLException {
multiHostConnection.close();
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/close");
}
});
}
@Test(expected = SQLException.class)
public void testCloseWithException() throws SQLException {
doThrow(new SQLException()).when(jdbcConnection).close();
swConnection.close();
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/close");
assertDBSpanLog(traceSegment.getSpans().get(0).getLogs().get(0));
}
});
}
@Test
public void testReleaseSavePoint() throws SQLException {
swConnection.releaseSavepoint(savepoint);
swConnection.clearWarnings();
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/releaseSavepoint savepoint");
}
});
}
@Test
public void testMultiHostReleaseSavePoint() throws SQLException {
multiHostConnection.releaseSavepoint(savepoint);
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/releaseSavepoint savepoint");
}
});
}
@Test(expected = SQLException.class)
public void testReleaseSavePointWithException() throws SQLException {
doThrow(new SQLException()).when(jdbcConnection).releaseSavepoint(any(Savepoint.class));
swConnection.releaseSavepoint(savepoint);
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/releaseSavepoint savepoint");
assertDBSpanLog(traceSegment.getSpans().get(0).getLogs().get(0));
}
});
}
@Test
public void testSetConfig() throws SQLException {
swConnection.createArrayOf("1", new Object[0]);
swConnection.createBlob();
swConnection.createClob();
swConnection.createNClob();
swConnection.createSQLXML();
swConnection.nativeSQL("SELECT IT");
swConnection.setAutoCommit(true);
swConnection.getAutoCommit();
swConnection.setCatalog("test");
swConnection.getCatalog();
swConnection.setClientInfo(new Properties());
swConnection.getClientInfo();
swConnection.setHoldability(1);
swConnection.getHoldability();
swConnection.setReadOnly(false);
swConnection.setClientInfo("test-client", "test-client");
swConnection.getClientInfo("test");
swConnection.setSavepoint();
swConnection.getMetaData();
swConnection.getTransactionIsolation();
swConnection.getTypeMap();
swConnection.getWarnings();
swConnection.isClosed();
swConnection.isReadOnly();
swConnection.isValid(10);
swConnection.setSavepoint("test");
swConnection.setTransactionIsolation(1);
swConnection.setTypeMap(new HashMap<String, Class<?>>());
verify(jdbcConnection, times(1)).createBlob();
verify(jdbcConnection, times(1)).createClob();
verify(jdbcConnection, times(1)).createNClob();
verify(jdbcConnection, times(1)).createSQLXML();
verify(jdbcConnection, times(1)).nativeSQL(anyString());
verify(jdbcConnection, times(1)).setAutoCommit(anyBoolean());
verify(jdbcConnection, times(1)).getAutoCommit();
verify(jdbcConnection, times(1)).setCatalog(anyString());
verify(jdbcConnection, times(1)).getCatalog();
verify(jdbcConnection, times(1)).setClientInfo(anyString(), anyString());
verify(jdbcConnection, times(1)).setHoldability(anyInt());
verify(jdbcConnection, times(1)).getHoldability();
verify(jdbcConnection, times(1)).setReadOnly(anyBoolean());
verify(jdbcConnection, times(1)).getClientInfo();
verify(jdbcConnection, times(1)).getClientInfo(anyString());
verify(jdbcConnection, times(1)).setSavepoint(anyString());
verify(jdbcConnection, times(1)).setSavepoint();
verify(jdbcConnection, times(1)).getMetaData();
verify(jdbcConnection, times(1)).getTransactionIsolation();
verify(jdbcConnection, times(1)).getTypeMap();
verify(jdbcConnection, times(1)).getWarnings();
verify(jdbcConnection, times(1)).setTransactionIsolation(anyInt());
verify(jdbcConnection, times(1)).getTransactionIsolation();
verify(jdbcConnection, times(1)).isClosed();
verify(jdbcConnection, times(1)).isReadOnly();
verify(jdbcConnection, times(1)).isValid(anyInt());
verify(jdbcConnection, times(1)).setTypeMap(any(HashMap.class));
}
@After
public void tearDown() throws Exception {
TracerContext.ListenerManager.remove(mockTracerContextListener);
}
}
\ No newline at end of file
package com.a.eye.skywalking.plugin.jdbc;
import com.a.eye.skywalking.api.context.TracerContext;
import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener;
import com.a.eye.skywalking.sniffer.mock.context.SegmentAssert;
import com.a.eye.skywalking.trace.LogData;
import com.a.eye.skywalking.trace.Span;
import com.a.eye.skywalking.trace.TraceSegment;
import com.a.eye.skywalking.trace.tag.Tags;
import com.mysql.cj.api.jdbc.JdbcConnection;
import org.hamcrest.CoreMatchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.net.MalformedURLException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class SWStatementTest extends AbstractStatementTest {
@Mock
private com.mysql.cj.jdbc.StatementImpl mysqlStatement;
@Mock
private JdbcConnection jdbcConnection;
private SWConnection swConnection;
private SWConnection multiHostConnection;
@Before
public void setUp() throws Exception {
mockTracerContextListener = new MockTracerContextListener();
swConnection = new SWConnection("jdbc:mysql://127.0.0.1:3306/test", new Properties(), jdbcConnection);
multiHostConnection = new SWConnection("jdbc:mysql://127.0.0.1:3306,127.0.0.1:3309/test", new Properties(), jdbcConnection);
TracerContext.ListenerManager.add(mockTracerContextListener);
when(jdbcConnection.createStatement()).thenReturn(mysqlStatement);
when(jdbcConnection.createStatement(anyInt(), anyInt())).thenReturn(mysqlStatement);
when(jdbcConnection.createStatement(anyInt(), anyInt(), anyInt())).thenReturn(mysqlStatement);
}
@Test
public void testPreparedStatementConfig() throws SQLException {
Statement statement = swConnection.createStatement();
statement.cancel();
statement.getUpdateCount();
statement.setFetchDirection(1);
statement.getFetchDirection();
statement.getResultSetConcurrency();
statement.getResultSetType();
statement.isClosed();
statement.setPoolable(false);
statement.isPoolable();
statement.getWarnings();
statement.clearWarnings();
statement.setCursorName("test");
statement.setMaxFieldSize(11);
statement.getMaxFieldSize();
statement.setMaxRows(10);
statement.getMaxRows();
statement.setEscapeProcessing(true);
statement.setFetchSize(1);
statement.getFetchSize();
statement.setQueryTimeout(1);
statement.getQueryTimeout();
Connection connection = statement.getConnection();
statement.execute("SELECT * FROM test");
statement.getMoreResults();
statement.getMoreResults(1);
statement.getResultSetHoldability();
statement.getResultSet();
statement.close();
verify(mysqlStatement, times(1)).getUpdateCount();
verify(mysqlStatement, times(1)).getMoreResults();
verify(mysqlStatement, times(1)).setFetchDirection(anyInt());
verify(mysqlStatement, times(1)).getFetchDirection();
verify(mysqlStatement, times(1)).getResultSetType();
verify(mysqlStatement, times(1)).isClosed();
verify(mysqlStatement, times(1)).setPoolable(anyBoolean());
verify(mysqlStatement, times(1)).getWarnings();
verify(mysqlStatement, times(1)).clearWarnings();
verify(mysqlStatement, times(1)).setCursorName(anyString());
verify(mysqlStatement, times(1)).setMaxFieldSize(anyInt());
verify(mysqlStatement, times(1)).getMaxFieldSize();
verify(mysqlStatement, times(1)).setMaxRows(anyInt());
verify(mysqlStatement, times(1)).getMaxRows();
verify(mysqlStatement, times(1)).setEscapeProcessing(anyBoolean());
verify(mysqlStatement, times(1)).getResultSetConcurrency();
verify(mysqlStatement, times(1)).getResultSetConcurrency();
verify(mysqlStatement, times(1)).getResultSetType();
verify(mysqlStatement, times(1)).getMoreResults(anyInt());
verify(mysqlStatement, times(1)).setFetchSize(anyInt());
verify(mysqlStatement, times(1)).getFetchSize();
verify(mysqlStatement, times(1)).getQueryTimeout();
verify(mysqlStatement, times(1)).setQueryTimeout(anyInt());
verify(mysqlStatement, times(1)).getResultSet();
assertThat(connection, CoreMatchers.<Connection>is(swConnection));
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertDBSpan(span, "JDBC/Statement/execute", "SELECT * FROM test");
}
});
}
@Test
public void testExecuteWithAutoGeneratedKey() throws SQLException {
Statement statement = swConnection.createStatement(1, 1);
boolean executeSuccess = statement.execute("SELECT * FROM test", 1);
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertDBSpan(span, "JDBC/Statement/execute", "SELECT * FROM test");
}
});
}
@Test
public void testExecuteQuery() throws SQLException {
Statement statement = swConnection.createStatement(1, 1, 1);
ResultSet executeSuccess = statement.executeQuery("SELECT * FROM test");
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertDBSpan(span, "JDBC/Statement/executeQuery", "SELECT * FROM test");
}
});
}
@Test
public void testExecuteUpdate() throws SQLException {
Statement statement = swConnection.createStatement(1, 1, 1);
int executeSuccess = statement.executeUpdate("UPDATE test SET a = 1");
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertDBSpan(span, "JDBC/Statement/executeUpdate", "UPDATE test SET a = 1");
}
});
}
@Test
public void testExecuteUpdateWithAutoGeneratedKey() throws SQLException {
Statement statement = swConnection.createStatement(1, 1, 1);
int executeSuccess = statement.executeUpdate("UPDATE test SET a = 1", 1);
statement.getGeneratedKeys();
verify(mysqlStatement, times(1)).getGeneratedKeys();
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertDBSpan(span, "JDBC/Statement/executeUpdate", "UPDATE test SET a = 1");
}
});
}
@Test
public void testExecuteUpdateWithColumnIndexes() throws SQLException {
Statement statement = swConnection.createStatement(1, 1, 1);
int executeSuccess = statement.executeUpdate("UPDATE test SET a = 1", new int[]{1});
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertDBSpan(span, "JDBC/Statement/executeUpdate", "UPDATE test SET a = 1");
}
});
}
@Test
public void testExecuteUpdateWithColumnStringIndexes() throws SQLException {
Statement statement = swConnection.createStatement(1, 1, 1);
int executeSuccess = statement.executeUpdate("UPDATE test SET a = 1", new String[]{"1"});
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertDBSpan(span, "JDBC/Statement/executeUpdate", "UPDATE test SET a = 1");
}
});
}
@Test
public void testExecuteWithColumnIndexes() throws SQLException {
Statement statement = swConnection.createStatement(1, 1, 1);
boolean executeSuccess = statement.execute("UPDATE test SET a = 1", new int[]{1});
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertDBSpan(span, "JDBC/Statement/execute", "UPDATE test SET a = 1");
}
});
}
@Test
public void testExecuteWithColumnStringIndexes() throws SQLException {
Statement statement = swConnection.createStatement(1, 1, 1);
boolean executeSuccess = statement.execute("UPDATE test SET a = 1", new String[]{"1"});
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertDBSpan(span, "JDBC/Statement/execute", "UPDATE test SET a = 1");
}
});
}
@Test
public void testBatch() throws SQLException, MalformedURLException {
Statement statement = multiHostConnection.createStatement();
statement.addBatch("UPDATE test SET a = 1 WHERE b = 2");
int[] resultSet = statement.executeBatch();
statement.clearBatch();
verify(mysqlStatement, times(1)).executeBatch();
verify(mysqlStatement, times(1)).addBatch(anyString());
verify(mysqlStatement, times(1)).clearBatch();
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertDBSpan(span, "JDBC/Statement/executeBatch", "");
}
});
}
@Test(expected = SQLException.class)
public void testMultiHostWithException() throws SQLException {
when(mysqlStatement.execute(anyString())).thenThrow(new SQLException());
try {
Statement statement = multiHostConnection.createStatement();
statement.execute("UPDATE test SET a = 1 WHERE b = 2");
} finally {
verify(mysqlStatement, times(1)).execute(anyString());
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertDBSpan(span, "JDBC/Statement/execute", "UPDATE test SET a = 1 WHERE b = 2");
assertThat(span.getLogs().size(), is(1));
assertDBSpanLog(span.getLogs().get(0));
}
});
}
}
@After
public void tearDown() throws Exception {
TracerContext.ListenerManager.remove(mockTracerContextListener);
}
}
\ No newline at end of file
......@@ -22,7 +22,7 @@ public class JedisClusterConstructorWithHostAndPortArgInterceptor implements Ins
public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) {
StringBuilder redisConnInfo = new StringBuilder();
HostAndPort hostAndPort = (HostAndPort) interceptorContext.allArguments()[0];
redisConnInfo.append(hostAndPort.toString()).append(";");
redisConnInfo.append(hostAndPort.toString());
context.set(KEY_OF_REDIS_CONN_INFO, redisConnInfo.toString());
context.set(KEY_OF_REDIS_HOST, hostAndPort.getHost());
context.set(KEY_OF_REDIS_PORT, hostAndPort.getPort());
......
......@@ -23,6 +23,6 @@ public class JedisClusterConstructorWithListHostAndPortArgInterceptor implements
redisConnInfo.append(hostAndPort.toString()).append(";");
}
context.set(JedisMethodInterceptor.KEY_OF_REDIS_CONN_INFO, redisConnInfo.toString());
context.set(JedisMethodInterceptor.KEY_OF_REDIS_HOSTS, redisConnInfo);
context.set(JedisMethodInterceptor.KEY_OF_REDIS_HOSTS, redisConnInfo.toString());
}
}
......@@ -46,11 +46,17 @@ public class JedisMethodInterceptor extends NoCocurrencyAceessObject {
this.whenEnter(context, new Runnable() {
@Override
public void run() {
Span span = ContextManager.INSTANCE.createSpan(context.get(KEY_OF_REDIS_CONN_INFO, String.class) + " " + interceptorContext.methodName());
Span span = ContextManager.INSTANCE.createSpan("Jedis/" + interceptorContext.methodName());
Tags.COMPONENT.set(span, REDIS_COMPONENT);
Tags.DB_TYPE.set(span, REDIS_COMPONENT);
tagPeer(span, context);
Tags.SPAN_LAYER.asDB(span);
if (StringUtil.isEmpty(context.get(KEY_OF_REDIS_HOST, String.class))) {
Tags.PEERS.set(span, String.valueOf(context.get(KEY_OF_REDIS_HOSTS)));
} else {
Tags.PEER_HOST.set(span, context.get(KEY_OF_REDIS_HOST, String.class));
Tags.PEER_PORT.set(span, (Integer) context.get(KEY_OF_REDIS_PORT));
}
if (interceptorContext.allArguments().length > 0
&& interceptorContext.allArguments()[0] instanceof String) {
......
package com.a.eye.skywalking.plugin.jedis.v2;
import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.ConstructorInvokeContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.powermock.modules.junit4.PowerMockRunner;
import redis.clients.jedis.HostAndPort;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_CONN_INFO;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_HOST;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_PORT;
import static org.junit.Assert.*;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class JedisClusterConstructorWithHostAndPortArgInterceptorTest {
private JedisClusterConstructorWithHostAndPortArgInterceptor interceptor;
@Mock
private EnhancedClassInstanceContext instanceContext;
@Mock
private ConstructorInvokeContext invokeContext;
@Before
public void setUp() throws Exception {
interceptor = new JedisClusterConstructorWithHostAndPortArgInterceptor();
when(invokeContext.allArguments()).thenReturn(new Object[]{new HostAndPort("127.0.0.1", 6379)});
}
@After
public void tearDown() throws Exception {
}
@Test
public void onConstruct() throws Exception {
interceptor.onConstruct(instanceContext, invokeContext);
verify(instanceContext, times(1)).set(KEY_OF_REDIS_CONN_INFO, "127.0.0.1:6379");
verify(instanceContext, times(1)).set(KEY_OF_REDIS_HOST, "127.0.0.1");
verify(instanceContext, times(1)).set(KEY_OF_REDIS_PORT, 6379);
}
}
\ No newline at end of file
package com.a.eye.skywalking.plugin.jedis.v2;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.ConstructorInvokeContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.HashSet;
import java.util.Set;
import redis.clients.jedis.HostAndPort;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_CONN_INFO;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_HOSTS;
import static org.hamcrest.core.Is.is;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.contains;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class JedisClusterConstructorWithListHostAndPortArgInterceptorTest {
private JedisClusterConstructorWithListHostAndPortArgInterceptor interceptor;
@Mock
private EnhancedClassInstanceContext instanceContext;
@Mock
private ConstructorInvokeContext invokeContext;
private Set<HostAndPort> hostAndPortSet;
@Before
public void setUp() throws Exception {
hostAndPortSet = new HashSet<HostAndPort>();
interceptor = new JedisClusterConstructorWithListHostAndPortArgInterceptor();
hostAndPortSet.add(new HostAndPort("127.0.0.1", 6379));
hostAndPortSet.add(new HostAndPort("127.0.0.1", 16379));
when(invokeContext.allArguments()).thenReturn(new Object[]{hostAndPortSet});
}
@After
public void tearDown() throws Exception {
}
@Test
public void onConstruct() throws Exception {
interceptor.onConstruct(instanceContext, invokeContext);
verify(instanceContext, times(1)).set(eq(KEY_OF_REDIS_CONN_INFO), contains("127.0.0.1:6379;"));
verify(instanceContext, times(1)).set(eq(KEY_OF_REDIS_HOSTS), contains("127.0.0.1:16379;"));
}
}
\ No newline at end of file
package com.a.eye.skywalking.plugin.jedis.v2;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.ConstructorInvokeContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.util.ShardInfo;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_CONN_INFO;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_HOST;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_PORT;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class JedisConstructorWithShardInfoArgInterceptorTest {
private JedisConstructorWithShardInfoArgInterceptor interceptor;
@Mock
private EnhancedClassInstanceContext instanceContext;
@Mock
private ConstructorInvokeContext invokeContext;
@Before
public void setUp() throws Exception {
interceptor = new JedisConstructorWithShardInfoArgInterceptor();
when(invokeContext.allArguments()).thenReturn(new Object[]{new JedisShardInfo("127.0.0.1", 6379)});
}
@After
public void tearDown() throws Exception {
}
@Test
public void onConstruct() throws Exception {
interceptor.onConstruct(instanceContext, invokeContext);
verify(instanceContext, times(1)).set(KEY_OF_REDIS_CONN_INFO, "127.0.0.1:6379");
verify(instanceContext, times(1)).set(KEY_OF_REDIS_HOST, "127.0.0.1");
verify(instanceContext, times(1)).set(KEY_OF_REDIS_PORT, 6379);
}
}
\ No newline at end of file
package com.a.eye.skywalking.plugin.jedis.v2;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.ConstructorInvokeContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_CONN_INFO;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_HOST;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_PORT;
import static org.junit.Assert.*;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class JedisConstructorWithStringArgInterceptorTest {
private JedisConstructorWithStringArgInterceptor interceptor;
@Mock
private EnhancedClassInstanceContext instanceContext;
@Mock
private ConstructorInvokeContext invokeContext;
@Before
public void setUp() throws Exception {
interceptor = new JedisConstructorWithStringArgInterceptor();
when(invokeContext.allArguments()).thenReturn(new Object[]{"127.0.0.1"});
}
@Test
public void onConstruct() throws Exception {
interceptor.onConstruct(instanceContext, invokeContext);
verify(instanceContext, times(1)).set(KEY_OF_REDIS_CONN_INFO, "127.0.0.1:6379");
verify(instanceContext, times(1)).set(KEY_OF_REDIS_HOST, "127.0.0.1");
verify(instanceContext, times(1)).set(KEY_OF_REDIS_PORT, 6379);
}
@Test
public void onConstructWithPort(){
when(invokeContext.allArguments()).thenReturn(new Object[]{"127.0.0.1", 16379});
interceptor.onConstruct(instanceContext, invokeContext);
verify(instanceContext, times(1)).set(KEY_OF_REDIS_CONN_INFO, "127.0.0.1:16379");
verify(instanceContext, times(1)).set(KEY_OF_REDIS_HOST, "127.0.0.1");
verify(instanceContext, times(1)).set(KEY_OF_REDIS_PORT, 16379);
}
}
\ No newline at end of file
package com.a.eye.skywalking.plugin.jedis.v2;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.ConstructorInvokeContext;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.net.URI;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_CONN_INFO;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_HOST;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_PORT;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(PowerMockRunner.class)
@PrepareForTest(URI.class)
public class JedisConstructorWithUriArgInterceptorTest {
private JedisConstructorWithUriArgInterceptor interceptor;
@Mock
private EnhancedClassInstanceContext instanceContext;
@Mock
private ConstructorInvokeContext invokeContext;
private URI uri = URI.create("http://127.0.0.1:6379");
@Before
public void setUp() throws Exception {
interceptor = new JedisConstructorWithUriArgInterceptor();
when(invokeContext.allArguments()).thenReturn(new Object[]{uri});
}
@Test
public void onConstruct() throws Exception {
interceptor.onConstruct(instanceContext, invokeContext);
verify(instanceContext, times(1)).set(KEY_OF_REDIS_CONN_INFO, "127.0.0.1:6379");
verify(instanceContext, times(1)).set(KEY_OF_REDIS_HOST, "127.0.0.1");
verify(instanceContext, times(1)).set(KEY_OF_REDIS_PORT, 6379);
}
}
\ No newline at end of file
package com.a.eye.skywalking.plugin.jedis.v2;
import com.a.eye.skywalking.api.context.TracerContext;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext;
import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener;
import com.a.eye.skywalking.sniffer.mock.context.SegmentAssert;
import com.a.eye.skywalking.trace.LogData;
import com.a.eye.skywalking.trace.Span;
import com.a.eye.skywalking.trace.TraceSegment;
import com.a.eye.skywalking.trace.tag.Tags;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.sql.SQLException;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_HOST;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_HOSTS;
import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_PORT;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class JedisMethodInterceptorTest {
private JedisMethodInterceptor interceptor;
private MockTracerContextListener mockTracerContextListener;
@Mock
private EnhancedClassInstanceContext classInstanceContext;
@Mock
private InstanceMethodInvokeContext methodInvokeContext;
@Before
public void setUp() throws Exception {
interceptor = new JedisMethodInterceptor();
mockTracerContextListener = new MockTracerContextListener();
TracerContext.ListenerManager.add(mockTracerContextListener);
when(classInstanceContext.get(KEY_OF_REDIS_HOST, String.class)).thenReturn("127.0.0.1");
when(classInstanceContext.get(KEY_OF_REDIS_PORT)).thenReturn(6379);
when(methodInvokeContext.methodName()).thenReturn("set");
when(methodInvokeContext.allArguments()).thenReturn(new Object[]{"OperationKey"});
when(classInstanceContext.isContain("__$invokeCounterKey")).thenReturn(true);
}
@Test
public void testIntercept() {
when(classInstanceContext.get("__$invokeCounterKey", Integer.class)).thenReturn(0);
interceptor.beforeMethod(classInstanceContext, methodInvokeContext, null);
when(classInstanceContext.get("__$invokeCounterKey", Integer.class)).thenReturn(1);
interceptor.afterMethod(classInstanceContext, methodInvokeContext, null);
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertRedisSpan(span);
}
});
}
@Test
public void testInterceptWithMultiHost() {
when(classInstanceContext.get("__$invokeCounterKey", Integer.class)).thenReturn(0);
when(classInstanceContext.get(KEY_OF_REDIS_HOST, String.class)).thenReturn(null);
when(classInstanceContext.get(KEY_OF_REDIS_HOSTS)).thenReturn("127.0.0.1:6379;127.0.0.1:16379;");
interceptor.beforeMethod(classInstanceContext, methodInvokeContext, null);
when(classInstanceContext.get("__$invokeCounterKey", Integer.class)).thenReturn(1);
interceptor.afterMethod(classInstanceContext, methodInvokeContext, null);
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertRedisSpan(span, "127.0.0.1:6379;127.0.0.1:16379;");
}
});
}
@Test
public void testInterceptWithException() {
when(classInstanceContext.get("__$invokeCounterKey", Integer.class)).thenReturn(0);
interceptor.beforeMethod(classInstanceContext, methodInvokeContext, null);
interceptor.handleMethodException(new RuntimeException(), classInstanceContext, methodInvokeContext);
when(classInstanceContext.get("__$invokeCounterKey", Integer.class)).thenReturn(1);
interceptor.afterMethod(classInstanceContext, methodInvokeContext, null);
mockTracerContextListener.assertSize(1);
mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertRedisSpan(span);
assertThat(span.getLogs().size(),is(1));
assertLogData(span.getLogs().get(0));
}
});
}
private void assertLogData(LogData logData) {
MatcherAssert.assertThat(logData.getFields().size(), is(4));
MatcherAssert.assertThat(logData.getFields().get("event"), CoreMatchers.<Object>is("error"));
assertEquals(logData.getFields().get("error.kind"), RuntimeException.class.getName());
assertNull(logData.getFields().get("message"));
}
private void assertRedisSpan(Span span) {
assertThat(span.getOperationName(), is("Jedis/set"));
assertThat(Tags.PEER_HOST.get(span), is("127.0.0.1"));
assertThat(Tags.PEER_PORT.get(span), is(6379));
assertThat(Tags.COMPONENT.get(span), is("Redis"));
assertThat(Tags.DB_STATEMENT.get(span), is("set OperationKey"));
assertThat(Tags.DB_TYPE.get(span), is("Redis"));
assertTrue(Tags.SPAN_LAYER.isDB(span));
}
private void assertRedisSpan(Span span, String exceptedPeerHosts){
assertThat(span.getOperationName(), is("Jedis/set"));
assertThat(Tags.PEERS.get(span), is(exceptedPeerHosts));
assertThat(Tags.COMPONENT.get(span), is("Redis"));
assertThat(Tags.DB_STATEMENT.get(span), is("set OperationKey"));
assertThat(Tags.DB_TYPE.get(span), is("Redis"));
assertTrue(Tags.SPAN_LAYER.isDB(span));
}
@After
public void tearDown() throws Exception {
TracerContext.ListenerManager.remove(mockTracerContextListener);
}
}
\ No newline at end of file
......@@ -29,7 +29,7 @@ public class MotanConsumerInvokeInterceptor implements InstanceMethodsAroundInte
/**
* Attachment key of the serialized context data.
*/
private static final String ATTACHMENT_KEY_OF_CONTEXT_DATA = "contextData";
private static final String ATTACHMENT_KEY_OF_CONTEXT_DATA = "SWTraceContext";
/**
* Motan component
......
......@@ -8,6 +8,7 @@ import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorIn
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult;
import com.a.eye.skywalking.api.util.StringUtil;
import com.a.eye.skywalking.trace.Span;
import com.a.eye.skywalking.trace.tag.Tags;
import com.weibo.api.motan.rpc.Request;
......@@ -33,7 +34,7 @@ public class MotanProviderInterceptor implements InstanceConstructorInterceptor,
/**
* The {@link Request#getAttachments()} key. It maps to the serialized {@link ContextCarrier}.
*/
private static final String ATTACHMENT_KEY_OF_CONTEXT_DATA = "contextData";
private static final String ATTACHMENT_KEY_OF_CONTEXT_DATA = "SWTraceContext";
/**
* Motan component
*/
......@@ -50,7 +51,7 @@ public class MotanProviderInterceptor implements InstanceConstructorInterceptor,
URL url = (URL) context.get(KEY_NAME_OF_REQUEST_URL);
if (url != null) {
com.weibo.api.motan.rpc.Request request = (com.weibo.api.motan.rpc.Request) interceptorContext.allArguments()[0];
Span span = ContextManager.INSTANCE.createSpan(generateViewPoint(url, request));
Span span = ContextManager.INSTANCE.createSpan(generateViewPoint(request));
Tags.COMPONENT.set(span, MOTAN_COMPONENT);
Tags.URL.set(span, url.getIdentity());
Tags.PEER_PORT.set(span, url.getPort());
......@@ -59,7 +60,9 @@ public class MotanProviderInterceptor implements InstanceConstructorInterceptor,
Tags.SPAN_LAYER.asRPCFramework(span);
String serializedContextData = request.getAttachments().get(ATTACHMENT_KEY_OF_CONTEXT_DATA);
ContextManager.INSTANCE.extract(new ContextCarrier().deserialize(serializedContextData));
if (!StringUtil.isEmpty(serializedContextData)) {
ContextManager.INSTANCE.extract(new ContextCarrier().deserialize(serializedContextData));
}
}
}
......@@ -72,6 +75,7 @@ public class MotanProviderInterceptor implements InstanceConstructorInterceptor,
Tags.ERROR.set(span, true);
span.log(response.getException());
}
ContextManager.INSTANCE.stopSpan();
return ret;
}
......@@ -82,8 +86,8 @@ public class MotanProviderInterceptor implements InstanceConstructorInterceptor,
}
private static String generateViewPoint(URL serviceURI, Request request) {
StringBuilder viewPoint = new StringBuilder(serviceURI.getUri());
private static String generateViewPoint(Request request) {
StringBuilder viewPoint = new StringBuilder(request.getInterfaceName());
viewPoint.append("." + request.getMethodName());
viewPoint.append("(" + request.getParamtersDesc() + ")");
return viewPoint.toString();
......
package com.a.eye.skywalking.plugin.motan;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext;
import com.weibo.api.motan.rpc.URL;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class MotanConsumerFetchRequestURLInterceptorTest {
private MotanConsumerFetchRequestURLInterceptor requestURLInterceptor;
@Mock
private EnhancedClassInstanceContext instanceContext;
@Mock
private InstanceMethodInvokeContext interceptorContext;
private URL url;
@Before
public void setUp() {
requestURLInterceptor = new MotanConsumerFetchRequestURLInterceptor();
url = URL.valueOf("motan://127.0.0.0.1:34000/com.a.eye.skywalking.test.TestService");
when(interceptorContext.allArguments()).thenReturn(new Object[]{url});
}
@Test
public void testFetchRequestURL() {
requestURLInterceptor.beforeMethod(instanceContext, interceptorContext, null);
requestURLInterceptor.afterMethod(instanceContext, interceptorContext, null);
verify(instanceContext, times(1)).set(Matchers.any(), Matchers.any());
}
@Test
public void testFetchRequestURLWithException(){
requestURLInterceptor.beforeMethod(instanceContext, interceptorContext, null);
requestURLInterceptor.handleMethodException(new RuntimeException(), instanceContext, interceptorContext);
requestURLInterceptor.afterMethod(instanceContext, interceptorContext, null);
verify(instanceContext, times(1)).set(Matchers.any(), Matchers.any());
}
}
\ No newline at end of file
package com.a.eye.skywalking.plugin.motan;
import com.a.eye.skywalking.api.context.TracerContext;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext;
import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener;
import com.a.eye.skywalking.sniffer.mock.context.SegmentAssert;
import com.a.eye.skywalking.trace.LogData;
import com.a.eye.skywalking.trace.Span;
import com.a.eye.skywalking.trace.TraceSegment;
import com.a.eye.skywalking.trace.tag.Tags;
import com.weibo.api.motan.rpc.Request;
import com.weibo.api.motan.rpc.Response;
import com.weibo.api.motan.rpc.URL;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class MotanConsumerInvokeInterceptorTest {
private MockTracerContextListener contextListener;
private MotanConsumerInvokeInterceptor invokeInterceptor;
@Mock
private EnhancedClassInstanceContext instanceContext;
@Mock
private InstanceMethodInvokeContext interceptorContext;
@Mock
private Response response;
@Mock
private Request request;
private URL url;
@Before
public void setUp() {
contextListener = new MockTracerContextListener();
invokeInterceptor = new MotanConsumerInvokeInterceptor();
url = URL.valueOf("motan://127.0.0.1:34000/com.a.eye.skywalking.test.TestService");
TracerContext.ListenerManager.add(contextListener);
when(instanceContext.get("REQUEST_URL")).thenReturn(url);
when(interceptorContext.allArguments()).thenReturn(new Object[]{request});
when(request.getMethodName()).thenReturn("test");
when(request.getInterfaceName()).thenReturn("com.a.eye.skywalking.test.TestService");
when(request.getParamtersDesc()).thenReturn("java.lang.String, java.lang.Object");
}
@Test
public void testInvokeInterceptor() {
invokeInterceptor.beforeMethod(instanceContext, interceptorContext, null);
invokeInterceptor.afterMethod(instanceContext, interceptorContext, response);
contextListener.assertSize(1);
contextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertMotanConsumerSpan(span);
verify(request, times(1)).setAttachment(anyString(), anyString());
}
});
}
@Test
public void testResponseWithException() {
when(response.getException()).thenReturn(new RuntimeException());
invokeInterceptor.beforeMethod(instanceContext, interceptorContext, null);
invokeInterceptor.afterMethod(instanceContext, interceptorContext, response);
contextListener.assertSize(1);
assertTraceSegmentWhenOccurException();
}
private void assertTraceSegmentWhenOccurException() {
contextListener.assertTraceSegment(0, new SegmentAssert() {
@Override
public void call(TraceSegment traceSegment) {
assertThat(traceSegment.getSpans().size(), is(1));
Span span = traceSegment.getSpans().get(0);
assertMotanConsumerSpan(span);
verify(request, times(1)).setAttachment(anyString(), anyString());
assertThat(span.getLogs().size(), is(1));
LogData logData = span.getLogs().get(0);
assertLogData(logData);
}
});
}
@Test
public void testInvokeInterceptorWithException() {
invokeInterceptor.beforeMethod(instanceContext, interceptorContext, null);
invokeInterceptor.handleMethodException(new RuntimeException(), instanceContext, interceptorContext);
invokeInterceptor.afterMethod(instanceContext, interceptorContext, response);
contextListener.assertSize(1);
assertTraceSegmentWhenOccurException();
}
private void assertLogData(LogData logData) {
assertThat(logData.getFields().size(), is(4));
MatcherAssert.assertThat(logData.getFields().get("event"), CoreMatchers.<Object>is("error"));
MatcherAssert.assertThat(logData.getFields().get("error.kind"), CoreMatchers.<Object>is(RuntimeException.class.getName()));
assertNull(logData.getFields().get("message"));
}
private void assertMotanConsumerSpan(Span span) {
assertThat(span.getOperationName(), is("com.a.eye.skywalking.test.TestService.test(java.lang.String, java.lang.Object)"));
assertThat(Tags.COMPONENT.get(span), is("Motan"));
assertThat(Tags.SPAN_KIND.get(span), is(Tags.SPAN_KIND_CLIENT));
assertThat(Tags.PEER_HOST.get(span), is("127.0.0.1"));
assertThat(Tags.PEER_PORT.get(span), is(34000));
assertTrue(Tags.SPAN_LAYER.isRPCFramework(span));
assertThat(Tags.URL.get(span), is("motan://127.0.0.1:34000/default_rpc/com.a.eye.skywalking.test.TestService/1.0/service"));
}
@After
public void tearDown() {
TracerContext.ListenerManager.remove(contextListener);
}
}
\ No newline at end of file
......@@ -22,7 +22,7 @@ public class TomcatInterceptor implements InstanceMethodsAroundInterceptor {
/**
* Header name that the serialized context data stored in {@link HttpServletRequest#getHeader(String)}.
*/
public static final String HEADER_NAME_OF_CONTEXT_DATA = "SKYWALKING_CONTEXT_DATA";
public static final String HEADER_NAME_OF_CONTEXT_DATA = "SWTraceContext";
/**
* Tomcat component.
*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册