Skip to content
This repository has been archived by the owner on Jun 24, 2024. It is now read-only.

Added resources as runtimeOnly dependency #14

Merged
merged 6 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.gradle/
build/
.env
.idea/
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dependencies {
implementation "io.opentelemetry:opentelemetry-exporter-otlp-logs:$otelVersion-alpha"
implementation "io.opentelemetry:opentelemetry-exporter-logging" // only for debug
runtimeOnly("io.opentelemetry.instrumentation:opentelemetry-logback-appender-1.0:$otelVersion-alpha")
runtimeOnly "io.opentelemetry.instrumentation:opentelemetry-resources:$otelVersion-alpha"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great finding - didn't know about that!

Just checked out the implementation, and we should probably also use InetAddress.getLocalHost().getHostName() instead of System.getenv("HOSTNAME") as here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The service name is also detected here:

I think the manifest should have priority over the jar name - can you check if that's the case?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might also make sense to describe how the service.name is created from both the manifest and the jar name there.

Copy link
Contributor Author

@kjrun316 kjrun316 May 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took a closer look. Below is the order of precedence for service name

  1. OTEL_SERVICE_NAME
  2. OTEL_RESOURCE_ATTRIBUTES
    a. service_name key:value (manually set)
    b. spring application name
    c. manifest

If none of the above are set the service_name shows as unknown_service:java

Note that JarServiceNameDetector extends ConditionalResourceProvider so it will only be applied if the shouldApply method returns true.

implementation "io.opentelemetry.instrumentation:opentelemetry-micrometer-1.5:$otelVersion-alpha"
implementation "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:$otelVersion-alpha"
runtimeOnly 'io.micrometer:micrometer-tracing-bridge-otel'
Expand Down
31 changes: 22 additions & 9 deletions src/main/java/com/grafana/opentelemetry/GrafanaProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,38 @@ public class GrafanaProperties {
* <p>
* For example, you can add <code>service.version</code> to make it easier to see if a new version of the
* application is causing a problem.
*
* <p>
* The attributes <code>service.name</code>, <code>service.version</code>, and <code>service.instance.id</code>
* are automatically detected as explained below, but if you set the value manually, it will be respected.
* are automatically detected as outlined below.
*
* <p>
* "spring.application.name" in application.properties will be translated to <code>service.name</code>.
* <p>
* You can also add the application name and version to MANIFEST.MF, where they will be copied to
* <code>service.name</code> and <code>service.version</code> respectively.
* <p>
* In gradle, the application name and version can be set as follows:
* For <code>service.name</code> the order of precedence is:
* <ol>
* <li>environment variable OTEL_SERVICE_NAME</li>
kjrun316 marked this conversation as resolved.
Show resolved Hide resolved
* <li>Manually set service_name in grafana.otlp.globalAttributes</li>
* <li>spring.application.name" in application.properties</li>
* <li>'Implementation-Title' in jar's MANIFEST.MF</li>
* </ol>
*
*<p>
* The following block can be added to build.gradle to set the application name and version
* in the jar's MANIFEST.MF:
* <pre>
* bootJar {
* manifest {
* attributes('Implementation-Title': 'Demo Application',
* 'Implementation-Version': version)
* 'Implementation-Version': version)
* }
* }
* </pre>
* The environment variables HOST or HOSTNAME will be translated to <code>service.instance.id</code>.
* The <code>service.instance.id</code> attribute will be set if any of the following return a value.
* The list is in order of precedence.
* <ol>
* <li>InetAddress.getLocalHost().getHostName()</li>
* <li>environment variable HOSTNAME</li>
* <li>environment variable HOST</li>
* </ol>
*/
private final Map<String, String> globalAttributes = new HashMap<>();

Expand Down
20 changes: 14 additions & 6 deletions src/main/java/com/grafana/opentelemetry/OpenTelemetryConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
Expand Down Expand Up @@ -117,12 +119,12 @@ static Optional<String> getEndpoint(String endpoint, String zone, Optional<Strin
}
} else {
if (hasZone) {
logger.warn("ignoring grafana.otlp.cloud.zone, because grafana.otlp.onprem.endpoint was found");
logger.warn("ignoring grafana.otlp.cloud.zone, because grafana.otlp.cloud.instanceId was not found");
zeitlinger marked this conversation as resolved.
Show resolved Hide resolved
}
if (hasEndpoint) {
return Optional.of(endpoint);
} else {
logger.warn("please specify grafana.otlp.onprem.endpoint");
logger.info("grafana.otlp.onprem.endpoint not found, using default endpoint for otel.exporter.otlp.protocol");
}
}
return Optional.empty();
Expand Down Expand Up @@ -169,11 +171,17 @@ private static String getResourceAttributes(GrafanaProperties properties, String
// ignore error reading manifest
}

