Merge branch '2.2.x'

This commit is contained in:
Marcin Grzejszczak
2021-03-29 15:00:54 +02:00
6 changed files with 79 additions and 6 deletions

View File

@@ -62,6 +62,7 @@
|spring.sleuth.web.webclient.enabled | `true` | Enable tracing instrumentation for WebClient.
|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.api-path | | The API path to append to baseUrl (above) as suffix. This applies if you use other monitoring tools, such as New Relic. The trace API doesn't need the API path, so you can set it to blank ("") in the configuration.
|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/).
|spring.zipkin.compression.enabled | `false` |
|spring.zipkin.discovery-client-enabled | | If set to {@code false}, will treat the {@link ZipkinProperties#baseUrl} as a URL always.

View File

@@ -316,6 +316,13 @@ object, you will have to create a bean of `zipkin2.reporter.Sender` type.
}
----
By default, api path will be set to `api/v2/spans` or `api/v1/spans` depending on the encoder version. If you want to use a custom api path, you can configure it using the following property (empty case, set ""):
[source,yaml]
----
spring.zipkin.api-path: v2/path2
----
[[features-zipkin-custom-service-name]]
=== Custom service name

View File

@@ -54,7 +54,7 @@ class ZipkinRestTemplateSenderConfiguration {
ZipkinUrlExtractor extractor) {
RestTemplate restTemplate = new ZipkinRestTemplateWrapper(zipkin, extractor);
restTemplate = zipkinRestTemplateCustomizer.customizeTemplate(restTemplate);
return new RestTemplateSender(restTemplate, zipkin.getBaseUrl(), zipkin.getEncoder());
return new RestTemplateSender(restTemplate, zipkin.getBaseUrl(), zipkin.getApiPath(), zipkin.getEncoder());
}
@Bean

View File

@@ -19,6 +19,7 @@ package org.springframework.cloud.sleuth.zipkin2;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Objects;
import zipkin2.Call;
import zipkin2.Callback;
@@ -59,20 +60,28 @@ public class RestTemplateSender extends Sender {
*/
transient boolean closeCalled;
@Deprecated
public RestTemplateSender(RestTemplate restTemplate, String baseUrl, BytesEncoder<Span> encoder) {
this(restTemplate, baseUrl, "", encoder);
}
public RestTemplateSender(RestTemplate restTemplate, String baseUrl, String apiPath, BytesEncoder<Span> encoder) {
this.restTemplate = restTemplate;
this.encoding = encoder.encoding();
if (encoder.equals(JSON_V2)) {
this.mediaType = MediaType.APPLICATION_JSON;
this.url = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "api/v2/spans";
this.url = buildUrlWithCustomPathIfNecessary(baseUrl, apiPath,
baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "api/v2/spans");
}
else if (this.encoding == Encoding.PROTO3) {
this.mediaType = MediaType.parseMediaType("application/x-protobuf");
this.url = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "api/v2/spans";
this.url = buildUrlWithCustomPathIfNecessary(baseUrl, apiPath,
baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "api/v2/spans");
}
else if (this.encoding == Encoding.JSON) {
this.mediaType = MediaType.APPLICATION_JSON;
this.url = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "api/v1/spans";
this.url = buildUrlWithCustomPathIfNecessary(baseUrl, apiPath,
baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "api/v1/spans");
}
else {
throw new UnsupportedOperationException("Unsupported encoding: " + this.encoding.name());
@@ -80,6 +89,16 @@ public class RestTemplateSender extends Sender {
this.messageEncoder = BytesMessageEncoder.forEncoding(this.encoding);
}
private String buildUrlWithCustomPathIfNecessary(final String baseUrl, final String customApiPath,
final String defaultUrl) {
if (Objects.nonNull(customApiPath)) {
return baseUrl
+ (baseUrl.endsWith("/") || customApiPath.startsWith("/") || customApiPath.isEmpty() ? "" : "/")
+ customApiPath;
}
return defaultUrl;
}
@Override
public Encoding encoding() {
return this.encoding;

View File

@@ -37,6 +37,13 @@ public class ZipkinProperties {
*/
private String baseUrl = "http://localhost:9411/";
/**
* The API path to append to baseUrl (above) as suffix. This applies if you use other
* monitoring tools, such as New Relic. The trace API doesn't need the API path, so
* you can set it to blank ("") in the configuration.
*/
private String apiPath = null;
/**
* If set to {@code false}, will treat the {@link ZipkinProperties#baseUrl} as a URL
* always.
@@ -84,6 +91,14 @@ public class ZipkinProperties {
this.baseUrl = baseUrl;
}
public String getApiPath() {
return this.apiPath;
}
public void setApiPath(String apiPath) {
this.apiPath = apiPath;
}
public boolean isEnabled() {
return this.enabled;
}

View File

@@ -50,7 +50,7 @@ public class RestTemplateSenderTest {
String endpoint = this.server.url("/api/v2/spans").toString();
RestTemplateSender sender = new RestTemplateSender(new RestTemplate(), this.endpoint, JSON_V2);
RestTemplateSender sender = new RestTemplateSender(new RestTemplate(), this.endpoint, null, JSON_V2);
@AfterEach
void clean() throws IOException {
@@ -74,7 +74,7 @@ public class RestTemplateSenderTest {
@Test
public void proto3() throws Exception {
this.server.enqueue(new MockResponse());
this.sender = new RestTemplateSender(new RestTemplate(), this.endpoint, PROTO3);
this.sender = new RestTemplateSender(new RestTemplate(), this.endpoint, "", PROTO3);
send(SPAN).execute();
@@ -85,6 +85,37 @@ public class RestTemplateSenderTest {
assertThat(request.getBody().readByteArray()).containsExactly(SpanBytesEncoder.PROTO3.encode(SPAN));
}
@Test
public void testWhereApiIsSetNonEmpty() {
final String mockedApiPath = "/test/v2";
final RestTemplateSender senderWithMockedApiPath = new RestTemplateSender(new RestTemplate(), this.endpoint,
mockedApiPath, JSON_V2);
assertThat(senderWithMockedApiPath.toString())
.isEqualTo("RestTemplateSender{" + this.endpoint + mockedApiPath + "}");
}
@Test
public void testWhereApiIsSetToEmpty() {
final String mockedApiPath = "";
final RestTemplateSender senderWithMockedApiPath = new RestTemplateSender(new RestTemplate(), this.endpoint,
mockedApiPath, JSON_V2);
assertThat(senderWithMockedApiPath.toString()).isEqualTo("RestTemplateSender{" + this.endpoint + "}");
}
/**
* The output of toString() on {@link Sender} implementations appears in thread names
* created by {@link AsyncZipkinSpanHandler}. Since thread names are likely to be
* exposed in logs and other monitoring tools, care should be taken to ensure the
* toString() output is a reasonable length and does not contain sensitive
* information.
*/
@Test
public void toStringContainsOnlySenderTypeAndEndpoint() {
assertThat(sender.toString()).isEqualTo("RestTemplateSender{" + this.endpoint + "/api/v2/spans}");
}
Call<Void> send(Span... spans) {
SpanBytesEncoder bytesEncoder = this.sender.encoding() == Encoding.JSON ? SpanBytesEncoder.JSON_V2
: SpanBytesEncoder.PROTO3;