start to move instrumenting code to s-c-s-core
This commit is contained in:
@@ -42,6 +42,21 @@
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.hystrix</groupId>
|
||||
<artifactId>hystrix-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.reactivex</groupId>
|
||||
<artifactId>rxjava</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.springframework.cloud.sleuth.slf4j;
|
||||
|
||||
import static org.springframework.cloud.sleuth.slf4j.Slf4jSpanStartListener.SPAN_ID_NAME;
|
||||
import static org.springframework.cloud.sleuth.trace.Trace.SPAN_ID_NAME;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
package org.springframework.cloud.sleuth.slf4j;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.cloud.sleuth.trace.Span;
|
||||
import org.springframework.cloud.sleuth.trace.SpanStartListener;
|
||||
import org.springframework.cloud.sleuth.trace.Trace;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Slf4j
|
||||
public class Slf4jSpanStartListener implements SpanStartListener {
|
||||
//TODO: Where to put span id name?
|
||||
public static final String SPAN_ID_NAME = "Span-Id";
|
||||
|
||||
@Override
|
||||
public void startSpan(Span span) {
|
||||
//TODO: what log level?
|
||||
log.info("Starting span with id: [{}]", span.getSpanId());
|
||||
MDC.put(SPAN_ID_NAME, span.getSpanId());
|
||||
MDC.put(Trace.SPAN_ID_NAME, span.getSpanId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,9 @@ package org.springframework.cloud.sleuth.trace;
|
||||
*/
|
||||
public interface Trace {
|
||||
|
||||
String SPAN_ID_NAME = "Span-Id";
|
||||
String TRACE_ID_NAME = "Trace-Id";
|
||||
|
||||
/**
|
||||
* Creates a new trace scope.
|
||||
* <p/>
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.springframework.cloud.sleuth.trace.intercept.circuitbreaker;
|
||||
|
||||
import com.netflix.hystrix.HystrixCommand;
|
||||
import com.netflix.hystrix.HystrixCommandGroupKey;
|
||||
import com.netflix.hystrix.HystrixThreadPoolKey;
|
||||
import org.springframework.cloud.sleuth.trace.Trace;
|
||||
import org.springframework.cloud.sleuth.trace.TraceScope;
|
||||
|
||||
/**
|
||||
* Abstraction over {@code HystrixCommand} that wraps command execution with Trace setting
|
||||
*
|
||||
* @see HystrixCommand
|
||||
* @see CorrelationIdUpdater
|
||||
*
|
||||
* @author Tomasz Nurkiewicz, 4financeIT
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public abstract class TraceCommand<R> extends HystrixCommand<R> {
|
||||
|
||||
private Trace trace;
|
||||
|
||||
protected TraceCommand(Trace trace, HystrixCommandGroupKey group) {
|
||||
super(group);
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
protected TraceCommand(Trace trace, HystrixCommandGroupKey group, HystrixThreadPoolKey threadPool) {
|
||||
super(group, threadPool);
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
protected TraceCommand(Trace trace, HystrixCommandGroupKey group, int executionIsolationThreadTimeoutInMilliseconds) {
|
||||
super(group, executionIsolationThreadTimeoutInMilliseconds);
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
protected TraceCommand(Trace trace, HystrixCommandGroupKey group, HystrixThreadPoolKey threadPool, int executionIsolationThreadTimeoutInMilliseconds) {
|
||||
super(group, threadPool, executionIsolationThreadTimeoutInMilliseconds);
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
protected TraceCommand(Trace trace, Setter setter) {
|
||||
super(setter);
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected R run() throws Exception {
|
||||
TraceScope scope = trace.startSpan(getCommandKey().name());
|
||||
try {
|
||||
return doRun();
|
||||
} finally {
|
||||
scope.close();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract R doRun() throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.springframework.cloud.sleuth.trace.intercept.scheduling;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.cloud.sleuth.trace.Trace;
|
||||
import org.springframework.cloud.sleuth.trace.TraceScope;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
/**
|
||||
* Aspect that sets correlationId for running threads executing methods annotated with {@link Scheduled} annotation.
|
||||
* For every execution of scheduled method a new, i.e. unique one, value of correlationId will be set.
|
||||
*
|
||||
* @author Tomasz Nurkewicz, 4financeIT
|
||||
* @author Michal Chmielarz, 4financeIT
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @see org.springframework.cloud.sleuth.trace.Trace
|
||||
*/
|
||||
@Aspect
|
||||
public class TraceSchedulingAspect {
|
||||
|
||||
private final Trace trace;
|
||||
|
||||
public TraceSchedulingAspect(Trace trace) {
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
@Around("execution (@org.springframework.scheduling.annotation.Scheduled * *.*(..))")
|
||||
public Object setNewCorrelationIdOnThread(final ProceedingJoinPoint pjp) throws Throwable {
|
||||
TraceScope scope = trace.startSpan(pjp.toShortString());
|
||||
try {
|
||||
return pjp.proceed();
|
||||
} finally {
|
||||
scope.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.springframework.cloud.sleuth.trace.intercept.scheduling;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
|
||||
import org.springframework.cloud.sleuth.trace.Trace;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
* Registers beans related to task scheduling.
|
||||
*
|
||||
* @see TraceSchedulingAspect
|
||||
*
|
||||
* @author Michal Chmielarz, 4financeIT
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
@EnableAspectJAutoProxy
|
||||
public class TraceSchedulingAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public TraceSchedulingAspect traceSchedulingAspect(Trace trace) {
|
||||
return new TraceSchedulingAspect(trace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.sleuth.trace.intercept.web;
|
||||
|
||||
import static org.springframework.cloud.sleuth.trace.Trace.SPAN_ID_NAME;
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Collections;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.cloud.sleuth.trace.MilliSpan;
|
||||
import org.springframework.cloud.sleuth.trace.Span;
|
||||
import org.springframework.cloud.sleuth.trace.Trace;
|
||||
import org.springframework.cloud.sleuth.trace.TraceScope;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
* Filter that takes the value of the {@link CorrelationIdHolder#CORRELATION_ID_HEADER}
|
||||
* header from either request or response and sets it in the {@link CorrelationIdHolder}.
|
||||
* It also provides that value in {@link MDC} logging related class so that logger prints
|
||||
* the value of correlation id at each log.
|
||||
*
|
||||
* @see Trace
|
||||
* @see MDC
|
||||
*
|
||||
* @author Jakub Nabrdalik, 4financeIT
|
||||
* @author Tomasz Nurkiewicz, 4financeIT
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class TraceFilter extends OncePerRequestFilter {
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup()
|
||||
.lookupClass());
|
||||
public static final Pattern DEFAULT_SKIP_PATTERN = Pattern
|
||||
.compile("/api-docs.*|/autoconfig|/configprops|/dump|/info|/metrics.*|/mappings|/trace|/swagger.*|.*\\.png|.*\\.css|.*\\.js|.*\\.html");
|
||||
|
||||
private final Trace trace;
|
||||
private final Pattern skipPattern;
|
||||
|
||||
public TraceFilter(Trace trace) {
|
||||
this.trace = trace;
|
||||
this.skipPattern = DEFAULT_SKIP_PATTERN;
|
||||
}
|
||||
|
||||
public TraceFilter(Trace trace, Pattern skipPattern) {
|
||||
this.trace = trace;
|
||||
this.skipPattern = skipPattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
String spanIdFromRequest = getSpanIdFrom(request);
|
||||
String spanId = (hasText(spanIdFromRequest)) ? spanIdFromRequest
|
||||
: getSpanIdFrom(response);
|
||||
|
||||
TraceScope traceScope = null;
|
||||
if (spanId != null) {
|
||||
addCorrelationIdToResponseIfNotPresent(response, spanId);
|
||||
|
||||
Span span = MilliSpan.builder().traceId("") // FIXME get traceId from request
|
||||
.parents(Collections.singletonList(spanId))
|
||||
// TODO: use parent() when lombok plugin supports it
|
||||
.build();
|
||||
traceScope = trace.startSpan("traceFilter", span);
|
||||
}
|
||||
else {
|
||||
traceScope = trace.startSpan("traceFilter");
|
||||
}
|
||||
|
||||
try {
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
finally {
|
||||
traceScope.close();
|
||||
}
|
||||
}
|
||||
|
||||
private String getSpanIdFrom(final HttpServletResponse response) {
|
||||
return response.getHeader(SPAN_ID_NAME);
|
||||
}
|
||||
|
||||
private String getSpanIdFrom(final HttpServletRequest request) {
|
||||
return request.getHeader(SPAN_ID_NAME);
|
||||
}
|
||||
|
||||
private void addCorrelationIdToResponseIfNotPresent(HttpServletResponse response,
|
||||
String spanId) {
|
||||
if (!hasText(response.getHeader(SPAN_ID_NAME))) {
|
||||
response.addHeader(SPAN_ID_NAME, spanId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldNotFilterAsyncDispatch() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package org.springframework.cloud.sleuth.trace.intercept.web;
|
||||
|
||||
import static org.springframework.cloud.sleuth.trace.Trace.SPAN_ID_NAME;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.extern.apachecommons.CommonsLog;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.springframework.cloud.sleuth.trace.Trace;
|
||||
import org.springframework.cloud.sleuth.trace.TraceScope;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
/**
|
||||
* Aspect that adds correlation id to
|
||||
* <p/>
|
||||
* <ul>
|
||||
* <li>{@link RestController} annotated classes</li>
|
||||
* <li>{@link Controller} annotated classes</li>
|
||||
* <li>explicit {@link RestOperations}.exchange(..) method calls</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* For controllers an around aspect is created that create a {@link Span} for each call.
|
||||
* <p/>
|
||||
* For {@link RestOperations} we are wrapping all executions of the <b>exchange</b>
|
||||
* methods and we are extracting {@link HttpHeaders} from the passed {@link HttpEntity}.
|
||||
* Next we are adding span id header * {@link Trace#SPAN_ID_NAME} with the value taken
|
||||
* from the current Span. Finally the method execution proceeds.
|
||||
*
|
||||
* @see RestController
|
||||
* @see Controller
|
||||
* @see RestOperations
|
||||
* @see Trace
|
||||
*
|
||||
* @author Tomasz Nurkewicz, 4financeIT
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Michal Chmielarz, 4financeIT
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@CommonsLog
|
||||
public class TraceWebAspect {
|
||||
|
||||
private final Trace trace;
|
||||
|
||||
public TraceWebAspect(Trace trace) {
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
private static final int HTTP_ENTITY_PARAM_INDEX = 2;
|
||||
|
||||
@Pointcut("@target(org.springframework.web.bind.annotation.RestController)")
|
||||
private void anyRestControllerAnnotated() {
|
||||
}
|
||||
|
||||
@Pointcut("@target(org.springframework.stereotype.Controller)")
|
||||
private void anyControllerAnnotated() {
|
||||
}
|
||||
|
||||
@Pointcut("anyRestControllerAnnotated() || anyControllerAnnotated()")
|
||||
private void anyControllerOrRestController() {
|
||||
}
|
||||
|
||||
@Around("anyControllerOrRestController()")
|
||||
public Object wrapWithCorrelationId(ProceedingJoinPoint pjp) throws Throwable {
|
||||
TraceScope scope = trace.startSpan(pjp.toShortString());
|
||||
try {
|
||||
return pjp.proceed();
|
||||
}
|
||||
finally {
|
||||
scope.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Pointcut("execution(public * org.springframework.web.client.RestOperations.exchange(..))")
|
||||
private void anyExchangeRestOperationsMethod() {
|
||||
}
|
||||
|
||||
@Around("anyExchangeRestOperationsMethod()")
|
||||
public Object wrapWithCorrelationIdForRestOperations(ProceedingJoinPoint pjp)
|
||||
throws Throwable {
|
||||
TraceScope scope = trace.startSpan(pjp.toShortString());
|
||||
try {
|
||||
String spanId = scope.getSpan().getSpanId();
|
||||
//TODO: set traceId on restTemplate call as well
|
||||
log.debug("Wrapping RestTemplate call with span id [" + spanId + "]");
|
||||
HttpEntity httpEntity = (HttpEntity) pjp.getArgs()[HTTP_ENTITY_PARAM_INDEX];
|
||||
HttpEntity newHttpEntity = createNewHttpEntity(httpEntity, spanId);
|
||||
List<Object> newArgs = modifyHttpEntityInMethodArguments(pjp, newHttpEntity);
|
||||
return pjp.proceed(newArgs.toArray());
|
||||
}
|
||||
finally {
|
||||
scope.close();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private HttpEntity createNewHttpEntity(HttpEntity httpEntity, String correlationId) {
|
||||
HttpHeaders newHttpHeaders = new HttpHeaders();
|
||||
newHttpHeaders.putAll(httpEntity.getHeaders());
|
||||
newHttpHeaders.add(SPAN_ID_NAME, correlationId);
|
||||
return new HttpEntity(httpEntity.getBody(), newHttpHeaders);
|
||||
}
|
||||
|
||||
private List<Object> modifyHttpEntityInMethodArguments(ProceedingJoinPoint pjp,
|
||||
HttpEntity newHttpEntity) {
|
||||
List<Object> newArgs = new ArrayList<>();
|
||||
for (int i = 0; i < pjp.getArgs().length; i++) {
|
||||
Object arg = pjp.getArgs()[i];
|
||||
if (i != HTTP_ENTITY_PARAM_INDEX) {
|
||||
newArgs.add(i, arg);
|
||||
}
|
||||
else {
|
||||
newArgs.add(i, newHttpEntity);
|
||||
}
|
||||
}
|
||||
return newArgs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.sleuth.trace.intercept.web;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.context.embedded.FilterRegistrationBean;
|
||||
import org.springframework.cloud.sleuth.trace.Trace;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Registers beans that add tracing to requests
|
||||
*
|
||||
* @author Tomasz Nurkewicz, 4financeIT
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Michal Chmielarz, 4financeIT
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "spring.cloud.sleuth.trace.web.enabled", matchIfMissing = true)
|
||||
@ConditionalOnWebApplication
|
||||
public class TraceWebAutoConfiguration {
|
||||
|
||||
/**
|
||||
* Pattern for URLs that should be skipped in correlationID setting
|
||||
*/
|
||||
@Value("${spring.cloud.sleuth.trace.web.skipPattern:}")
|
||||
private String skipPattern;
|
||||
|
||||
@Autowired
|
||||
private Trace trace;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TraceWebAspect traceWebAspect() {
|
||||
return new TraceWebAspect(trace);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public FilterRegistrationBean correlationHeaderFilter() {
|
||||
Pattern pattern = StringUtils.hasText(skipPattern) ? Pattern.compile(skipPattern)
|
||||
: TraceFilter.DEFAULT_SKIP_PATTERN;
|
||||
return new FilterRegistrationBean(new TraceFilter(trace, pattern));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.sleuth.trace.intercept.web.client;
|
||||
|
||||
import static org.springframework.cloud.sleuth.trace.Trace.SPAN_ID_NAME;
|
||||
import static org.springframework.cloud.sleuth.trace.Trace.TRACE_ID_NAME;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.cloud.sleuth.trace.SpanHolder;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
|
||||
/**
|
||||
* Interceptor that verifies whether the trance and span id has been set on the
|
||||
* request and sets them if one or both of them are missing.
|
||||
*
|
||||
* @see org.springframework.web.client.RestTemplate
|
||||
* @see org.springframework.cloud.sleuth.trace.Trace
|
||||
*
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class TraceRestTemplateInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
|
||||
ClientHttpRequestExecution execution) throws IOException {
|
||||
if (!request.getHeaders().containsKey(SPAN_ID_NAME)) {
|
||||
request.getHeaders().add(SPAN_ID_NAME,
|
||||
SpanHolder.getCurrentSpan().getSpanId());
|
||||
}
|
||||
if (!request.getHeaders().containsKey(TRACE_ID_NAME)) {
|
||||
request.getHeaders().add(TRACE_ID_NAME,
|
||||
SpanHolder.getCurrentSpan().getSpanId());
|
||||
}
|
||||
return execution.execute(request, body);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.springframework.cloud.sleuth.trace.intercept.web.client;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.sleuth.resttemplate.SleuthRestTemplateAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "spring.cloud.sleuth.trace.web.client.enabled", matchIfMissing = true)
|
||||
@ConditionalOnClass(RestTemplate.class)
|
||||
@AutoConfigureAfter(SleuthRestTemplateAutoConfiguration.class)
|
||||
public class TraceWebClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TraceRestTemplateInterceptor traceRestTemplateInterceptor() {
|
||||
return new TraceRestTemplateInterceptor();
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,6 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.sleuth.resttemplate.SleuthRestTemplateAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.trace.TraceAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.trace.intercept.web.TraceWebAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.trace.intercept.web.client.TraceWebClientAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.slf4j.SleuthSlf4jAutoConfiguration
|
||||
|
||||
Reference in New Issue
Block a user