Skip to content

Commit d3c8219

Browse files
Merge pull request #13 from spring-cloud-incubator/resource_customizer
Resource customizer
2 parents bbde7a0 + 3ba001a commit d3c8219

File tree

5 files changed

+84
-6
lines changed

5 files changed

+84
-6
lines changed

docs/src/main/asciidoc/project-features.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ We're providing an Slf4j integration via a `SpanProcessor` that injects to and r
4141
If it's there on the classpath, we integrate with the `LoggingSpanExporter`.
4242
You can disable that integration via the `spring.sleuth.otel.log.exporter.enabled=false` property.
4343

44+
[[features-otel-resource-customization]]
45+
=== OpenTelemetry Resource Customization
46+
47+
OpenTelemetry provides a `Resource` abstraction which captures identifying information about the entities for which signals (stats or traces) are reported. If you wish to customize that `Resource` you can register as a bean an implementation of the `ResourceCustomizer` interface.
48+
4449
[[features-otel-opentracing]]
4550
=== OpenTelemetry Opentracing
4651

spring-cloud-sleuth-otel-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/otel/OtelAutoConfiguration.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,18 @@ SdkTracerProvider otelTracerProvider(SpanLimits spanLimits, ObjectProvider<List<
100100

101101
@Bean
102102
@ConditionalOnMissingBean
103-
Resource otelResource(Environment env) {
104-
// todo: populate the resource with the right stuff (service.name, etc)
105-
// this was the code in the zipkin exporter configuration previously:
106-
// env.getProperty("spring.application.name", env.getProperty(
107-
// "spring.zipkin.service.name", ZipkinSpanExporter.DEFAULT_SERVICE_NAME)
103+
Resource otelResource(Environment env, ObjectProvider<List<ResourceCustomizer>> resourceCustomizerProvider) {
108104
String applicationName = env.getProperty("spring.application.name");
105+
Resource resource = defaultResource(applicationName);
106+
List<ResourceCustomizer> resourceCustomizers = resourceCustomizerProvider.getIfAvailable(ArrayList::new);
107+
for (ResourceCustomizer customizer : resourceCustomizers) {
108+
Resource customized = customizer.customize(resource);
109+
resource = resource.merge(customized);
110+
}
111+
return resource;
112+
}
113+
114+
private Resource defaultResource(String applicationName) {
109115
if (applicationName == null) {
110116
return Resource.getDefault();
111117
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2013-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.sleuth.autoconfig.otel;
18+
19+
import io.opentelemetry.sdk.resources.Resource;
20+
21+
/**
22+
* Allows to customize the {@link Resource}.
23+
*
24+
* @author Marcin Grzejszczak
25+
* @since 1.0.0
26+
*/
27+
@FunctionalInterface
28+
public interface ResourceCustomizer {
29+
30+
/**
31+
* Customizes the resource or returns itself if there's nothing to customize.
32+
* @param resource - resource to customize
33+
* @return resource to be merged with the customized resource
34+
*/
35+
Resource customize(Resource resource);
36+
37+
}

spring-cloud-sleuth-otel-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/otel/zipkin2/ZipkinOtelAutoConfiguration.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,19 @@
1616

1717
package org.springframework.cloud.sleuth.autoconfig.otel.zipkin2;
1818

19+
import io.opentelemetry.api.common.Attributes;
1920
import io.opentelemetry.api.trace.Tracer;
2021
import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter;
22+
import io.opentelemetry.sdk.resources.Resource;
23+
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
2124
import zipkin2.reporter.Sender;
2225

2326
import org.springframework.beans.factory.annotation.Qualifier;
2427
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
2528
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2629
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
2730
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
31+
import org.springframework.cloud.sleuth.autoconfig.otel.ResourceCustomizer;
2832
import org.springframework.cloud.sleuth.autoconfig.zipkin2.ZipkinAutoConfiguration;
2933
import org.springframework.cloud.sleuth.zipkin2.DefaultZipkinRestTemplateCustomizer;
3034
import org.springframework.cloud.sleuth.zipkin2.EndpointLocator;
@@ -62,11 +66,22 @@ static class ZipkinConfiguration {
6266
@Bean
6367
@ConditionalOnMissingBean
6468
ZipkinSpanExporter otelZipkinSpanExporter(ZipkinProperties zipkinProperties,
65-
@Qualifier(ZipkinAutoConfiguration.SENDER_BEAN_NAME) Sender sender, Environment env) {
69+
@Qualifier(ZipkinAutoConfiguration.SENDER_BEAN_NAME) Sender sender) {
6670
return ZipkinSpanExporter.builder().setEndpoint(zipkinProperties.getBaseUrl() + "api/v2/spans")
6771
.setSender(sender).setEncoder(zipkinProperties.getEncoder()).build();
6872
}
6973

74+
@Bean
75+
ResourceCustomizer zipkinResourceCustomizer(Environment environment) {
76+
return resource -> {
77+
String zipkinServiceName = environment.getProperty("spring.zipkin.service.name");
78+
if (zipkinServiceName == null) {
79+
return resource;
80+
}
81+
return Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, zipkinServiceName));
82+
};
83+
}
84+
7085
}
7186

7287
}

spring-cloud-sleuth-otel-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/otel/zipkin2/ZipkinSamplerTests.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.cloud.sleuth.autoconfig.otel.zipkin2;
1818

19+
import io.opentelemetry.api.common.AttributeKey;
20+
import io.opentelemetry.sdk.resources.Resource;
1921
import org.assertj.core.api.BDDAssertions;
2022
import org.junit.jupiter.api.Test;
2123

@@ -45,6 +47,19 @@ void should_set_sampler_to_non_off_when_zipkin_handler_on_classpath_for_otel() {
4547
});
4648
}
4749

50+
@Test
51+
void should_set_service_name_to_zipkin_service_name() {
52+
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
53+
.withPropertyValues("spring.sleuth.tracer.mode=AUTO", "spring.application.name=foo",
54+
"spring.zipkin.service.name=bar")
55+
.withConfiguration(AutoConfigurations.of(TestConfig.class));
56+
57+
contextRunner.run(context -> {
58+
Resource resource = context.getBean(Resource.class);
59+
BDDAssertions.then(resource.getAttributes().get(AttributeKey.stringKey("service.name"))).isEqualTo("bar");
60+
});
61+
}
62+
4863
@Configuration(proxyBeanMethods = false)
4964
@EnableAutoConfiguration
5065
static class TestConfig {

0 commit comments

Comments
 (0)