diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptor.java index 860be92f4f319a3c9f6c7f48157582bfe9edff01..9851d1d47507d0b6ed9887020f1ea9c5f1860953 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptor.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptor.java @@ -24,6 +24,7 @@ import org.apache.http.StatusLine; */ public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterceptor { public static final String HEADER_NAME_OF_CONTEXT_DATA = "SKYWALKING_CONTEXT_DATA"; + 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); } diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/test/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptorTest.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/test/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..82e2a1d42659615a6094e41841b5e4ad3aa204a5 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/test/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptorTest.java @@ -0,0 +1,166 @@ +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 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