Merge branch '2.2.x'
This commit is contained in:
@@ -676,7 +676,7 @@ To that end, Sleuth:
|
||||
** Includes a sampling policy to manage volume.
|
||||
** Can report to a Zipkin system for query and visualization.
|
||||
|
||||
* Instruments common ingress and egress points from Spring applications (servlet filter, async endpoints, rest template, scheduled actions, message channels, Zuul filters, and Feign client).
|
||||
* Instruments common ingress and egress points from Spring applications (servlet filter, async endpoints, rest template, scheduled actions, message channels, and Feign client).
|
||||
|
||||
* Sleuth includes default logic to join a trace across HTTP or messaging boundaries.
|
||||
For example, HTTP propagation works over Zipkin-compatible request headers.
|
||||
@@ -983,4 +983,4 @@ Go to `File` -> `Settings` -> `Other settings` -> `Checkstyle`. There click on t
|
||||
- `checkstyle.suppressions.file` - default suppressions. Please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` URL.
|
||||
- `checkstyle.additional.suppressions.file` - this variable corresponds to suppressions in your local project. E.g. you're working on `spring-cloud-contract`. Then point to the `project-root/src/checkstyle/checkstyle-suppressions.xml` folder. Example for `spring-cloud-contract` would be: `/home/username/spring-cloud-contract/src/checkstyle/checkstyle-suppressions.xml`.
|
||||
|
||||
IMPORTANT: Remember to set the `Scan Scope` to `All sources` since we apply checkstyle rules for production and test sources.
|
||||
IMPORTANT: Remember to set the `Scan Scope` to `All sources` since we apply checkstyle rules for production and test sources.
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|spring.sleuth.sampler.probability | | Probability of requests that should be sampled. E.g. 1.0 - 100% requests should be sampled. The precision is whole-numbers only (i.e. there's no support for 0.1% of the traces).
|
||||
|spring.sleuth.sampler.rate | 10 | A rate per second can be a nice choice for low-traffic endpoints as it allows you surge protection. For example, you may never expect the endpoint to get more than 50 requests per second. If there was a sudden surge of traffic, to 5000 requests per second, you would still end up with 50 traces per second. Conversely, if you had a percentage, like 10%, the same surge would end up with 500 traces per second, possibly overloading your storage. Amazon X-Ray includes a rate-limited sampler (named Reservoir) for this purpose. Brave has taken the same approach via the {@link brave.sampler.RateLimitingSampler}.
|
||||
|spring.sleuth.scheduled.enabled | true | Enable tracing for {@link org.springframework.scheduling.annotation.Scheduled}.
|
||||
|spring.sleuth.scheduled.skip-pattern | org.springframework.cloud.netflix.hystrix.stream.HystrixStreamTask | Pattern for the fully qualified name of a class that should be skipped.
|
||||
|spring.sleuth.scheduled.skip-pattern | | Pattern for the fully qualified name of a class that should be skipped.
|
||||
|spring.sleuth.supports-join | true | True means the tracing system supports sharing a span ID between a client and server.
|
||||
|spring.sleuth.trace-id128 | false | When true, generate 128-bit trace IDs instead of 64-bit ones.
|
||||
|spring.sleuth.web.additional-skip-pattern | | Additional pattern for URLs that should be skipped in tracing. This will be appended to the {@link SleuthWebProperties#skipPattern}.
|
||||
@@ -52,7 +52,6 @@
|
||||
|spring.sleuth.web.filter-order | | Order in which the tracing filters should be registered. Defaults to {@link TraceHttpAutoConfiguration#TRACING_FILTER_ORDER}.
|
||||
|spring.sleuth.web.ignore-auto-configured-skip-patterns | false | If set to true, auto-configured skip patterns will be ignored. @see TraceWebAutoConfiguration
|
||||
|spring.sleuth.web.skip-pattern | /api-docs.*\|/swagger.*\|.*\.png\|.*\.css\|.*\.js\|.*\.html\|/favicon.ico\|/hystrix.stream | Pattern for URLs that should be skipped in tracing.
|
||||
|spring.sleuth.zuul.enabled | true | Enable span information propagation when using Zuul.
|
||||
|spring.zipkin.activemq.message-max-bytes | 100000 | Maximum number of bytes for a given message with spans sent to Zipkin over ActiveMQ.
|
||||
|spring.zipkin.activemq.queue | zipkin | Name of the ActiveMQ queue where spans should be sent to Zipkin.
|
||||
|spring.zipkin.base-url | http://localhost:9411/ | URL of the zipkin query server instance. You can also provide the service id of the Zipkin server if Zipkin's registered in service discovery (e.g. https://zipkinserver/).
|
||||
|
||||
@@ -32,7 +32,7 @@ To that end, Sleuth:
|
||||
** Includes a sampling policy to manage volume.
|
||||
** Can report to a Zipkin system for query and visualization.
|
||||
|
||||
* Instruments common ingress and egress points from Spring applications (servlet filter, async endpoints, rest template, scheduled actions, message channels, Zuul filters, and Feign client).
|
||||
* Instruments common ingress and egress points from Spring applications (servlet filter, async endpoints, rest template, scheduled actions, message channels, and Feign client).
|
||||
|
||||
* Sleuth includes default logic to join a trace across HTTP or messaging boundaries.
|
||||
For example, HTTP propagation works over Zipkin-compatible request headers.
|
||||
|
||||
@@ -8,5 +8,5 @@ Spring Cloud Sleuth features:
|
||||
|
||||
* Adds trace and span ids to the Slf4J MDC, so you can extract all the logs from a given trace or span in a log aggregator.
|
||||
* Provides an abstraction over common distributed tracing data models: traces, spans (forming a DAG), annotations, key-value annotations. Loosely based on HTrace, but Zipkin (Dapper) compatible.
|
||||
* Instruments common ingress and egress points from Spring applications (servlet filter, rest template, scheduled actions, message channels, zuul filters, feign client).
|
||||
* If `spring-cloud-sleuth-zipkin` is available then the app will generate and collect Zipkin-compatible traces via HTTP. By default it sends them to a Zipkin collector service on localhost (port 9411). Configure the location of the service using `spring.zipkin.baseUrl`.
|
||||
* Instruments common ingress and egress points from Spring applications (servlet filter, rest template, scheduled actions, message channels, feign client).
|
||||
* If `spring-cloud-sleuth-zipkin` is available then the app will generate and collect Zipkin-compatible traces via HTTP. By default it sends them to a Zipkin collector service on localhost (port 9411). Configure the location of the service using `spring.zipkin.baseUrl`.
|
||||
|
||||
@@ -620,8 +620,6 @@ Sometimes, you do not want to create a new span but you want to continue one. An
|
||||
situation might be as follows:
|
||||
|
||||
* *AOP*: If there was already a span created before an aspect was reached, you might not want to create a new span.
|
||||
* *Hystrix*: Executing a Hystrix command is most likely a logical part of the current processing.
|
||||
It is in fact merely a technical implementation detail that you would not necessarily want to reflect in tracing as a separate being.
|
||||
|
||||
To continue a span, you can use `brave.Tracer`, as shown in the following example:
|
||||
|
||||
@@ -1352,8 +1350,6 @@ If you annotate your method with `@Scheduled`, we automatically create a new spa
|
||||
* The span is tagged with the method's class name and method name.
|
||||
|
||||
If you want to skip span creation for some `@Scheduled` annotated classes, you can set the `spring.sleuth.scheduled.skipPattern` with a regular expression that matches the fully qualified name of the `@Scheduled` annotated class.
|
||||
If you use `spring-cloud-sleuth-stream` and `spring-cloud-netflix-hystrix-stream` together, a span is created for each Hystrix metrics and sent to Zipkin.
|
||||
This behavior may be annoying. That's why, by default, `spring.sleuth.scheduled.skipPattern=org.springframework.cloud.netflix.hystrix.stream.HystrixStreamTask`.
|
||||
|
||||
==== Executor, ExecutorService, and ScheduledExecutorService
|
||||
|
||||
@@ -1450,11 +1446,6 @@ so that tracing headers get extracted from the message and a trace gets put into
|
||||
|
||||
To block this feature, set `spring.sleuth.messaging.sqs.enabled` to `false`.
|
||||
|
||||
=== Zuul
|
||||
|
||||
We instrument the Zuul Ribbon integration by enriching the Ribbon requests with tracing information.
|
||||
To disable Zuul support, set the `spring.sleuth.zuul.enabled` property to `false`.
|
||||
|
||||
=== Redis
|
||||
|
||||
We set `tracing` property to Lettcue `ClientResources` instance to enable Brave tracing built in Lettuce .
|
||||
|
||||
@@ -36,7 +36,7 @@ public class SleuthSchedulingProperties {
|
||||
/**
|
||||
* Pattern for the fully qualified name of a class that should be skipped.
|
||||
*/
|
||||
private String skipPattern = "org.springframework.cloud.netflix.hystrix.stream.HystrixStreamTask";
|
||||
private String skipPattern;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
@@ -51,7 +51,14 @@ public class SleuthSchedulingProperties {
|
||||
}
|
||||
|
||||
public void setSkipPattern(String skipPattern) {
|
||||
this.skipPattern = skipPattern;
|
||||
this.skipPattern = emptyToNull(skipPattern);
|
||||
}
|
||||
|
||||
static String emptyToNull(String skipPattern) {
|
||||
if (skipPattern != null && skipPattern.isEmpty()) {
|
||||
skipPattern = null; // otherwise this make an empty pattern!
|
||||
}
|
||||
return skipPattern;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
|
||||
import org.springframework.cloud.sleuth.util.SpanNameUtil;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Aspect that creates a new Span for running threads executing methods annotated with
|
||||
@@ -50,6 +51,7 @@ public class TraceSchedulingAspect {
|
||||
|
||||
private final Tracer tracer;
|
||||
|
||||
@Nullable
|
||||
private final Pattern skipPattern;
|
||||
|
||||
public TraceSchedulingAspect(Tracer tracer, Pattern skipPattern) {
|
||||
@@ -59,7 +61,8 @@ public class TraceSchedulingAspect {
|
||||
|
||||
@Around("execution (@org.springframework.scheduling.annotation.Scheduled * *.*(..))")
|
||||
public Object traceBackgroundThread(final ProceedingJoinPoint pjp) throws Throwable {
|
||||
if (this.skipPattern.matcher(pjp.getTarget().getClass().getName()).matches()) {
|
||||
if (this.skipPattern != null && this.skipPattern
|
||||
.matcher(pjp.getTarget().getClass().getName()).matches()) {
|
||||
// we might have a span in context due to wrapping of runnables
|
||||
// we want to clear that context
|
||||
this.tracer.withSpanInScope(null);
|
||||
|
||||
@@ -51,8 +51,10 @@ public class TraceSchedulingAutoConfiguration {
|
||||
@ConditionalOnClass(name = "org.aspectj.lang.ProceedingJoinPoint")
|
||||
public TraceSchedulingAspect traceSchedulingAspect(Tracer tracer,
|
||||
SleuthSchedulingProperties sleuthSchedulingProperties) {
|
||||
return new TraceSchedulingAspect(tracer,
|
||||
Pattern.compile(sleuthSchedulingProperties.getSkipPattern()));
|
||||
String skipPatternString = sleuthSchedulingProperties.getSkipPattern();
|
||||
Pattern skipPattern = skipPatternString != null
|
||||
? Pattern.compile(skipPatternString) : null;
|
||||
return new TraceSchedulingAspect(tracer, skipPattern);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,18 +27,12 @@ import brave.sampler.SamplerFunction;
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class SkipPatternHttpServerSampler implements SamplerFunction<HttpRequest> {
|
||||
|
||||
private final SkipPatternProvider provider;
|
||||
abstract class SkipPatternSampler implements SamplerFunction<HttpRequest> {
|
||||
|
||||
private Pattern pattern;
|
||||
|
||||
SkipPatternHttpServerSampler(SkipPatternProvider provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean trySample(HttpRequest request) {
|
||||
public final Boolean trySample(HttpRequest request) {
|
||||
String url = request.path();
|
||||
boolean shouldSkip = pattern().matcher(url).matches();
|
||||
if (shouldSkip) {
|
||||
@@ -47,9 +41,11 @@ class SkipPatternHttpServerSampler implements SamplerFunction<HttpRequest> {
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract Pattern getPattern();
|
||||
|
||||
private Pattern pattern() {
|
||||
if (this.pattern == null) {
|
||||
this.pattern = this.provider.skipPattern();
|
||||
this.pattern = getPattern();
|
||||
}
|
||||
return this.pattern;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ public class SleuthWebProperties {
|
||||
}
|
||||
|
||||
public void setSkipPattern(String skipPattern) {
|
||||
this.skipPattern = skipPattern;
|
||||
this.skipPattern = emptyToNull(skipPattern);
|
||||
}
|
||||
|
||||
public String getAdditionalSkipPattern() {
|
||||
@@ -104,7 +104,7 @@ public class SleuthWebProperties {
|
||||
}
|
||||
|
||||
public void setAdditionalSkipPattern(String additionalSkipPattern) {
|
||||
this.additionalSkipPattern = additionalSkipPattern;
|
||||
this.additionalSkipPattern = emptyToNull(additionalSkipPattern);
|
||||
}
|
||||
|
||||
public int getFilterOrder() {
|
||||
@@ -149,6 +149,13 @@ public class SleuthWebProperties {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
static String emptyToNull(String skipPattern) {
|
||||
if (skipPattern != null && skipPattern.isEmpty()) {
|
||||
skipPattern = null; // otherwise this would skip paths named ""!
|
||||
}
|
||||
return skipPattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Web client properties.
|
||||
*
|
||||
@@ -159,7 +166,7 @@ public class SleuthWebProperties {
|
||||
/**
|
||||
* Pattern for URLs that should be skipped in client side tracing.
|
||||
*/
|
||||
private String skipPattern = "";
|
||||
private String skipPattern;
|
||||
|
||||
/**
|
||||
* Enable interceptor injecting into
|
||||
@@ -180,7 +187,7 @@ public class SleuthWebProperties {
|
||||
}
|
||||
|
||||
public void setSkipPattern(String skipPattern) {
|
||||
this.skipPattern = skipPattern;
|
||||
this.skipPattern = emptyToNull(skipPattern);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cloud.sleuth.instrument.web;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import brave.Tracing;
|
||||
import brave.http.HttpRequest;
|
||||
@@ -26,6 +27,7 @@ import brave.http.HttpResponseParser;
|
||||
import brave.http.HttpTracing;
|
||||
import brave.http.HttpTracingCustomizer;
|
||||
import brave.sampler.SamplerFunction;
|
||||
import brave.sampler.SamplerFunctions;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
@@ -59,7 +61,7 @@ public class TraceHttpAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
// NOTE: stable bean name as might be used outside sleuth
|
||||
HttpTracing httpTracing(Tracing tracing, SkipPatternProvider provider,
|
||||
HttpTracing httpTracing(Tracing tracing, @Nullable SkipPatternProvider provider,
|
||||
@Nullable @HttpClientRequestParser HttpRequestParser httpClientRequestParser,
|
||||
@Nullable @HttpClientResponseParser HttpResponseParser httpClientResponseParser,
|
||||
@Nullable brave.http.HttpClientParser clientParser,
|
||||
@@ -106,12 +108,18 @@ public class TraceHttpAutoConfiguration {
|
||||
|
||||
private SamplerFunction<HttpRequest> combineUserProvidedSamplerWithSkipPatternSampler(
|
||||
@Nullable SamplerFunction<HttpRequest> serverSampler,
|
||||
SkipPatternProvider provider) {
|
||||
SkipPatternHttpServerSampler skipPatternSampler = new SkipPatternHttpServerSampler(
|
||||
provider);
|
||||
if (serverSampler == null) {
|
||||
@Nullable SkipPatternProvider provider) {
|
||||
SamplerFunction<HttpRequest> skipPatternSampler = provider != null
|
||||
? new SkipPatternHttpServerSampler(provider) : null;
|
||||
if (serverSampler == null && skipPatternSampler == null) {
|
||||
return SamplerFunctions.deferDecision();
|
||||
}
|
||||
else if (serverSampler == null) {
|
||||
return skipPatternSampler;
|
||||
}
|
||||
else if (skipPatternSampler == null) {
|
||||
return serverSampler;
|
||||
}
|
||||
return new CompositeHttpSampler(skipPatternSampler, serverSampler);
|
||||
}
|
||||
|
||||
@@ -119,7 +127,12 @@ public class TraceHttpAutoConfiguration {
|
||||
@ConditionalOnMissingBean(name = HttpClientSampler.NAME)
|
||||
SamplerFunction<HttpRequest> sleuthHttpClientSampler(
|
||||
SleuthWebProperties sleuthWebProperties) {
|
||||
return new SkipPatternHttpClientSampler(sleuthWebProperties);
|
||||
String skipPattern = sleuthWebProperties.getClient().getSkipPattern();
|
||||
if (skipPattern == null) {
|
||||
return SamplerFunctions.deferDecision();
|
||||
}
|
||||
|
||||
return new SkipPatternHttpClientSampler(Pattern.compile(skipPattern));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -129,7 +142,7 @@ public class TraceHttpAutoConfiguration {
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
class CompositeHttpSampler implements SamplerFunction<HttpRequest> {
|
||||
final class CompositeHttpSampler implements SamplerFunction<HttpRequest> {
|
||||
|
||||
final SamplerFunction<HttpRequest> left;
|
||||
|
||||
@@ -170,21 +183,32 @@ class CompositeHttpSampler implements SamplerFunction<HttpRequest> {
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
class SkipPatternHttpClientSampler implements SamplerFunction<HttpRequest> {
|
||||
final class SkipPatternHttpServerSampler extends SkipPatternSampler {
|
||||
|
||||
private final SleuthWebProperties properties;
|
||||
private final SkipPatternProvider provider;
|
||||
|
||||
SkipPatternHttpClientSampler(SleuthWebProperties properties) {
|
||||
this.properties = properties;
|
||||
SkipPatternHttpServerSampler(SkipPatternProvider provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean trySample(HttpRequest request) {
|
||||
String path = request.path();
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
return path.matches(this.properties.getClient().getSkipPattern()) ? false : null;
|
||||
Pattern getPattern() {
|
||||
return this.provider.skipPattern();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final class SkipPatternHttpClientSampler extends SkipPatternSampler {
|
||||
|
||||
private final Pattern skipPattern;
|
||||
|
||||
SkipPatternHttpClientSampler(Pattern skipPattern) {
|
||||
this.skipPattern = skipPattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
Pattern getPattern() {
|
||||
return skipPattern;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import brave.Tracing;
|
||||
|
||||
@@ -66,18 +67,26 @@ public class TraceWebAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
SkipPatternProvider sleuthSkipPatternProvider() {
|
||||
return () -> {
|
||||
StringJoiner joiner = new StringJoiner("|");
|
||||
for (SingleSkipPattern pattern : this.patterns) {
|
||||
Optional<Pattern> skipPattern = pattern.skipPattern();
|
||||
if (skipPattern.isPresent()) {
|
||||
Pattern pattern1 = skipPattern.get();
|
||||
String s = pattern1.pattern();
|
||||
joiner.add(s);
|
||||
}
|
||||
}
|
||||
return Pattern.compile(joiner.toString());
|
||||
};
|
||||
if (this.patterns == null) {
|
||||
return null;
|
||||
}
|
||||
List<Pattern> presentPatterns = this.patterns.stream()
|
||||
.map(SingleSkipPattern::skipPattern).filter(Optional::isPresent)
|
||||
.map(Optional::get).collect(Collectors.toList());
|
||||
if (presentPatterns.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (presentPatterns.size() == 1) {
|
||||
Pattern pattern = presentPatterns.get(0);
|
||||
return () -> pattern;
|
||||
}
|
||||
StringJoiner joiner = new StringJoiner("|");
|
||||
for (Pattern pattern : presentPatterns) {
|
||||
String s = pattern.pattern();
|
||||
joiner.add(s);
|
||||
}
|
||||
Pattern pattern = Pattern.compile(joiner.toString());
|
||||
return () -> pattern;
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@@ -200,24 +209,25 @@ public class TraceWebAutoConfiguration {
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class DefaultSkipPatternConfig {
|
||||
|
||||
private static String combinedPattern(String skipPattern,
|
||||
String additionalSkipPattern) {
|
||||
String pattern = skipPattern;
|
||||
if (!StringUtils.hasText(skipPattern)) {
|
||||
pattern = SleuthWebProperties.DEFAULT_SKIP_PATTERN;
|
||||
}
|
||||
if (StringUtils.hasText(additionalSkipPattern)) {
|
||||
return pattern + "|" + additionalSkipPattern;
|
||||
}
|
||||
return pattern;
|
||||
}
|
||||
|
||||
@Bean
|
||||
SingleSkipPattern defaultSkipPatternBean(
|
||||
SleuthWebProperties sleuthWebProperties) {
|
||||
return () -> Optional.of(
|
||||
Pattern.compile(combinedPattern(sleuthWebProperties.getSkipPattern(),
|
||||
sleuthWebProperties.getAdditionalSkipPattern())));
|
||||
Pattern pattern = combinePatterns(sleuthWebProperties.getSkipPattern(),
|
||||
sleuthWebProperties.getAdditionalSkipPattern());
|
||||
return () -> Optional.ofNullable(pattern);
|
||||
}
|
||||
|
||||
private static Pattern combinePatterns(String left, String right) {
|
||||
if (left == null && right == null) {
|
||||
return null;
|
||||
}
|
||||
else if (left == null) {
|
||||
return Pattern.compile(right);
|
||||
}
|
||||
else if (right == null) {
|
||||
return Pattern.compile(left);
|
||||
}
|
||||
return Pattern.compile(left + "|" + right);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,8 +53,6 @@ public class TraceFeignClientAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Scope("prototype")
|
||||
@ConditionalOnProperty(name = "feign.hystrix.enabled", havingValue = "false",
|
||||
matchIfMissing = true)
|
||||
Feign.Builder feignBuilder(BeanFactory beanFactory) {
|
||||
return SleuthFeignBuilder.builder(beanFactory);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,10 @@ class TraceFeignContext extends FeignContext {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getInstance(String name, Class<T> type) {
|
||||
T object = this.delegate.getInstance(name, type);
|
||||
return (T) this.traceFeignObjectWrapper.wrap(object);
|
||||
if (object != null) {
|
||||
return (T) this.traceFeignObjectWrapper.wrap(object);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -36,12 +36,6 @@
|
||||
"description": "Enable post processor that wraps Feign Context in its tracing representations.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "spring.sleuth.zuul.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Enable span information propagation when using Zuul.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "spring.sleuth.grpc.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
|
||||
@@ -59,6 +59,13 @@ public class SkipPatternProviderConfigTest {
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
TraceAutoConfiguration.class, TraceWebAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void should_return_null_when_cleared() throws Exception {
|
||||
contextRunner.withPropertyValues("spring.sleuth.web.skip-pattern")
|
||||
.run(context -> then(context.getBean("sleuthSkipPatternProvider"))
|
||||
.hasToString("null"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_pick_skip_pattern_from_sleuth_properties() throws Exception {
|
||||
contextRunner.withPropertyValues("spring.sleuth.web.skip-pattern=foo.*|bar.*")
|
||||
|
||||
@@ -31,27 +31,59 @@ import static org.assertj.core.api.BDDAssertions.then;
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class SkipPatternHttpServerSamplerTests {
|
||||
public class SkipPatternSamplerTests {
|
||||
|
||||
@Mock
|
||||
HttpRequest request;
|
||||
|
||||
@Test
|
||||
public void should_delegate_sampling_decision_if_pattern_is_not_matched() {
|
||||
SkipPatternProvider provider = () -> Pattern.compile("foo");
|
||||
BDDMockito.given(this.request.path()).willReturn("url");
|
||||
SkipPatternHttpServerSampler sampler = new SkipPatternHttpServerSampler(provider);
|
||||
SkipPatternSampler sampler = new SkipPatternSampler() {
|
||||
@Override
|
||||
Pattern getPattern() {
|
||||
return Pattern.compile("foo");
|
||||
}
|
||||
};
|
||||
|
||||
then(sampler.trySample(this.request)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_not_sample_if_pattern_is_matched() {
|
||||
SkipPatternProvider provider = () -> Pattern.compile(".*");
|
||||
BDDMockito.given(this.request.path()).willReturn("url");
|
||||
SkipPatternHttpServerSampler sampler = new SkipPatternHttpServerSampler(provider);
|
||||
SkipPatternSampler sampler = new SkipPatternSampler() {
|
||||
@Override
|
||||
Pattern getPattern() {
|
||||
return Pattern.compile(".*");
|
||||
}
|
||||
};
|
||||
|
||||
then(sampler.trySample(this.request)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_not_get_pattern_twice() {
|
||||
BDDMockito.given(this.request.path()).willReturn("url");
|
||||
SkipPatternSampler sampler = new SkipPatternSampler() {
|
||||
boolean provisioned;
|
||||
|
||||
@Override
|
||||
Pattern getPattern() {
|
||||
if (provisioned) {
|
||||
throw new AssertionError("called twice!");
|
||||
}
|
||||
try {
|
||||
return Pattern.compile(".*");
|
||||
}
|
||||
finally {
|
||||
provisioned = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
then(sampler.trySample(this.request)).isFalse();
|
||||
then(sampler.trySample(this.request)).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import brave.http.HttpRequestParser;
|
||||
import brave.http.HttpResponseParser;
|
||||
import brave.http.HttpTracing;
|
||||
import brave.sampler.SamplerFunction;
|
||||
import brave.sampler.SamplerFunctions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
@@ -36,15 +37,27 @@ import static org.assertj.core.api.BDDAssertions.then;
|
||||
public class TraceHttpAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void defaultsToSkipPatternHttpClientSampler() {
|
||||
public void defaultsClientSamplerToDefer() {
|
||||
contextRunner().run((context) -> {
|
||||
SamplerFunction<HttpRequest> clientSampler = context
|
||||
.getBean(HttpTracing.class).clientRequestSampler();
|
||||
|
||||
then(clientSampler).isInstanceOf(SkipPatternHttpClientSampler.class);
|
||||
then(clientSampler).isSameAs(SamplerFunctions.deferDecision());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configuresClientSkipPattern() throws Exception {
|
||||
contextRunner()
|
||||
.withPropertyValues("spring.sleuth.web.client.skip-pattern=foo.*|bar.*")
|
||||
.run((context) -> {
|
||||
SamplerFunction<HttpRequest> clientSampler = context
|
||||
.getBean(HttpTracing.class).clientRequestSampler();
|
||||
|
||||
then(clientSampler).isInstanceOf(SkipPatternHttpClientSampler.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configuresUserProvidedHttpClientSampler() {
|
||||
contextRunner().withUserConfiguration(HttpClientSamplerConfig.class)
|
||||
@@ -57,7 +70,7 @@ public class TraceHttpAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultsToSkipPatternHttpServerSampler() {
|
||||
public void defaultsServerSamplerToSkipPattern() {
|
||||
contextRunner().run((context) -> {
|
||||
SamplerFunction<HttpRequest> serverSampler = context
|
||||
.getBean(HttpTracing.class).serverRequestSampler();
|
||||
@@ -66,6 +79,17 @@ public class TraceHttpAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultsServerSamplerToDeferWhenSkipPatternCleared() {
|
||||
contextRunner().withPropertyValues("spring.sleuth.web.skip-pattern")
|
||||
.run((context) -> {
|
||||
SamplerFunction<HttpRequest> clientSampler = context
|
||||
.getBean(HttpTracing.class).serverRequestSampler();
|
||||
|
||||
then(clientSampler).isSameAs(SamplerFunctions.deferDecision());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrapsUserProvidedHttpServerSampler() {
|
||||
contextRunner().withUserConfiguration(HttpServerSamplerConfig.class)
|
||||
|
||||
@@ -95,8 +95,6 @@ public class WebClientDiscoveryExceptionTests {
|
||||
span.finish();
|
||||
}
|
||||
|
||||
// hystrix commands should finish at this point
|
||||
Thread.sleep(200);
|
||||
List<zipkin2.Span> spans = this.reporter.getSpans();
|
||||
then(spans.stream().filter(span1 -> span1.kind() == zipkin2.Span.Kind.CLIENT)
|
||||
.findFirst().get().tags()).containsKey("error");
|
||||
|
||||
@@ -52,8 +52,7 @@ import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
@SpringBootTest(classes = { WebClientExceptionTests.TestConfiguration.class },
|
||||
properties = { "ribbon.ConnectTimeout=30000",
|
||||
"spring.application.name=exceptionservice" },
|
||||
properties = { "spring.application.name=exceptionservice" },
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class WebClientExceptionTests {
|
||||
|
||||
@@ -128,7 +127,7 @@ public class WebClientExceptionTests {
|
||||
@EnableAutoConfiguration
|
||||
@EnableFeignClients
|
||||
@LoadBalancerClient(value = "exceptionservice",
|
||||
configuration = ExceptionServiceRibbonClientConfiguration.class)
|
||||
configuration = ExceptionServiceLoadBalancerClientConfiguration.class)
|
||||
public static class TestConfiguration {
|
||||
|
||||
@LoadBalanced
|
||||
@@ -153,7 +152,7 @@ public class WebClientExceptionTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class ExceptionServiceRibbonClientConfiguration {
|
||||
public static class ExceptionServiceLoadBalancerClientConfiguration {
|
||||
|
||||
@Bean
|
||||
public ServiceInstanceListSupplier serviceInstanceListSupplier(Environment env) {
|
||||
|
||||
@@ -96,7 +96,7 @@ import static org.assertj.core.api.BDDAssertions.then;
|
||||
@SpringBootTest(classes = WebClientTests.TestConfiguration.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@TestPropertySource(properties = { "spring.application.name=fooservice",
|
||||
"feign.hystrix.enabled=false", "spring.sleuth.web.client.skip-pattern=/skip.*" })
|
||||
"spring.sleuth.web.client.skip-pattern=/skip.*" })
|
||||
@DirtiesContext
|
||||
public class WebClientTests {
|
||||
|
||||
|
||||
@@ -10,10 +10,6 @@ There are a few samples with slightly different features. You can run all of the
|
||||
|
||||
* `spring-cloud-sleuth-sample-messaging`: a Spring Integration application with two HTTP endpoints ("/" and "/xform")
|
||||
|
||||
* `spring-cloud-sleuth-sample-ribbon`: two endpoints ("/" and "/call") that make calls to the "zipkin" sample via Ribbon. Also has `@EnableZUulProxy" so if the other samples are running they are proxied at "/messaging", "/zipkin", "/vanilla" (see "/routes" for a list).
|
||||
|
||||
The Ribbon sample makes an interesting demo or playground for learning about zipkin. In the screenshot below you can see a trace with 3 spans - it starts in the "testSleuthRibbon" app and crosses to "testSleuthMessaging" for the next 2 spans.
|
||||
|
||||
=== Running samples with Zipkin
|
||||
|
||||
1. Optionally run the https://github.com/openzipkin/zipkin[Zipkin] Server, e.g. via docker compose (there's a `docker-compose.yml` in https://github.com/spring-cloud/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin[Spring Cloud Sleuth], or in https://github.com/openzipkin/docker-zipkin[Docker Zipkin]
|
||||
@@ -25,5 +21,5 @@ NOTE: You can see the zipkin spans without the UI (in logs) if you run the sampl
|
||||
|
||||
image::{github-raw}/docs/src/main/asciidoc/images/zipkin-trace-screenshot.png[Sample Zipkin Screenshot]
|
||||
|
||||
> The fact that the first trace in says "testSleuthMessaging" seems to be a bug in the UI (it has some annotations from that service, but it originates in the "testSleuthRibbon" service).
|
||||
> The fact that the first trace in says "testSleuthMessaging" seems to be a bug in the UI (it has some annotations from that service, but it originates in the "testSleuthMessaging" service).
|
||||
|
||||
|
||||
@@ -69,10 +69,8 @@
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- Including Eureka is a good test, even if there is no service to connect
|
||||
with because it exercises slightly different code paths in Ribbon -->
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
|
||||
@@ -59,8 +59,7 @@ import static org.assertj.core.api.BDDAssertions.then;
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@SpringBootTest(classes = { AppConfig.class, Application.class },
|
||||
webEnvironment = WebEnvironment.RANDOM_PORT,
|
||||
properties = { "ribbon.eureka.enabled=false", "feign.hystrix.enabled=false" })
|
||||
webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class Issue410Tests {
|
||||
|
||||
private static final Log log = LogFactory
|
||||
|
||||
@@ -40,9 +40,7 @@ import static org.assertj.core.api.BDDAssertions.then;
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@SpringBootTest(classes = Issue546TestsApp.class,
|
||||
properties = { "ribbon.eureka.enabled=false", "feign.hystrix.enabled=false",
|
||||
"server.port=0" },
|
||||
@SpringBootTest(classes = Issue546TestsApp.class, properties = { "server.port=0" },
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class Issue546Tests {
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ class MyDelegateClient implements Client {
|
||||
|
||||
}
|
||||
|
||||
@FeignClient(name = "foo", url = "https://non.existing.url")
|
||||
@FeignClient(name = "foo", url = "http://foo")
|
||||
interface MyNameRemote {
|
||||
|
||||
@RequestMapping(value = "/", method = RequestMethod.GET)
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import brave.Tracing;
|
||||
import brave.http.HttpRequest;
|
||||
import brave.sampler.Sampler;
|
||||
import brave.sampler.SamplerFunction;
|
||||
@@ -72,9 +71,6 @@ public class ManuallyCreatedDelegateLoadBalancerFeignClientTests {
|
||||
@Autowired
|
||||
MyDelegateClient myClient;
|
||||
|
||||
@Autowired
|
||||
Tracing tracer;
|
||||
|
||||
@BeforeEach
|
||||
public void open() {
|
||||
this.reporter.clear();
|
||||
@@ -87,7 +83,6 @@ public class ManuallyCreatedDelegateLoadBalancerFeignClientTests {
|
||||
// then(this.myClient.wasCalled()).isTrue();
|
||||
then(this.myDelegateClient.wasCalled()).isTrue();
|
||||
then(response).isEqualTo("foo");
|
||||
// System.out.println("this.myclient.wascalled: " + this.myClient.wasCalled());
|
||||
List<Span> spans = this.reporter.getSpans();
|
||||
// retries
|
||||
then(spans).hasSize(1);
|
||||
@@ -126,8 +121,8 @@ class Application {
|
||||
public MyNameRemote myNameRemote(Client client, Decoder decoder, Encoder encoder,
|
||||
Contract contract) {
|
||||
return Feign.builder().client(client).encoder(encoder).decoder(decoder)
|
||||
.contract(contract).target(new HardCodedTarget<>(MyNameRemote.class,
|
||||
"foo", "https://non.existing.url"));
|
||||
.contract(contract)
|
||||
.target(new HardCodedTarget<>(MyNameRemote.class, "foo", "http://foo"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -167,7 +162,7 @@ class MyDelegateClient implements Client {
|
||||
|
||||
}
|
||||
|
||||
@FeignClient(name = "foo", url = "https://non.existing.url")
|
||||
@FeignClient(name = "foo", url = "http://foo")
|
||||
interface MyNameRemote {
|
||||
|
||||
@RequestMapping(value = "/", method = RequestMethod.GET)
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2019 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
|
||||
*
|
||||
* https://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.feign.issues.issue350;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import brave.Tracing;
|
||||
import brave.sampler.Sampler;
|
||||
import feign.Logger;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import zipkin2.Span;
|
||||
import zipkin2.reporter.Reporter;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration;
|
||||
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
@FeignClient(name = "myFeignClient", url = "localhost:9988")
|
||||
interface MyFeignClient {
|
||||
|
||||
@RequestMapping("/service/ok")
|
||||
String ok();
|
||||
|
||||
@RequestMapping("/service/not-ok")
|
||||
String exp();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
|
||||
@SpringBootTest(classes = Application.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
|
||||
@TestPropertySource(properties = { "ribbon.eureka.enabled=false",
|
||||
"feign.hystrix.enabled=false", "server.port=9988" })
|
||||
public class Issue350Tests {
|
||||
|
||||
TestRestTemplate template = new TestRestTemplate();
|
||||
|
||||
@Autowired
|
||||
Tracing tracer;
|
||||
|
||||
@Autowired
|
||||
ArrayListSpanReporter reporter;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
this.reporter.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_successfully_work_without_hystrix() {
|
||||
this.template.getForEntity("http://localhost:9988/sleuth/test-not-ok",
|
||||
String.class);
|
||||
|
||||
List<Span> spans = this.reporter.getSpans();
|
||||
then(spans).hasSize(1);
|
||||
then(spans.get(0).tags()).containsEntry("http.status_code", "406");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration(exclude = TraceWebServletAutoConfiguration.class)
|
||||
@EnableFeignClients(basePackageClasses = { SleuthTestController.class })
|
||||
class Application {
|
||||
|
||||
@Bean
|
||||
public ServiceTestController serviceTestController() {
|
||||
return new ServiceTestController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SleuthTestController sleuthTestController() {
|
||||
return new SleuthTestController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Logger.Level feignLoggerLevel() {
|
||||
return Logger.Level.FULL;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Sampler defaultSampler() {
|
||||
return Sampler.ALWAYS_SAMPLE;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Reporter<Span> spanReporter() {
|
||||
return new ArrayListSpanReporter();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
@RequestMapping(path = "/service")
|
||||
class ServiceTestController {
|
||||
|
||||
@RequestMapping("/ok")
|
||||
public String ok() throws InterruptedException, ExecutionException {
|
||||
return "I'm OK";
|
||||
}
|
||||
|
||||
@RequestMapping("/not-ok")
|
||||
@ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
|
||||
public String notOk() throws InterruptedException, ExecutionException {
|
||||
return "Not OK";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
@RequestMapping(path = "/sleuth")
|
||||
class SleuthTestController {
|
||||
|
||||
@Autowired
|
||||
private MyFeignClient myFeignClient;
|
||||
|
||||
@RequestMapping("/test-ok")
|
||||
public String ok() throws InterruptedException, ExecutionException {
|
||||
return this.myFeignClient.ok();
|
||||
}
|
||||
|
||||
@RequestMapping("/test-not-ok")
|
||||
public String notOk() throws InterruptedException, ExecutionException {
|
||||
return this.myFeignClient.exp();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -76,8 +76,7 @@ interface MyFeignClient {
|
||||
|
||||
@SpringBootTest(classes = Application.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
|
||||
@TestPropertySource(properties = { "ribbon.eureka.enabled=false",
|
||||
"feign.hystrix.enabled=false", "server.port=9998" })
|
||||
@TestPropertySource(properties = { "server.port=9998" })
|
||||
public class Issue362Tests {
|
||||
|
||||
RestTemplate template = new RestTemplate();
|
||||
|
||||
@@ -61,8 +61,8 @@ interface MyNameRemote {
|
||||
|
||||
@SpringBootTest(classes = Application.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
|
||||
@TestPropertySource(properties = { "spring.application.name=demo-feign-uri",
|
||||
"server.port=9978", "eureka.client.enabled=true", "ribbon.eureka.enabled=true" })
|
||||
@TestPropertySource(
|
||||
properties = { "spring.application.name=demo-feign-uri", "server.port=9978" })
|
||||
public class Issue393Tests {
|
||||
|
||||
RestTemplate template = new RestTemplate();
|
||||
|
||||
@@ -46,7 +46,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
@FeignClient(name = "foo", url = "https://non.existing.url")
|
||||
@FeignClient(name = "foo", url = "http://foo")
|
||||
interface MyNameRemote {
|
||||
|
||||
@RequestMapping(value = "/", method = RequestMethod.GET)
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
|
||||
ribbon:
|
||||
ConnectTimeout: 3000
|
||||
ReadTimeout: 5000
|
||||
|
||||
exceptionService.ribbon:
|
||||
MaxAutoRetries: 3
|
||||
OkToRetryOnAllOperations: true
|
||||
ConnectTimeout: 1
|
||||
ReadTimeout: 1
|
||||
|
||||
eureka.client.enabled: false
|
||||
ribbon.eureka.enabled: false
|
||||
|
||||
logging.level.org.springframework.cloud: DEBUG
|
||||
logging.level.com.netflix.discovery.InstanceInfoReplicator: ERROR
|
||||
logging.level.org.springframework.cloud.sleuth.instrument.web.client.feign: TRACE
|
||||
logging.level.org.springframework.cloud.sleuth.instrument.web.client.feign: TRACE
|
||||
|
||||
Reference in New Issue
Block a user