tech.mhuang.pacebox.springboot.autoconfiguration.trace.rest.TraceRestTemplateInterceptor Maven / Gradle / Ivy
The newest version!
package tech.mhuang.pacebox.springboot.autoconfiguration.trace.rest;
import io.micrometer.tracing.Span;
import io.micrometer.tracing.Tracer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import tech.mhuang.pacebox.springboot.core.jackson.JsonUtil;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
/**
* restTemplate埋点
*
* @author mhuang
* @since 1.0.0
*/
@Slf4j
public class TraceRestTemplateInterceptor implements ClientHttpRequestInterceptor {
private final Tracer tracer;
private final Pattern skipPattern;
private final List spanDecorators;
public TraceRestTemplateInterceptor(Tracer tracer, Pattern skipPattern) {
this.tracer = tracer;
this.skipPattern = skipPattern;
this.spanDecorators = Collections.singletonList(new TraceRestTemplateSpanDecorator());
}
protected boolean isTraced(HttpRequest httpRequest) {
// skip URLs matching skip pattern
// e.g. pattern is defined as '/health|/status' then URL 'http://localhost:5000/context/health' won't be traced
if (skipPattern != null) {
String url = httpRequest.getURI().toString();
return skipPattern.matcher(url).matches();
}
return false;
}
@Override
public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
if (isTraced(httpRequest)) {
return execution.execute(httpRequest, body);
}
ClientHttpResponse httpResponse;
Span span = tracer.nextSpan().name("restTemplate");
span.tag("request.body", new String(body));
span.tag("request.param", httpRequest.getURI().getQuery() == null ?
""
:
httpRequest.getURI().getQuery());
span.tag("request.header", JsonUtil.toString(httpRequest.getHeaders()));
for (TraceRestTemplateSpanDecorator spanDecorator : spanDecorators) {
try {
spanDecorator.onRequest(httpRequest, span);
} catch (RuntimeException exDecorator) {
log.error("Exception during decorating span", exDecorator);
}
}
try (Tracer.SpanInScope ws = this.tracer.withSpan(span.start())) {
httpResponse = execution.execute(httpRequest, body);
for (TraceRestTemplateSpanDecorator spanDecorator : spanDecorators) {
try {
spanDecorator.onResponse(httpResponse, span);
span.event("restTemplateEnd");
} catch (RuntimeException exDecorator) {
log.error("Exception during decorating span", exDecorator);
}
}
} catch (Exception ex) {
for (TraceRestTemplateSpanDecorator spanDecorator : spanDecorators) {
try {
spanDecorator.onError(httpRequest, ex, span);
} catch (RuntimeException exDecorator) {
log.error("Exception during decorating span", exDecorator);
}
}
throw ex;
} finally {
span.end();
}
return httpResponse;
}
}