updateResourceAttribute(resourceAttributes, ResourceAttributes.SERVICE_NAME, applicationName,
manifestApplicationName);
updateResourceAttribute(resourceAttributes, ResourceAttributes.SERVICE_NAME, applicationName, manifestApplicationName);
updateResourceAttribute(resourceAttributes, ResourceAttributes.SERVICE_VERSION, manifestApplicationVersion);
updateResourceAttribute(resourceAttributes, ResourceAttributes.SERVICE_INSTANCE_ID, System.getenv("HOSTNAME"),
System.getenv("HOST"));

String hostName;
try {
hostName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
hostName = System.getenv("HOSTNAME");
}
updateResourceAttribute(resourceAttributes, ResourceAttributes.SERVICE_INSTANCE_ID,
hostName, System.getenv("HOST"));

return resourceAttributes.entrySet().stream()
.map(e -> String.format("%s=%s", e.getKey(), e.getValue()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,13 @@ private static Stream<Arguments> basicAuthCases() {

@ParameterizedTest(name = "{0}")
@MethodSource("endpointCases")
void getEndpoint(String name, Optional<String> expected, String expectedOutput,
String zone, String endpoint, Optional<String> authHeader, CapturedOutput output) {
void getEndpoint(String name,
Optional<String> expected,
String expectedOutput,
String zone,
String endpoint,
Optional<String> authHeader,
CapturedOutput output) {
Assertions.assertThat(OpenTelemetryConfig.getEndpoint(endpoint, zone, authHeader)).isEqualTo(expected);
Assertions.assertThat(output).contains(expectedOutput);
}
Expand All @@ -85,24 +90,24 @@ private static Stream<Arguments> endpointCases() {
Arguments.of("only zone",
Optional.of("https://otlp-gateway-zone.grafana.net/otlp"), "",
"zone", "", Optional.of("apiKey")),
Arguments.of("only endpoint",
Arguments.of("only onprem endpoint",
Optional.of("endpoint"), "",
"", "endpoint", Optional.empty()),
Arguments.of("both with cloud",
Optional.of("https://otlp-gateway-zone.grafana.net/otlp"),
"ignoring grafana.otlp.onprem.endpoint, because grafana.otlp.cloud.instanceId was found",
"zone", "endpoint", Optional.of("key")),
Arguments.of("both without cloud",
Arguments.of("zone without instanceId",
Optional.of("endpoint"),
"ignoring grafana.otlp.cloud.zone, because grafana.otlp.onprem.endpoint was found",
"ignoring grafana.otlp.cloud.zone, because grafana.otlp.cloud.instanceId was not found",
"zone", "endpoint", Optional.empty()),
Arguments.of("missing zone",
Optional.empty(),
"please specify grafana.otlp.cloud.zone",
" ", " ", Optional.of("key")),
Arguments.of("missing endpoint",
Arguments.of("onprem endpoint not set",
Optional.empty(),
"please specify grafana.otlp.onprem.endpoint",
"grafana.otlp.onprem.endpoint not found, using default endpoint for otel.exporter.otlp.protocol",
" ", " ", Optional.empty())
);
}
Expand Down