Skip to content

Commit

Permalink
detect service.name based on build-info.properties
Browse files Browse the repository at this point in the history
  • Loading branch information
zeitlinger committed Feb 12, 2024
1 parent d0763d9 commit 3b4b952
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 24 deletions.
14 changes: 12 additions & 2 deletions instrumentation/spring/spring-boot-autoconfigure/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -445,13 +445,23 @@ export OTEL_RESOURCE_ATTRIBUTES="key1=value1,key2=value2"
The service name is determined by the following precedence, in accordance with the OpenTelemetry
[specification](https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_service_name):

1. `otel.service.name` spring property or `OTEL_SERVICE_NAME` environment variable (highest
1. `otel.service.name` spring property or `OTEL_SERVICE_NAME` environment variable (highest
precedence)
2. `service.name` in `otel.resource.attributes` system/spring property or `OTEL_RESOURCE_ATTRIBUTES`
environment variable
3. `service.name` in `otel.springboot.resource.attributes` system/spring property
4. `spring.application.name` spring property
5. the default value `unknown_service:java` (lowest precedence)
5. `build-info.properties`
6. the default value `unknown_service:java` (lowest precedence)

Use the following snippet in your gradle file to generate the `build-info.properties` file:

```groovy
springBoot {
buildInfo {
}
}
```

##### Exporter Properties

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import com.google.auto.service.AutoService;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ConditionalResourceProvider;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.semconv.ResourceAttributes;
import java.io.IOException;
Expand Down Expand Up @@ -47,7 +46,7 @@
* </ul>
*/
@AutoService(ResourceProvider.class)
public class SpringBootServiceNameDetector implements ConditionalResourceProvider {
public class SpringBootServiceNameDetector implements ResourceProvider {

private static final Logger logger =
Logger.getLogger(SpringBootServiceNameDetector.class.getName());
Expand Down Expand Up @@ -101,17 +100,6 @@ public Resource createResource(ConfigProperties config) {
.orElseGet(Resource::empty);
}

@Override
public boolean shouldApply(ConfigProperties config, Resource resource) {
// we're skipping this provider if the service name was manually set by the user -- no need to
// waste time trying to compute the service name if it's going to be overridden anyway
String serviceName = config.getString("otel.service.name");
Map<String, String> resourceAttributes = config.getMap("otel.resource.attributes");
return serviceName == null
&& !resourceAttributes.containsKey(ResourceAttributes.SERVICE_NAME.getKey())
&& "unknown_service:java".equals(resource.getAttribute(ResourceAttributes.SERVICE_NAME));
}

@Override
public int order() {
// make it run later than the default set of providers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,27 @@
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.resources.ResourceBuilder;
import io.opentelemetry.semconv.ResourceAttributes;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;
import java.util.Properties;
import java.util.logging.Logger;

/**
* Detects <code>service.name</code> and <code>service.version</code> from Spring Boot's <code>
* build-info.properties</code> file.
*
* <p>Use the following snippet in your gradle file to generate the build-info.properties file:
*
* <pre>{@code
* springBoot {
* buildInfo {
* }
* }
* }</pre>
*/
@AutoService(ResourceProvider.class)
public class SpringBootServiceVersionDetector implements ResourceProvider {

Expand All @@ -37,29 +51,41 @@ public SpringBootServiceVersionDetector() {

@Override
public Resource createResource(ConfigProperties config) {
return getServiceVersionFromBuildInfo()
return getPropertiesFromBuildInfo()
.map(
version -> {
logger.log(FINE, "Auto-detected Spring Boot service version: {0}", version);
return Resource.builder().put(ResourceAttributes.SERVICE_VERSION, version).build();
properties -> {
logger.log(FINE, "Auto-detected Spring Boot service version: {0}", properties);
ResourceBuilder builder = Resource.builder();

String version = properties.getProperty("build.version");
if (version != null) {
builder.put(ResourceAttributes.SERVICE_VERSION, version);
}

String name = properties.getProperty("build.name");
if (name != null) {
builder.put(ResourceAttributes.SERVICE_NAME, name);
}

return builder.build();
})
.orElseGet(Resource::empty);
}

private Optional<String> getServiceVersionFromBuildInfo() {
private Optional<Properties> getPropertiesFromBuildInfo() {
try (InputStream in = system.openClasspathResource("META-INF", "build-info.properties")) {
return in != null ? getServiceVersionPropertyFromStream(in) : Optional.empty();
return in != null ? getPropertiesFromStream(in) : Optional.empty();
} catch (Exception e) {
return Optional.empty();
}
}

private static Optional<String> getServiceVersionPropertyFromStream(InputStream in) {
private static Optional<Properties> getPropertiesFromStream(InputStream in) {
Properties properties = new Properties();
try {
// Note: load() uses ISO 8859-1 encoding, same as spring uses by default for property files
properties.load(in);
return Optional.ofNullable(properties.getProperty("build.version"));
return Optional.of(properties);
} catch (IOException e) {
return Optional.empty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package io.opentelemetry.instrumentation.spring.resources;

import static io.opentelemetry.semconv.ResourceAttributes.SERVICE_NAME;
import static io.opentelemetry.semconv.ResourceAttributes.SERVICE_VERSION;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -34,6 +35,7 @@ void givenBuildVersionIsPresentInBuildInfProperties_thenReturnBuildVersion() {
SpringBootServiceVersionDetector guesser = new SpringBootServiceVersionDetector(system);
Resource result = guesser.createResource(config);
assertThat(result.getAttribute(SERVICE_VERSION)).isEqualTo("0.0.2");
assertThat(result.getAttribute(SERVICE_NAME)).isEqualTo("some-name");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
build.artifact=something
build.name=some-name

0 comments on commit 3b4b952

Please sign in to comment.