diff --git a/CHANGELOG.md b/CHANGELOG.md index d04634b7e9..9737217043 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Add support for Spring's JMS flavor - instrumenting `org.springframework.jms.listener.SessionAwareMessageListener` * Add support to legacy ApacheHttpClient APIs (which adds support to Axis2 configured to use ApacheHttpClient) * Added support for setting `server_urls` dynamically via properties file [#723](https://github.com/elastic/apm-agent-java/issues/723) + * Add [`config_file`](https://www.elastic.co/guide/en/apm/agent/java/current/config-core.html#config-config-file) option ## Bug Fixes * Some JMS Consumers and Producers are filtered due to class name filtering in instrumentation matching diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java index 4677d7d008..9ee301d357 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java @@ -24,6 +24,7 @@ */ package co.elastic.apm.agent.configuration; +import co.elastic.apm.agent.bci.ElasticApmAgent; import co.elastic.apm.agent.bci.methodmatching.MethodMatcher; import co.elastic.apm.agent.bci.methodmatching.configuration.MethodMatcherValueConverter; import co.elastic.apm.agent.configuration.converter.TimeDuration; @@ -36,6 +37,7 @@ import org.stagemonitor.configuration.converter.ListValueConverter; import org.stagemonitor.configuration.converter.MapValueConverter; import org.stagemonitor.configuration.converter.StringValueConverter; +import org.stagemonitor.configuration.source.ConfigurationSource; import javax.annotation.Nullable; import java.util.Arrays; @@ -45,6 +47,7 @@ import java.util.Map; import static co.elastic.apm.agent.configuration.validation.RangeValidator.isInRange; +import static co.elastic.apm.agent.logging.LoggingConfiguration.AGENT_HOME_PLACEHOLDER; public class CoreConfiguration extends ConfigurationOptionProvider { @@ -53,6 +56,8 @@ public class CoreConfiguration extends ConfigurationOptionProvider { public static final String SERVICE_NAME = "service_name"; public static final String SAMPLE_RATE = "transaction_sample_rate"; private static final String CORE_CATEGORY = "Core"; + public static final String DEFAULT_CONFIG_FILE = AGENT_HOME_PLACEHOLDER + "/elasticapm.properties"; + public static final String CONFIG_FILE = "config_file"; private final ConfigurationOption active = ConfigurationOption.booleanOption() .key(ACTIVE) .configurationCategory(CORE_CATEGORY) @@ -360,6 +365,14 @@ public class CoreConfiguration extends ConfigurationOptionProvider { .description("Disables the collection of breakdown metrics (`span.self_time`)") .buildWithDefault(true); + private final ConfigurationOption configFileLocation = ConfigurationOption.stringOption() + .key(CONFIG_FILE) + .configurationCategory(CORE_CATEGORY) + .description("Sets the path of the agent config file.\n" + + "The special value `_AGENT_HOME_` is a placeholder for the folder the elastic-apm-agent.jar is in.\n" + + "The location can either be in the classpath of the application or on the file system.") + .buildWithDefault(DEFAULT_CONFIG_FILE); + public boolean isActive() { return active.get(); } @@ -450,4 +463,29 @@ public Map getGlobalLabels() { public boolean isBreakdownMetricsEnabled() { return breakdownMetrics.get(); } + + /* + * Makes sure to not initialize ConfigurationOption, which would initialize the logger + */ + @Nullable + public static String getConfigFileLocation(List configurationSources) { + String configFileLocation = DEFAULT_CONFIG_FILE; + for (ConfigurationSource configurationSource : configurationSources) { + String valueFromSource = configurationSource.getValue(CONFIG_FILE); + if (valueFromSource != null) { + configFileLocation = valueFromSource; + break; + } + } + if (configFileLocation.contains(AGENT_HOME_PLACEHOLDER)) { + String agentHome = ElasticApmAgent.getAgentHome(); + if (agentHome != null) { + return configFileLocation.replace(AGENT_HOME_PLACEHOLDER, agentHome); + } else { + return null; + } + } else { + return configFileLocation; + } + } } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracerBuilder.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracerBuilder.java index 6871839c0f..2081274460 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracerBuilder.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracerBuilder.java @@ -24,7 +24,6 @@ */ package co.elastic.apm.agent.impl; -import co.elastic.apm.agent.bci.ElasticApmAgent; import co.elastic.apm.agent.configuration.AgentArgumentsConfigurationSource; import co.elastic.apm.agent.configuration.ApmServerConfigurationSource; import co.elastic.apm.agent.configuration.CoreConfiguration; @@ -35,7 +34,6 @@ import co.elastic.apm.agent.impl.stacktrace.StacktraceConfiguration; import co.elastic.apm.agent.logging.LoggingConfiguration; import co.elastic.apm.agent.report.ApmServerClient; -import co.elastic.apm.agent.report.ApmServerHealthChecker; import co.elastic.apm.agent.report.Reporter; import co.elastic.apm.agent.report.ReporterConfiguration; import co.elastic.apm.agent.report.ReporterFactory; @@ -149,6 +147,9 @@ private ConfigurationRegistry getDefaultConfigurationRegistry(List getConfigSources(@Nullable String agentArguments) { List result = new ArrayList<>(); if (agentArguments != null && !agentArguments.isEmpty()) { @@ -167,9 +168,9 @@ public String getName() { return "Inline configuration"; } }); - String agentHome = ElasticApmAgent.getAgentHome(); - if (agentHome != null && PropertyFileConfigurationSource.isPresent(agentHome + "/elasticapm.properties")) { - result.add(new PropertyFileConfigurationSource(agentHome + "/elasticapm.properties")); + String configFileLocation = CoreConfiguration.getConfigFileLocation(result); + if (configFileLocation != null && PropertyFileConfigurationSource.isPresent(configFileLocation)) { + result.add(new PropertyFileConfigurationSource(configFileLocation)); } // looks if we can find a elasticapm.properties on the classpath // mainly useful for unit tests diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/logging/LoggingConfiguration.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/logging/LoggingConfiguration.java index f0ae02c2fa..1bbd5935c1 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/logging/LoggingConfiguration.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/logging/LoggingConfiguration.java @@ -59,7 +59,7 @@ public class LoggingConfiguration extends ConfigurationOptionProvider { private static final String DEFAULT_LOG_FILE = SYSTEM_OUT; private static final String LOGGING_CATEGORY = "Logging"; - private static final String AGENT_HOME_PLACEHOLDER = "_AGENT_HOME_"; + public static final String AGENT_HOME_PLACEHOLDER = "_AGENT_HOME_"; private static final String DEPRECATED_LOG_LEVEL_KEY = "logging.log_level"; private static final String DEPRECATED_LOG_FILE_KEY = "logging.log_file"; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/ElasticApmTracerBuilderTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/ElasticApmTracerBuilderTest.java new file mode 100644 index 0000000000..9cd8211cf2 --- /dev/null +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/ElasticApmTracerBuilderTest.java @@ -0,0 +1,62 @@ +/*- + * #%L + * Elastic APM Java agent + * %% + * Copyright (C) 2018 - 2019 Elastic and contributors + * %% + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * #L% + */ +package co.elastic.apm.agent.impl; + +import co.elastic.apm.agent.configuration.CoreConfiguration; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.stagemonitor.configuration.ConfigurationRegistry; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class ElasticApmTracerBuilderTest { + + + @AfterEach + void tearDown() { + System.clearProperty("elastic.apm." + CoreConfiguration.CONFIG_FILE); + } + + @Test + void testConfigFileLocation(@TempDir Path tempDir) throws IOException { + Path file = Files.createFile(tempDir.resolve("elastic-apm-test.properties")); + Files.write(file, List.of("instrument=false")); + System.setProperty("elastic.apm." + CoreConfiguration.CONFIG_FILE, file.toString()); + + ConfigurationRegistry configurationRegistry = new ElasticApmTracerBuilder().build().getConfigurationRegistry(); + CoreConfiguration config = configurationRegistry.getConfig(CoreConfiguration.class); + + // tests that changing non-dynamic properties also works + assertThat(config.isInstrument()).isFalse(); + configurationRegistry.getString(CoreConfiguration.CONFIG_FILE); + assertThat(configurationRegistry.getString(CoreConfiguration.CONFIG_FILE)).isEqualTo(file.toString()); + } +} diff --git a/docs/configuration.asciidoc b/docs/configuration.asciidoc index 33c120fcf9..e58e8b3e37 100644 --- a/docs/configuration.asciidoc +++ b/docs/configuration.asciidoc @@ -74,6 +74,7 @@ Click on a key to get more information. ** <> ** <> ** <> +** <> * <> ** <> ** <> @@ -535,6 +536,28 @@ Disables the collection of breakdown metrics (`span.self_time`) | `elastic.apm.breakdown_metrics` | `breakdown_metrics` | `ELASTIC_APM_BREAKDOWN_METRICS` |============ +[float] +[[config-config-file-location]] +==== `config_file_location` + +Sets the path of the agent config file. +The special value `_AGENT_HOME_` is a placeholder for the folder the elastic-apm-agent.jar is in. +The location can either be in the classpath of the application or on the file system. + + +[options="header"] +|============ +| Default | Type | Dynamic +| `_AGENT_HOME_/elasticapm.properties` | String | false +|============ + + +[options="header"] +|============ +| Java System Properties | Property file | Environment +| `elastic.apm.config_file_location` | `config_file_location` | `ELASTIC_APM_CONFIG_FILE_LOCATION` +|============ + [[config-http]] === HTTP configuration options [float] @@ -1446,6 +1469,16 @@ The default unit for this option is `ms` # # breakdown_metrics=true +# Sets the path of the agent config file. +# The special value `_AGENT_HOME_` is a placeholder for the folder the elastic-apm-agent.jar is in. +# The location can either be in the classpath of the application or on the file system. +# +# This setting can not be changed at runtime. Changes require a restart of the application. +# Type: String +# Default value: _AGENT_HOME_/elasticapm.properties +# +# config_file_location=_AGENT_HOME_/elasticapm.properties + ############################################ # HTTP # ############################################ diff --git a/pom.xml b/pom.xml index 591ec8905e..e09aeefdce 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ 2.2.0 1.4.196 2.9.9 - 5.3.2 + 5.5.1 4.12 1.2.3 3.9.1