
com.undefinedlabs.scope.rules.OkHttp3ClientScopeAgentRuleInterceptor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scope-rule-okhttp3 Show documentation
Show all versions of scope-rule-okhttp3 Show documentation
Scope is a APM for tests to give engineering teams unprecedented visibility into their CI process to quickly
identify, troubleshoot and fix failed builds.
This artifact contains the classes to instrument OkHttp3 library.
package com.undefinedlabs.scope.rules;
import com.undefinedlabs.scope.ScopeGlobalTracer;
import com.undefinedlabs.scope.events.EventFieldsFactory;
import com.undefinedlabs.scope.events.exception.ThrowableEvent;
import com.undefinedlabs.scope.rules.headers.OkHttp3HeadersAdapter;
import com.undefinedlabs.scope.rules.http.HttpHeadersExtractorForSpan;
import com.undefinedlabs.scope.rules.propagation.carriers.RequestBuilderInjectAdapter;
import com.undefinedlabs.scope.sender.internal.HttpSender;
import com.undefinedlabs.scope.settings.ScopeSettings;
import com.undefinedlabs.scope.settings.ScopeSettingsResolver;
import com.undefinedlabs.scope.utils.ScopeIOUtils;
import com.undefinedlabs.scope.utils.SpanUtils;
import com.undefinedlabs.scope.utils.StacktraceUtils;
import com.undefinedlabs.scope.utils.StringUtils;
import com.undefinedlabs.scope.utils.event.EventValues;
import com.undefinedlabs.scope.utils.sourcecode.ExceptionSourceCodeFactory;
import com.undefinedlabs.scope.utils.sourcecode.ExceptionSourceCodeFrame;
import com.undefinedlabs.scope.utils.tag.TagKeys;
import com.undefinedlabs.scope.utils.tag.TagValues;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import okio.Buffer;
public class OkHttp3ClientScopeAgentRuleInterceptor {
public static final Interceptor SCOPE_OKHTTP_INTERCEPTOR =
new Interceptor() {
@Override
public Response intercept(final Chain chain) throws IOException {
if (HttpSender.SCOPE_JAVA_USER_AGENT.equals(chain.request().header("User-Agent"))) {
return chain.proceed(chain.request());
}
final Tracer tracer = ScopeGlobalTracer.get();
final Request request = chain.request();
final Span previousActiveSpan = tracer.activeSpan();
// If there is no previousActiveSpan, it is not created Span Client.
if (previousActiveSpan == null) {
return chain.proceed(request);
}
final String operationName = String.format("HTTP %s", request.method());
final Span span =
tracer
.buildSpan(operationName)
.withTag(TagKeys.COMPONENT, TagValues.Component.HTTP)
.withTag(TagKeys.SPAN_KIND, TagValues.Network.SPAN_KIND_CLIENT)
.withTag(TagKeys.Network.HTTP_URL, request.url().toString())
.withTag(TagKeys.Network.HTTP_METHOD, request.method())
.withTag(TagKeys.Network.PEER_HOSTNAME, request.url().host())
.withTag(TagKeys.Network.PEER_PORT, request.url().port())
.withTag(TagKeys.Network.PEER_SERVICE, TagValues.Network.Service.HTTP)
.start();
SpanUtils.INSTANCE.setTagObject(
span,
TagKeys.Network.HTTP_REQUEST_HEADERS,
HttpHeadersExtractorForSpan.DEFAULT.extract(
new OkHttp3HeadersAdapter(request.headers())));
if ((boolean)
ScopeSettingsResolver.INSTANCE
.get()
.getSetting(ScopeSettings.SCOPE_INSTRUMENTATION_HTTP_STACKTRACE)) {
SpanUtils.INSTANCE.setTagObject(
span,
TagKeys.Stacktrace.STACKTRACE,
StacktraceUtils.INSTANCE.createStackTraceFields(
Thread.currentThread().getStackTrace()));
}
if ((boolean)
ScopeSettingsResolver.INSTANCE
.get()
.getSetting(ScopeSettings.SCOPE_INSTRUMENTATION_HTTP_PAYLOADS)) {
if ("GET".equalsIgnoreCase(request.method())) {
span.setTag(TagKeys.Network.HTTP_REQUEST_PAYLOAD, "");
} else {
if (request.body() != null) {
final Buffer buffer = new Buffer();
request.body().writeTo(buffer);
span.setTag(
TagKeys.Network.HTTP_REQUEST_PAYLOAD,
ScopeIOUtils.getSubstring(buffer.inputStream()));
} else {
span.setTag(TagKeys.Network.HTTP_REQUEST_PAYLOAD, "");
}
}
} else {
span.setTag(
TagKeys.Network.HTTP_REQUEST_PAYLOAD_UNAVAILABLE,
TagValues.Network.HTTP_PAYLOAD_DISABLED);
}
final Request.Builder requestBuilder = chain.request().newBuilder();
final Scope scope = tracer.activateSpan(span);
tracer.inject(
span.context(),
Format.Builtin.HTTP_HEADERS,
new RequestBuilderInjectAdapter(requestBuilder));
try {
final Request newRequest = requestBuilder.build();
final Response response = chain.proceed(newRequest);
if ((boolean)
ScopeSettingsResolver.INSTANCE
.get()
.getSetting(ScopeSettings.SCOPE_INSTRUMENTATION_HTTP_PAYLOADS)) {
if (response.body() != null) {
if (response.body().byteStream() != null
&& response.body().byteStream().markSupported()) {
final String responseStr =
ScopeIOUtils.getSubstring(response.body().byteStream());
span.setTag(
TagKeys.Network.HTTP_RESPONSE_PAYLOAD,
(StringUtils.isNotEmpty(responseStr) ? responseStr : null));
span.setTag(
TagKeys.Network.HTTP_RESPONSE_PAYLOAD_UNAVAILABLE,
(StringUtils.isNotEmpty(responseStr)
? null
: TagValues.Network.HTTP_PAYLOAD_NOT_ACCESSIBLE));
} else {
span.setTag(
TagKeys.Network.HTTP_RESPONSE_PAYLOAD_UNAVAILABLE,
TagValues.Network.HTTP_PAYLOAD_NOT_ACCESSIBLE);
}
} else {
span.setTag(TagKeys.Network.HTTP_RESPONSE_PAYLOAD, "");
}
} else {
span.setTag(
TagKeys.Network.HTTP_RESPONSE_PAYLOAD_UNAVAILABLE,
TagValues.Network.HTTP_PAYLOAD_DISABLED);
}
SpanUtils.INSTANCE.setTagObject(
span,
TagKeys.Network.HTTP_RESPONSE_HEADERS,
HttpHeadersExtractorForSpan.DEFAULT.extract(
new OkHttp3HeadersAdapter(response.headers())));
span.setTag(TagKeys.Network.HTTP_STATUS_CODE, response.code());
return response;
} catch (final Throwable throwable) {
span.setTag(TagKeys.ERROR, true);
final ExceptionSourceCodeFrame exceptionSourceCodeFrame =
ExceptionSourceCodeFactory.INSTANCE.createFrame(throwable);
final ThrowableEvent.Builder throwableEventBuilder = ThrowableEvent.newBuilder();
throwableEventBuilder
.withEventType(EventValues.General.ERROR)
.withThrowable(exceptionSourceCodeFrame.getUserThrowable())
.withSource(
exceptionSourceCodeFrame.getSourceCodeFrame().getLinkPathWithMethodLine());
span.log(EventFieldsFactory.INSTANCE.createFields(throwableEventBuilder.build()));
throw throwable;
} finally {
span.finish();
scope.close();
}
}
};
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy