Merge branch '1.1.x'
This commit is contained in:
@@ -446,6 +446,26 @@ By default Sleuth assumes that when you send a span to Zipkin, you want the span
|
||||
spring.zipkin.service.name: foo
|
||||
----
|
||||
|
||||
=== Customization of reported spans
|
||||
|
||||
Before reporting spans to e.g. Zipkin you can be interested in modifying that span in some way.
|
||||
You can achieve that by using the `SpanAdjuster` interface.
|
||||
|
||||
Example of usage:
|
||||
|
||||
In Sleuth we're generating spans with a fixed name. Some users want to modify the name depending on values
|
||||
of tags. Implementation of the `SpanAdjuster` interface can be used to alter that name. Example:
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
@Bean
|
||||
SpanAdjuster customSpanAdjuster() {
|
||||
return span -> span.toBuilder().name(scrub(span.getName())).build();
|
||||
}
|
||||
----
|
||||
|
||||
This will lead in changing the name of the reported span just before it gets sent to Zipkin.
|
||||
|
||||
=== Host locator
|
||||
|
||||
In order to define the host that is corresponding to a particular span we need to resolve the host name
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Span adjuster that does nothing.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.1.4
|
||||
*/
|
||||
public class NoOpSpanAdjuster implements SpanAdjuster {
|
||||
@Override public Span adjust(Span span) {
|
||||
return span;
|
||||
}
|
||||
}
|
||||
@@ -534,6 +534,13 @@ public class Span implements SpanContext {
|
||||
return new String(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the span to a {@link SpanBuilder} format
|
||||
*/
|
||||
public SpanBuilder toBuilder() {
|
||||
return builder().from(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents given long id as 16-character lower-hex string
|
||||
*
|
||||
@@ -697,6 +704,7 @@ public class Span implements SpanContext {
|
||||
}
|
||||
|
||||
public Span.SpanBuilder parents(Collection<Long> parents) {
|
||||
this.parents.clear();
|
||||
this.parents.addAll(parents);
|
||||
return this;
|
||||
}
|
||||
@@ -707,6 +715,7 @@ public class Span implements SpanContext {
|
||||
}
|
||||
|
||||
public Span.SpanBuilder logs(Collection<Log> logs) {
|
||||
this.logs.clear();
|
||||
this.logs.addAll(logs);
|
||||
return this;
|
||||
}
|
||||
@@ -717,6 +726,7 @@ public class Span implements SpanContext {
|
||||
}
|
||||
|
||||
public Span.SpanBuilder tags(Map<String, String> tags) {
|
||||
this.tags.clear();
|
||||
this.tags.putAll(tags);
|
||||
return this;
|
||||
}
|
||||
@@ -756,6 +766,14 @@ public class Span implements SpanContext {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Span.SpanBuilder from(Span span) {
|
||||
return begin(span.begin).end(span.end).name(span.name)
|
||||
.traceIdHigh(span.traceIdHigh).traceId(span.traceId)
|
||||
.parents(span.getParents()).logs(span.logs).tags(span.tags)
|
||||
.spanId(span.spanId).remote(span.remote).exportable(span.exportable)
|
||||
.processId(span.processId).savedSpan(span.savedSpan);
|
||||
}
|
||||
|
||||
public Span build() {
|
||||
return new Span(this);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Adds ability to adjust a span before reporting it.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.1.4
|
||||
*/
|
||||
public interface SpanAdjuster {
|
||||
/**
|
||||
* You can adjust the {@link Span} by creating a new one using the {@link Span.SpanBuilder}
|
||||
* before reporting it.
|
||||
*
|
||||
* In Sleuth we're generating spans with a fixed name. Some users want to modify the name
|
||||
* depending on some values of tags. Implementation of this interface can be used to alter
|
||||
* then name. Example:
|
||||
*
|
||||
* {@code span -> span.toBuilder().name(scrub(span.getName())).build();}
|
||||
*/
|
||||
Span adjust(Span span);
|
||||
}
|
||||
@@ -23,8 +23,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.sleuth.DefaultSpanNamer;
|
||||
import org.springframework.cloud.sleuth.NoOpSpanAdjuster;
|
||||
import org.springframework.cloud.sleuth.NoOpSpanReporter;
|
||||
import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.SpanAdjuster;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.SpanReporter;
|
||||
import org.springframework.cloud.sleuth.TraceKeys;
|
||||
@@ -83,4 +85,10 @@ public class TraceAutoConfiguration {
|
||||
return new NoOpSpanReporter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public SpanAdjuster defaultSpanAdjuster() {
|
||||
return new NoOpSpanAdjuster();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class NoOpSpanAdjusterTests {
|
||||
@Test
|
||||
public void should_return_same_span() {
|
||||
Span span = Span.builder().spanId(1).build();
|
||||
|
||||
then(new NoOpSpanAdjuster().adjust(span)).isSameAs(span);
|
||||
}
|
||||
}
|
||||
@@ -253,4 +253,29 @@ public class SpanTests {
|
||||
// We round so that we don't confuse "not started" with a short span.
|
||||
assertThat(span.getAccumulatedMicros()).isEqualTo(1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_build_a_span_from_provided_span() throws IOException {
|
||||
Span span = builder().build();
|
||||
|
||||
Span builtSpan = Span.builder().from(span).build();
|
||||
|
||||
assertThat(builtSpan).isEqualTo(span);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_convert_a_span_to_builder() throws IOException {
|
||||
Span.SpanBuilder spanBuilder = builder();
|
||||
Span span = spanBuilder.build();
|
||||
|
||||
Span span2 = span.toBuilder().build();
|
||||
|
||||
assertThat(span).isEqualTo(span2);
|
||||
}
|
||||
|
||||
private Span.SpanBuilder builder() {
|
||||
return Span.builder().name("http:name").traceId(1L).spanId(2L).parent(3L)
|
||||
.begin(1L).end(2L).traceId(3L).exportable(true).parent(4L)
|
||||
.remote(true).tag("tag", "tag").log(new Log(System.currentTimeMillis(), "log"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.commons.util.InetUtils;
|
||||
import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.SpanAdjuster;
|
||||
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
|
||||
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
|
||||
import org.springframework.cloud.sleuth.metric.TraceMetricsAutoConfiguration;
|
||||
@@ -57,9 +58,9 @@ import org.springframework.scheduling.support.PeriodicTrigger;
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({SleuthStreamProperties.class, SamplerProperties.class, ZipkinProperties.class})
|
||||
@EnableConfigurationProperties({ SleuthStreamProperties.class, SamplerProperties.class, ZipkinProperties.class })
|
||||
@AutoConfigureAfter(TraceMetricsAutoConfiguration.class)
|
||||
@AutoConfigureBefore({ChannelBindingAutoConfiguration.class, TraceAutoConfiguration.class, ChannelsEndpointAutoConfiguration.class})
|
||||
@AutoConfigureBefore({ ChannelBindingAutoConfiguration.class, TraceAutoConfiguration.class, ChannelsEndpointAutoConfiguration.class })
|
||||
@EnableBinding(SleuthSource.class)
|
||||
@ConditionalOnProperty(value = "spring.sleuth.stream.enabled", matchIfMissing = true)
|
||||
public class SleuthStreamAutoConfiguration {
|
||||
@@ -79,8 +80,8 @@ public class SleuthStreamAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public StreamSpanReporter sleuthStreamSpanReporter(HostLocator endpointLocator,
|
||||
SpanMetricReporter spanMetricReporter, Environment environment) {
|
||||
return new StreamSpanReporter(endpointLocator, spanMetricReporter, environment);
|
||||
SpanMetricReporter spanMetricReporter, Environment environment, SpanAdjuster spanAdjuster) {
|
||||
return new StreamSpanReporter(endpointLocator, spanMetricReporter, environment, spanAdjuster);
|
||||
}
|
||||
|
||||
@Bean(name = StreamSpanReporter.POLLER)
|
||||
|
||||
@@ -27,7 +27,9 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.commons.util.IdUtils;
|
||||
import org.springframework.cloud.sleuth.Log;
|
||||
import org.springframework.cloud.sleuth.NoOpSpanAdjuster;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanAdjuster;
|
||||
import org.springframework.cloud.sleuth.SpanReporter;
|
||||
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
|
||||
import org.springframework.core.env.Environment;
|
||||
@@ -61,6 +63,7 @@ public class StreamSpanReporter implements SpanReporter {
|
||||
private final HostLocator endpointLocator;
|
||||
private final SpanMetricReporter spanMetricReporter;
|
||||
private final Environment environment;
|
||||
private final SpanAdjuster spanAdjuster;
|
||||
|
||||
@Deprecated
|
||||
public StreamSpanReporter(HostLocator endpointLocator,
|
||||
@@ -68,11 +71,18 @@ public class StreamSpanReporter implements SpanReporter {
|
||||
this(endpointLocator, spanMetricReporter, null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public StreamSpanReporter(HostLocator endpointLocator,
|
||||
SpanMetricReporter spanMetricReporter, Environment environment) {
|
||||
this(endpointLocator, spanMetricReporter, environment, new NoOpSpanAdjuster());
|
||||
}
|
||||
|
||||
public StreamSpanReporter(HostLocator endpointLocator,
|
||||
SpanMetricReporter spanMetricReporter, Environment environment, SpanAdjuster spanAdjuster) {
|
||||
this.endpointLocator = endpointLocator;
|
||||
this.spanMetricReporter = spanMetricReporter;
|
||||
this.environment = environment;
|
||||
this.spanAdjuster = spanAdjuster;
|
||||
}
|
||||
|
||||
public void setQueue(BlockingQueue<Span> queue) {
|
||||
@@ -101,21 +111,23 @@ public class StreamSpanReporter implements SpanReporter {
|
||||
|
||||
@Override
|
||||
public void report(Span span) {
|
||||
if (span.isExportable()) {
|
||||
Span spanToReport = span;
|
||||
if (spanToReport.isExportable()) {
|
||||
try {
|
||||
if (this.environment != null) {
|
||||
processLogs(span);
|
||||
processLogs(spanToReport);
|
||||
}
|
||||
this.queue.add(span);
|
||||
spanToReport = this.spanAdjuster.adjust(spanToReport);
|
||||
this.queue.add(spanToReport);
|
||||
} catch (Exception e) {
|
||||
this.spanMetricReporter.incrementDroppedSpans(1);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("The span " + span + " will not be sent to Zipkin due to [" + e + "]");
|
||||
log.debug("The span " + spanToReport + " will not be sent to Zipkin due to [" + e + "]");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("The span " + span + " will not be sent to Zipkin due to sampling");
|
||||
log.debug("The span " + spanToReport + " will not be sent to Zipkin due to sampling");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,4 +92,23 @@ public class StreamSpanReporterTests {
|
||||
.isNullOrEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void should_adjust_span_before_reporting_it() throws Exception {
|
||||
this.reporter = new StreamSpanReporter(this.endpointLocator, this.spanMetricReporter, null,
|
||||
span -> Span.builder().from(span).name("foo").build());
|
||||
LinkedBlockingQueue<Span> queue = new LinkedBlockingQueue<>(1000);
|
||||
this.reporter.setQueue(queue);
|
||||
Span span = Span.builder().name("bar").exportable(true).build();
|
||||
span.logEvent(Span.CLIENT_SEND);
|
||||
|
||||
this.reporter.report(span);
|
||||
|
||||
assertThat(queue).isNotEmpty();
|
||||
assertThat(queue.poll())
|
||||
.extracting(Span::getName)
|
||||
.filteredOn(o -> o.equals("foo"))
|
||||
.isNotEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.commons.util.InetUtils;
|
||||
import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.SpanAdjuster;
|
||||
import org.springframework.cloud.sleuth.SpanReporter;
|
||||
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
|
||||
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
|
||||
@@ -83,8 +84,8 @@ public class ZipkinAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public SpanReporter zipkinSpanListener(ZipkinSpanReporter reporter, EndpointLocator endpointLocator,
|
||||
Environment environment) {
|
||||
return new ZipkinSpanListener(reporter, endpointLocator, environment);
|
||||
Environment environment, SpanAdjuster spanAdjuster) {
|
||||
return new ZipkinSpanListener(reporter, endpointLocator, environment, spanAdjuster);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -23,7 +23,9 @@ import java.util.Map;
|
||||
|
||||
import org.springframework.cloud.commons.util.IdUtils;
|
||||
import org.springframework.cloud.sleuth.Log;
|
||||
import org.springframework.cloud.sleuth.NoOpSpanAdjuster;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanAdjuster;
|
||||
import org.springframework.cloud.sleuth.SpanReporter;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -54,6 +56,7 @@ public class ZipkinSpanListener implements SpanReporter {
|
||||
|
||||
private final ZipkinSpanReporter reporter;
|
||||
private final Environment environment;
|
||||
private final SpanAdjuster spanAdjuster;
|
||||
/**
|
||||
* Endpoint is the visible IP address of this service, the port it is listening on and
|
||||
* the service name from discovery.
|
||||
@@ -66,11 +69,18 @@ public class ZipkinSpanListener implements SpanReporter {
|
||||
this(reporter, endpointLocator, null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public ZipkinSpanListener(ZipkinSpanReporter reporter, EndpointLocator endpointLocator,
|
||||
Environment environment) {
|
||||
this(reporter, endpointLocator, environment, new NoOpSpanAdjuster());
|
||||
}
|
||||
|
||||
public ZipkinSpanListener(ZipkinSpanReporter reporter, EndpointLocator endpointLocator,
|
||||
Environment environment, SpanAdjuster spanAdjuster) {
|
||||
this.reporter = reporter;
|
||||
this.endpointLocator = endpointLocator;
|
||||
this.environment = environment;
|
||||
this.spanAdjuster = spanAdjuster;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,34 +98,34 @@ public class ZipkinSpanListener implements SpanReporter {
|
||||
// Visible for testing
|
||||
zipkin.Span convert(Span span) {
|
||||
//TODO: Consider adding support for the debug flag (related to #496)
|
||||
Span convertedSpan = this.spanAdjuster.adjust(span);
|
||||
zipkin.Span.Builder zipkinSpan = zipkin.Span.builder();
|
||||
|
||||
Endpoint endpoint = this.endpointLocator.local();
|
||||
processLogs(span, zipkinSpan, endpoint);
|
||||
addZipkinAnnotations(zipkinSpan, span, endpoint);
|
||||
addZipkinBinaryAnnotations(zipkinSpan, span, endpoint);
|
||||
processLogs(convertedSpan, zipkinSpan, endpoint);
|
||||
addZipkinAnnotations(zipkinSpan, convertedSpan, endpoint);
|
||||
addZipkinBinaryAnnotations(zipkinSpan, convertedSpan, endpoint);
|
||||
// In the RPC span model, the client owns the timestamp and duration of the span. If we
|
||||
// were propagated an id, we can assume that we shouldn't report timestamp or duration,
|
||||
// rather let the client do that. Worst case we were propagated an unreported ID and
|
||||
// Zipkin backfills timestamp and duration.
|
||||
if (!span.isRemote()) {
|
||||
zipkinSpan.timestamp(span.getBegin() * 1000L);
|
||||
if (!span.isRunning()) { // duration is authoritative, only write when the span stopped
|
||||
zipkinSpan.duration(calculateDurationInMicros(span));
|
||||
if (!convertedSpan.isRemote()) {
|
||||
zipkinSpan.timestamp(convertedSpan.getBegin() * 1000L);
|
||||
if (!convertedSpan.isRunning()) { // duration is authoritative, only write when the span stopped
|
||||
zipkinSpan.duration(calculateDurationInMicros(convertedSpan));
|
||||
}
|
||||
}
|
||||
zipkinSpan.traceIdHigh(span.getTraceIdHigh());
|
||||
zipkinSpan.traceId(span.getTraceId());
|
||||
if (span.getParents().size() > 0) {
|
||||
if (span.getParents().size() > 1) {
|
||||
zipkinSpan.traceIdHigh(convertedSpan.getTraceIdHigh());
|
||||
zipkinSpan.traceId(convertedSpan.getTraceId());
|
||||
if (convertedSpan.getParents().size() > 0) {
|
||||
if (convertedSpan.getParents().size() > 1) {
|
||||
log.error("Zipkin doesn't support spans with multiple parents. Omitting "
|
||||
+ "other parents for " + span);
|
||||
+ "other parents for " + convertedSpan);
|
||||
}
|
||||
zipkinSpan.parentId(span.getParents().get(0));
|
||||
zipkinSpan.parentId(convertedSpan.getParents().get(0));
|
||||
}
|
||||
zipkinSpan.id(span.getSpanId());
|
||||
if (StringUtils.hasText(span.getName())) {
|
||||
zipkinSpan.name(span.getName());
|
||||
zipkinSpan.id(convertedSpan.getSpanId());
|
||||
if (StringUtils.hasText(convertedSpan.getName())) {
|
||||
zipkinSpan.name(convertedSpan.getName());
|
||||
}
|
||||
return zipkinSpan.build();
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanAdjuster;
|
||||
import org.springframework.cloud.sleuth.SpanReporter;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
|
||||
@@ -292,6 +293,19 @@ public class ZipkinSpanListenerTests {
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_adjust_span_before_reporting_it() {
|
||||
this.parent.logEvent(Span.CLIENT_RECV);
|
||||
ZipkinSpanListener spanListener = new ZipkinSpanListener(this.spanReporter,
|
||||
this.endpointLocator, null, span -> Span.builder().from(span)
|
||||
.name("foo")
|
||||
.build());
|
||||
|
||||
zipkin.Span result = spanListener.convert(this.parent);
|
||||
|
||||
assertThat(result.name).isEqualTo("foo");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
protected static class TestConfiguration {
|
||||
|
||||
Reference in New Issue
Block a user