package org.skywalking.apm.plugin.httpClient.v4;
import org.apache.http.*;
import org.skywalking.apm.agent.core.context.ContextCarrier;
import org.skywalking.apm.agent.core.context.ContextManager;
import org.skywalking.apm.agent.core.plugin.interceptor.EnhancedClassInstanceContext;
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodInvokeContext;
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.skywalking.apm.trace.Span;
import org.skywalking.apm.trace.tag.Tags;
import java.net.MalformedURLException;
import java.net.URL;
/**
* {@link HttpClientExecuteInterceptor} transport the trace context by call {@link HttpRequest#setHeader(Header)},
* The current span tag the {@link Tags#ERROR} if {@link StatusLine#getStatusCode()} is not equals 200.
*
* @author zhangxin
*/
public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterceptor {
public static final String HEADER_NAME_OF_CONTEXT_DATA = "SWTraceContext";
private static final String COMPONENT_NAME = "HttpClient";
@Override
public void beforeMethod(EnhancedClassInstanceContext context,
InstanceMethodInvokeContext interceptorContext, MethodInterceptResult result) {
Object[] allArguments = interceptorContext.allArguments();
if (allArguments[0] == null || allArguments[1] == null) {
// illegal args, can't trace. ignore.
return;
}
HttpHost httpHost = (HttpHost) allArguments[0];
HttpRequest httpRequest = (HttpRequest) allArguments[1];
Span span = createSpan(httpRequest);
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(httpRequest));
Tags.SPAN_LAYER.asHttp(span);
ContextCarrier contextCarrier = new ContextCarrier();
ContextManager.inject(contextCarrier);
httpRequest.setHeader(HEADER_NAME_OF_CONTEXT_DATA, contextCarrier.serialize());
}
/**
* Format request URL.
*
* @return request URL
*/
private String generateURL(HttpRequest httpRequest) {
return httpRequest.getRequestLine().getUri();
}
/**
* Create span.
*/
private Span createSpan(HttpRequest httpRequest) {
Span span;
try {
URL url = new URL(httpRequest.getRequestLine().getUri());
span = ContextManager.createSpan(url.getPath());
} catch (MalformedURLException e) {
span = ContextManager.createSpan(httpRequest.getRequestLine().getUri());
}
return span;
}
@Override
public Object afterMethod(EnhancedClassInstanceContext context,
InstanceMethodInvokeContext interceptorContext, Object ret) {
Object[] allArguments = interceptorContext.allArguments();
if (allArguments[0] == null || allArguments[1] == null) {
return ret;
}
HttpResponse response = (HttpResponse) ret;
int statusCode = response.getStatusLine().getStatusCode();
Span span = ContextManager.activeSpan();
if (statusCode != 200) {
Tags.ERROR.set(span, true);
}
Tags.STATUS_CODE.set(span, statusCode);
ContextManager.stopSpan();
return ret;
}
@Override
public void handleMethodException(Throwable t, EnhancedClassInstanceContext context,
InstanceMethodInvokeContext interceptorContext) {
Tags.ERROR.set(ContextManager.activeSpan(), true);
ContextManager.activeSpan().log(t);
}
}