From 409471543e41d9620cbff8726f3ae647308996d4 Mon Sep 17 00:00:00 2001 From: Anna Nosek Date: Fri, 16 Jul 2021 07:37:17 +0200 Subject: [PATCH] Test and document otel.javaagent.configuration-file (#3585) * test and document configuration file property * use TemporaryFolder rule, documentation changes after review --- docs/agent-config.md | 18 ++++ .../tooling/config/ConfigInitializer.java | 8 +- .../config/ConfigurationFileTest.groovy | 88 +++++++++++++++++++ 3 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 javaagent-tooling/src/test/groovy/io/opentelemetry/javaagent/tooling/config/ConfigurationFileTest.groovy diff --git a/docs/agent-config.md b/docs/agent-config.md index 8bf41ed6c8d0..c347c63ed7da 100644 --- a/docs/agent-config.md +++ b/docs/agent-config.md @@ -10,6 +10,7 @@ Please report any bugs or unexpected behavior you find. ## Contents * [SDK Autoconfiguration](#sdk-autoconfiguration) +* [Configuring the agent](#configuring-the-agent) * [Peer service name](#peer-service-name) * [DB statement sanitization](#db-statement-sanitization) * [Suppressing specific auto-instrumentation](#suppressing-specific-auto-instrumentation) @@ -35,6 +36,23 @@ Here are some quick links into those docs for the configuration options for spec * [Span limits](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure/README.md#span-limits) * [Using SPI to further configure the SDK](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure/README.md#customizing-the-opentelemetry-sdk) +## Configuring the agent + +The agent can consume configuration from one or more of the following sources (ordered from highest to lowest priority): +* system properties +* environment variables +* the [configuration file](#configuration-file) +* the [`ConfigPropertySource`](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/config/ConfigPropertySource.java) SPI + +### Configuration file + +You can provide a path to agent configuration file by setting the corresponding property. + +| System property | Environment variable | Description | +|--------------------------------------|--------------------------------------|----------------------------------------------------------------------------------| +| `otel.javaagent.configuration-file` | `OTEL_JAVAAGENT_CONFIGURATION_FILE` | Path to valid Java properties file which contains the javaagent configuration.| + + ## Peer service name The [peer service name](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/span-general.md#general-remote-service-attributes) is the name of a remote service being connected to. It corresponds to `service.name` in the [Resource](https://github.com/open-telemetry/opentelemetry-specification/tree/master/specification/resource/semantic_conventions#service) for the local service. diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigInitializer.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigInitializer.java index 5d4db5f86494..7d2fba7473a9 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigInitializer.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigInitializer.java @@ -22,8 +22,9 @@ public final class ConfigInitializer { private static final Logger logger = LoggerFactory.getLogger(ConfigInitializer.class); - private static final String CONFIGURATION_FILE_PROPERTY = "otel.javaagent.configuration-file"; - private static final String CONFIGURATION_FILE_ENV_VAR = "OTEL_JAVAAGENT_CONFIGURATION_FILE"; + // visible for testing + static final String CONFIGURATION_FILE_PROPERTY = "otel.javaagent.configuration-file"; + static final String CONFIGURATION_FILE_ENV_VAR = "OTEL_JAVAAGENT_CONFIGURATION_FILE"; public static void initialize() { Config.internalInitializeConfig(create(loadSpiConfiguration(), loadConfigurationFile())); @@ -54,7 +55,8 @@ private static Properties loadSpiConfiguration() { * @return The {@link Properties} object. the returned instance might be empty of file does not * exist or if it is in a wrong format. */ - private static Properties loadConfigurationFile() { + // visible for testing + static Properties loadConfigurationFile() { Properties properties = new Properties(); // Reading from system property first and from env after diff --git a/javaagent-tooling/src/test/groovy/io/opentelemetry/javaagent/tooling/config/ConfigurationFileTest.groovy b/javaagent-tooling/src/test/groovy/io/opentelemetry/javaagent/tooling/config/ConfigurationFileTest.groovy new file mode 100644 index 000000000000..a168c31856e4 --- /dev/null +++ b/javaagent-tooling/src/test/groovy/io/opentelemetry/javaagent/tooling/config/ConfigurationFileTest.groovy @@ -0,0 +1,88 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.tooling.config + +import org.junit.Rule +import org.junit.contrib.java.lang.system.EnvironmentVariables +import org.junit.contrib.java.lang.system.RestoreSystemProperties +import org.junit.rules.TemporaryFolder +import spock.lang.Specification + +class ConfigurationFileTest extends Specification { + + @Rule + public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties() + @Rule + public final EnvironmentVariables environmentVariables = new EnvironmentVariables() + @Rule + public final TemporaryFolder tmpFolder = new TemporaryFolder() + + def "should use env property"() { + given: + def path = createFile("config", "property1=val-env") + environmentVariables.set(ConfigInitializer.CONFIGURATION_FILE_ENV_VAR, path) + + when: + def properties = ConfigInitializer.loadConfigurationFile() + + then: + properties.get("property1") == "val-env" + } + + def "should use system property"() { + given: + def path = createFile("config", "property1=val-sys") + System.setProperty(ConfigInitializer.CONFIGURATION_FILE_PROPERTY, path) + + when: + def properties = ConfigInitializer.loadConfigurationFile() + + then: + properties.get("property1") == "val-sys" + } + + def "system property should take precedence over env property"() { + given: + def pathEnv = createFile("configEnv", "property1=val-env") + def pathSys = createFile("configSys", "property1=val-sys") + + environmentVariables.set(ConfigInitializer.CONFIGURATION_FILE_ENV_VAR, pathEnv) + System.setProperty(ConfigInitializer.CONFIGURATION_FILE_PROPERTY, pathSys) + + when: + def properties = ConfigInitializer.loadConfigurationFile() + + then: + properties.get("property1") == "val-sys" + } + + + def "should return empty properties if file does not exist"() { + given: + environmentVariables.set(ConfigInitializer.CONFIGURATION_FILE_ENV_VAR, "somePath") + + when: + def properties = ConfigInitializer.loadConfigurationFile() + + then: + !properties.propertyNames().hasMoreElements() + } + + def "should return empty properties if property is not set"() { + when: + def properties = ConfigInitializer.loadConfigurationFile() + + then: + !properties.propertyNames().hasMoreElements() + } + + def createFile(String name, String contents){ + def file = tmpFolder.newFile(name) + file.write(contents) + return file.getAbsolutePath() + } + +}