Added support for Feign + OkHttpClient + Sleuth

without this change we get exceptions related to not being able to extend a final class
with this change we're not wrapping any final types and we have a custom bean post processor for okhttp

fixes #513
This commit is contained in:
Marcin Grzejszczak
2017-02-24 16:58:27 +01:00
parent e0c2656354
commit cc07a8f777
7 changed files with 89 additions and 9 deletions

View File

@@ -596,11 +596,6 @@ include::../../../../spring-cloud-sleuth-core/src/test/java/org/springframework/
Spring Cloud Sleuth integrates with http://projects.spring.io/spring-integration/[Spring Integration]. It creates spans for publish and
subscribe events. To disable Spring Integration instrumentation, set `spring.sleuth.integration.enabled` to false.
Spring Cloud Sleuth up till version 1.0.4 is sending invalid tracing headers when using messaging. Those headers are actually
the same as the ones sent in HTTP (they contain a `-`) in its name. For the sake of
backwards compatibility in 1.0.4 we've started sending both valid and invalid headers. Please upgrade to 1.0.4 because
in Spring Cloud Sleuth 1.1 we will remove the support for the deprecated headers.
You can provide the `spring.sleuth.integration.patterns` pattern to explicitly
provide the names of channels that you want to include for tracing. By default all channels
are included.

View File

@@ -95,6 +95,11 @@
<artifactId>httpclient</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>

View File

@@ -34,12 +34,12 @@ import org.springframework.web.context.request.async.WebAsyncTask;
* Aspect that adds tracing to
* <p/>
* <ul>
* <li>{@link org.springframework.web.bind.annotation.RestController} annotated classes
* <li>{@code RestController} annotated classes
* with public {@link Callable} methods</li>
* <li>{@link org.springframework.stereotype.Controller} annotated classes with public
* {@link Callable} methods</li>
* <li>{@link org.springframework.stereotype.Controller} or
* {@link org.springframework.web.bind.annotation.RestController} annotated classes with
* {@code RestController} annotated classes with
* public {@link WebAsyncTask} methods</li>
* </ul>
* <p/>
@@ -57,7 +57,6 @@ import org.springframework.web.context.request.async.WebAsyncTask;
* @author Spencer Gibb
* @since 1.0.0
*
* @see org.springframework.web.bind.annotation.RestController
* @see org.springframework.stereotype.Controller
* @see org.springframework.web.client.RestOperations
* @see org.springframework.cloud.sleuth.TraceCallable

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2013-2016 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.instrument.web.client.feign;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import feign.okhttp.OkHttpClient;
/**
* Post processor that wraps takes care of the OkHttp Feign Client instrumentation
*
* @author Marcin Grzejszczak
*
* @since 1.1.3
*/
final class OkHttpFeignClientBeanPostProcessor implements BeanPostProcessor {
private final BeanFactory beanFactory;
private TraceFeignObjectWrapper traceFeignObjectWrapper;
OkHttpFeignClientBeanPostProcessor(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof OkHttpClient) {
return getTraceFeignObjectWrapper().wrap(bean);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
private TraceFeignObjectWrapper getTraceFeignObjectWrapper() {
if (this.traceFeignObjectWrapper == null) {
this.traceFeignObjectWrapper = this.beanFactory.getBean(TraceFeignObjectWrapper.class);
}
return this.traceFeignObjectWrapper;
}
}

View File

@@ -39,7 +39,7 @@ class TraceFeignAspect {
this.beanFactory = beanFactory;
}
@Around("execution (* feign.Client.*(..))")
@Around("execution (* feign.Client.*(..)) && !within(is(FinalType))")
public Object feignClientWasCalled(final ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
Request request = (Request) args[0];

View File

@@ -33,6 +33,7 @@ import org.springframework.context.annotation.Scope;
import feign.Client;
import feign.Feign;
import feign.okhttp.OkHttpClient;
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
@@ -75,6 +76,16 @@ public class TraceFeignClientAutoConfiguration {
}
}
@Configuration
@ConditionalOnClass(OkHttpClient.class)
protected static class OkHttpClientFeignBeanPostProcessorConfiguration {
@Bean
OkHttpFeignClientBeanPostProcessor okHttpFeignClientBeanPostProcessor(BeanFactory beanFactory) {
return new OkHttpFeignClientBeanPostProcessor(beanFactory);
}
}
@Bean
TraceFeignObjectWrapper traceFeignObjectWrapper(BeanFactory beanFactory) {
return new TraceFeignObjectWrapper(beanFactory);

View File

@@ -41,6 +41,8 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import feign.okhttp.OkHttpClient;
import static org.assertj.core.api.BDDAssertions.then;
/**
@@ -89,6 +91,12 @@ class Application {
return new DemoController(myNameRemote);
}
// issue #513
@Bean
public OkHttpClient myOkHttpClient() {
return new OkHttpClient();
}
@Bean
public feign.Logger.Level feignLoggerLevel() {
return feign.Logger.Level.BASIC;