entry : AGENT_CONFIG_KEYS_TO_PROPS.entrySet()) {
+ // dot.case -> UPPER_UNDERSCORE
+ AGENT_ENV_KEY_TO_PROPS.put(
+ ConfigPropertiesUtils.toEnvVarName(entry.getKey()),
+ entry.getValue()
+ );
+ }
}
+ /**
+ * update config value from environment variables and java properties
+ *
+ * java properties > environment variables > env:EASEAGENT_ENV_CONFIG={} > default
+ */
static Map updateEnvCfg() {
Map envCfg = new TreeMap<>();
- for (String key : subEnvKeys) {
- String value = System.getProperty(key);
- if (!StringUtils.isEmpty(value)) {
- envCfg.put(key.substring("easeagent.".length()), value);
- }
- }
- for (String key : envKeys) {
- String value = System.getProperty(key);
- if (!StringUtils.isEmpty(value)) {
- envCfg.put(key, value);
- }
- }
-
String configEnv = SystemEnv.get(EASEAGENT_ENV_CONFIG);
if (StringUtils.isNotEmpty(configEnv)) {
Map map = JsonUtil.toMap(configEnv);
@@ -77,12 +86,41 @@ static Map updateEnvCfg() {
envCfg.putAll(strMap);
}
+ // override by environment variables, eg: export EASEAGENT_NAME=xxx
+ for (Map.Entry entry : AGENT_ENV_KEY_TO_PROPS.entrySet()) {
+ String value = SystemEnv.get(entry.getKey());
+ if (!StringUtils.isEmpty(value)) {
+ envCfg.put(entry.getValue(), value);
+ }
+ }
+
+ // override by java properties; eg: java -Deaseagent.name=xxx
+ for (Map.Entry entry : AGENT_CONFIG_KEYS_TO_PROPS.entrySet()) {
+ String value = System.getProperty(entry.getKey());
+ if (!StringUtils.isEmpty(value)) {
+ envCfg.put(entry.getValue(), value);
+ }
+ }
+
return envCfg;
}
private ConfigFactory() {
}
+ /**
+ * Get config file path from system properties or environment variables
+ */
+ public static String getConfigPath() {
+ // get config path from -Deaseagent.config.path=/easeagent/agent.properties || export EASEAGENT_CONFIG_PATH=/easeagent/agent.properties
+ String path = ConfigPropertiesUtils.getString(AGENT_CONFIG_PATH_PROP_KEY);
+
+ if (StringUtils.isEmpty(path)) {
+ // eg: -Dotel.javaagent.configuration-file=/easeagent/agent.properties || export OTEL_JAVAAGENT_CONFIGURATION_FILE=/easeagent/agent.properties
+ path = OtelSdkConfigs.getConfigPath();
+ }
+ return path;
+ }
public static GlobalConfigs loadConfigs(String pathname, ClassLoader loader) {
// load property configuration file if exist
@@ -99,6 +137,9 @@ public static GlobalConfigs loadConfigs(String pathname, ClassLoader loader) {
configs.mergeConfigs(configsFromOuterFile);
}
+ // override by opentelemetry sdk env config
+ configs.updateConfigsNotNotify(OtelSdkConfigs.updateEnvCfg());
+
// check environment cfg override
configs.updateConfigsNotNotify(updateEnvCfg());
diff --git a/config/src/main/java/com/megaease/easeagent/config/ConfigPropertiesUtils.java b/config/src/main/java/com/megaease/easeagent/config/ConfigPropertiesUtils.java
new file mode 100644
index 00000000..b9b79a11
--- /dev/null
+++ b/config/src/main/java/com/megaease/easeagent/config/ConfigPropertiesUtils.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2022, MegaEase
+ * All rights reserved.
+ *
+ * Licensed 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.
+ */
+
+package com.megaease.easeagent.config;
+
+import com.megaease.easeagent.plugin.utils.SystemEnv;
+
+import javax.annotation.Nullable;
+import java.util.Locale;
+
+/**
+ * Get config from system properties or environment variables.
+ */
+final class ConfigPropertiesUtils {
+
+ public static boolean getBoolean(String propertyName, boolean defaultValue) {
+ String strValue = getString(propertyName);
+ return strValue == null ? defaultValue : Boolean.parseBoolean(strValue);
+ }
+
+ public static int getInt(String propertyName, int defaultValue) {
+ String strValue = getString(propertyName);
+ if (strValue == null) {
+ return defaultValue;
+ }
+ try {
+ return Integer.parseInt(strValue);
+ } catch (NumberFormatException ignored) {
+ return defaultValue;
+ }
+ }
+
+ @Nullable
+ public static String getString(String propertyName) {
+ String value = System.getProperty(propertyName);
+ if (value != null) {
+ return value;
+ }
+ return SystemEnv.get(toEnvVarName(propertyName));
+ }
+
+ /**
+ * dot.case -> UPPER_UNDERSCORE
+ */
+ public static String toEnvVarName(String propertyName) {
+ return propertyName.toUpperCase(Locale.ROOT).replace('-', '_').replace('.', '_');
+ }
+
+ private ConfigPropertiesUtils() {
+ }
+}
diff --git a/config/src/main/java/com/megaease/easeagent/config/OtelSdkConfigs.java b/config/src/main/java/com/megaease/easeagent/config/OtelSdkConfigs.java
new file mode 100644
index 00000000..d5b48416
--- /dev/null
+++ b/config/src/main/java/com/megaease/easeagent/config/OtelSdkConfigs.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2022, MegaEase
+ * All rights reserved.
+ *
+ * Licensed 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.
+ */
+
+package com.megaease.easeagent.config;
+
+import com.google.common.base.Splitter;
+import com.megaease.easeagent.plugin.utils.ImmutableMap;
+import com.megaease.easeagent.plugin.utils.SystemEnv;
+import com.megaease.easeagent.plugin.utils.common.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+
+/**
+ * Compatible with opentelemetry-java.
+ *
+ * {@see https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/autoconfigure/README.md#disabling-opentelemetrysdk}
+ */
+public class OtelSdkConfigs {
+ private static final String OTEL_RESOURCE_ATTRIBUTES_KEY = "otel.resource.attributes";
+
+ private static final String CONFIG_PATH_PROP_KEY = "otel.javaagent.configuration-file";
+
+ private static final Splitter.MapSplitter OTEL_RESOURCE_ATTRIBUTES_SPLITTER
+ = Splitter.on(",")
+ .omitEmptyStrings()
+ .withKeyValueSeparator("=");
+
+ private static final Map SDK_ATTRIBUTES_TO_EASE_AGENT_PROPS =
+ ImmutableMap.builder()
+ .put("sdk.disabled", "easeagent.server.enabled")
+ .put("service.name", "name") //"easeagent.name"
+ .put("service.namespace", "system") //"easeagent.system"
+ .build();
+
+ // -Dotel.service.name=xxx
+ private static final Map OTEL_SDK_PROPS_TO_EASE_AGENT_PROPS = new HashMap<>();
+
+ // OTEL_SERVICE_NAME=xxx
+ private static final Map OTEL_SDK_ENV_VAR_TO_EASE_AGENT_PROPS = new HashMap<>();
+
+ static {
+ for (Map.Entry entry : SDK_ATTRIBUTES_TO_EASE_AGENT_PROPS.entrySet()) {
+ // lower.hyphen -> UPPER_UNDERSCORE
+ OTEL_SDK_PROPS_TO_EASE_AGENT_PROPS.put(
+ "otel." + entry.getKey(),
+ entry.getValue()
+ );
+ }
+
+ for (Map.Entry entry : OTEL_SDK_PROPS_TO_EASE_AGENT_PROPS.entrySet()) {
+ // dot.case -> UPPER_UNDERSCORE
+ OTEL_SDK_ENV_VAR_TO_EASE_AGENT_PROPS.put(
+ ConfigPropertiesUtils.toEnvVarName(entry.getKey()),
+ entry.getValue()
+ );
+ }
+ }
+
+ /**
+ * Get config path from java properties or environment variables
+ */
+ static String getConfigPath() {
+ return ConfigPropertiesUtils.getString(CONFIG_PATH_PROP_KEY);
+ }
+
+
+ /**
+ * update config value from environment variables and java properties
+ *
+ * java properties > environment variables > OTEL_RESOURCE_ATTRIBUTES
+ */
+ static Map updateEnvCfg() {
+ Map envCfg = new TreeMap<>();
+
+ String configEnv = ConfigPropertiesUtils.getString(OTEL_RESOURCE_ATTRIBUTES_KEY);
+ if (StringUtils.isNotEmpty(configEnv)) {
+ Map map = OTEL_RESOURCE_ATTRIBUTES_SPLITTER.split(configEnv);
+ if (!map.isEmpty()) {
+ for (Map.Entry entry : SDK_ATTRIBUTES_TO_EASE_AGENT_PROPS.entrySet()) {
+ String value = map.get(entry.getKey());
+ if (!StringUtils.isEmpty(value)) {
+ envCfg.put(entry.getValue(), value);
+ }
+ }
+ }
+ }
+
+ // override by environment variables, eg: export OTEL_SERVICE_NAME=xxx
+ for (Map.Entry entry : OTEL_SDK_ENV_VAR_TO_EASE_AGENT_PROPS.entrySet()) {
+ String value = SystemEnv.get(entry.getKey());
+ if (!StringUtils.isEmpty(value)) {
+ envCfg.put(entry.getValue(), value);
+ }
+ }
+
+ // override by java properties; eg: java -Dotel.service.name=xxx
+ for (Map.Entry entry : OTEL_SDK_PROPS_TO_EASE_AGENT_PROPS.entrySet()) {
+ String value = System.getProperty(entry.getKey());
+ if (!StringUtils.isEmpty(value)) {
+ envCfg.put(entry.getValue(), value);
+ }
+ }
+
+ return envCfg;
+ }
+}
diff --git a/config/src/test/java/com/megaease/easeagent/config/ConfigFactoryTest.java b/config/src/test/java/com/megaease/easeagent/config/ConfigFactoryTest.java
index cee034ac..14796e3e 100644
--- a/config/src/test/java/com/megaease/easeagent/config/ConfigFactoryTest.java
+++ b/config/src/test/java/com/megaease/easeagent/config/ConfigFactoryTest.java
@@ -20,22 +20,76 @@
import com.megaease.easeagent.plugin.utils.SystemEnv;
import org.junit.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import java.io.File;
+import java.net.URISyntaxException;
+
+import static com.megaease.easeagent.config.ConfigFactory.AGENT_SERVICE;
+import static com.megaease.easeagent.config.ConfigFactory.AGENT_SYSTEM;
import static org.junit.Assert.assertEquals;
public class ConfigFactoryTest {
+
@Test
public void test_yaml() {
Configs config = ConfigFactory.loadConfigs(null, this.getClass().getClassLoader());
- assertEquals("test-service", config.getString("name"));
- assertEquals("demo-system", config.getString("system"));
+ assertEquals("test-service", config.getString(AGENT_SERVICE));
+ assertEquals("demo-system", config.getString(AGENT_SYSTEM));
}
@Test
public void test_env() {
- SystemEnv.set(ConfigFactory.EASEAGENT_ENV_CONFIG, "{\"name\":\"env-service\"}");
- Configs config = ConfigFactory.loadConfigs(null, this.getClass().getClassLoader());
- assertEquals("env-service", config.getString("name"));
- assertEquals("demo-system", config.getString("system"));
+ try (MockedStatic mock = Mockito.mockStatic(SystemEnv.class)) {
+ mock.when(() -> SystemEnv.get(ConfigFactory.EASEAGENT_ENV_CONFIG)).thenReturn("{\"name\":\"env-service\"}");
+
+ Configs config = ConfigFactory.loadConfigs(null, this.getClass().getClassLoader());
+ assertEquals("env-service", config.getString(AGENT_SERVICE));
+ assertEquals("demo-system", config.getString(AGENT_SYSTEM));
+ }
+ }
+
+
+ @Test
+ public void test_loadConfigs() {
+ try (MockedStatic mockSystemEnv = Mockito.mockStatic(SystemEnv.class)) {
+ mockSystemEnv.when(() -> SystemEnv.get("EASEAGENT_NAME")).thenReturn("service1");
+ mockSystemEnv.when(() -> SystemEnv.get("EASEAGENT_SYSTEM")).thenReturn("system1");
+
+ Configs config = ConfigFactory.loadConfigs(null, this.getClass().getClassLoader());
+ assertEquals("service1", config.getString(AGENT_SERVICE));
+ assertEquals("system1", config.getString(AGENT_SYSTEM));
+
+ System.setProperty("easeagent.name", "service2");
+ System.setProperty("easeagent.system", "system2");
+ config = ConfigFactory.loadConfigs(null, this.getClass().getClassLoader());
+ assertEquals("service2", config.getString(AGENT_SERVICE));
+ assertEquals("system2", config.getString(AGENT_SYSTEM));
+ }
+
+ }
+
+ @Test
+ public void test_loadConfigsFromUserSpec() throws URISyntaxException {
+ String userSpec = new File(this.getClass().getClassLoader().getResource("user-spec.properties").toURI()).getPath();
+
+ try (MockedStatic mockSystemEnv = Mockito.mockStatic(SystemEnv.class)) {
+ mockSystemEnv.when(() -> SystemEnv.get("EASEAGENT_CONFIG_PATH")).thenReturn(userSpec);
+ String path = ConfigFactory.getConfigPath();
+ assertEquals(userSpec, path);
+ }
+ }
+
+
+ @Test
+ public void test_loadConfigsFromOtelUserSpec() throws URISyntaxException {
+ String userSpec = new File(this.getClass().getClassLoader().getResource("user-spec.properties").toURI()).getPath();
+
+ try (MockedStatic mockSystemEnv = Mockito.mockStatic(SystemEnv.class)) {
+ mockSystemEnv.when(() -> SystemEnv.get("OTEL_JAVAAGENT_CONFIGURATION_FILE")).thenReturn(userSpec);
+ String path = ConfigFactory.getConfigPath();
+ assertEquals(userSpec, path);
+ }
}
}
diff --git a/config/src/test/java/com/megaease/easeagent/config/ConfigPropertiesUtilsTest.java b/config/src/test/java/com/megaease/easeagent/config/ConfigPropertiesUtilsTest.java
new file mode 100644
index 00000000..89bb555c
--- /dev/null
+++ b/config/src/test/java/com/megaease/easeagent/config/ConfigPropertiesUtilsTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2022, MegaEase
+ * All rights reserved.
+ *
+ * Licensed 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.
+ */
+
+package com.megaease.easeagent.config;
+
+import org.junit.*;
+import org.junit.contrib.java.lang.system.EnvironmentVariables;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+
+public class ConfigPropertiesUtilsTest {
+
+ @Rule
+ public final EnvironmentVariables environmentVariables
+ = new EnvironmentVariables();
+
+ @Rule
+ public final RestoreSystemProperties restoreSystemProperties
+ = new RestoreSystemProperties();
+
+ @BeforeClass
+ public static void beforeClass() {
+ // EnvironmentVariables and restoreSystemProperties does not work with Java 16
+ Assume.assumeTrue(
+ System.getProperty("java.version").startsWith("1.8")
+ || System.getProperty("java.version").startsWith("11")
+ );
+ }
+
+ @Test
+ public void getString_systemProperty() {
+ environmentVariables.set("TEST_PROPERTY_STRING", "env");
+ System.setProperty("test.property.string", "sys");
+ Assert.assertEquals("sys", ConfigPropertiesUtils.getString("test.property.string"));
+ }
+
+ @Test
+ public void getString_environmentVariable() {
+ environmentVariables.set("TEST_PROPERTY_STRING", "env");
+ Assert.assertEquals("env", ConfigPropertiesUtils.getString("test.property.string"));
+ }
+
+ @Test
+ public void getString_none() {
+ Assert.assertNull(ConfigPropertiesUtils.getString("test.property.string.none"));
+ }
+
+ @Test
+ public void getInt_systemProperty() {
+ environmentVariables.set("TEST_PROPERTY_INT", "12");
+ System.setProperty("test.property.int", "42");
+ Assert.assertEquals(42, ConfigPropertiesUtils.getInt("test.property.int", -1));
+ }
+
+ @Test
+ public void getInt_environmentVariable() {
+ environmentVariables.set("TEST_PROPERTY_INT", "12");
+ Assert.assertEquals(12, ConfigPropertiesUtils.getInt("test.property.int", -1));
+ }
+
+ @Test
+ public void getInt_none() {
+ Assert.assertEquals(-1, ConfigPropertiesUtils.getInt("test.property.int", -1));
+ }
+
+ @Test
+ public void getInt_invalidNumber() {
+ System.setProperty("test.property.int", "not a number");
+ Assert.assertEquals(-1, ConfigPropertiesUtils.getInt("test.property.int", -1));
+ }
+
+ @Test
+ public void getBoolean_systemProperty() {
+ environmentVariables.set("TEST_PROPERTY_BOOLEAN", "false");
+ System.setProperty("test.property.boolean", "true");
+ Assert.assertTrue(ConfigPropertiesUtils.getBoolean("test.property.boolean", false));
+ }
+
+ @Test
+ public void getBoolean_environmentVariable() {
+ environmentVariables.set("TEST_PROPERTY_BOOLEAN", "true");
+ Assert.assertTrue(ConfigPropertiesUtils.getBoolean("test.property.boolean", false));
+ }
+
+ @Test
+ public void getBoolean_none() {
+ Assert.assertFalse(ConfigPropertiesUtils.getBoolean("test.property.boolean", false));
+ }
+}
diff --git a/config/src/test/java/com/megaease/easeagent/config/OtelSdkConfigsTest.java b/config/src/test/java/com/megaease/easeagent/config/OtelSdkConfigsTest.java
new file mode 100644
index 00000000..3a6f8201
--- /dev/null
+++ b/config/src/test/java/com/megaease/easeagent/config/OtelSdkConfigsTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2022, MegaEase
+ * All rights reserved.
+ *
+ * Licensed 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.
+ */
+
+package com.megaease.easeagent.config;
+
+import com.megaease.easeagent.plugin.utils.SystemEnv;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Map;
+
+
+public class OtelSdkConfigsTest {
+
+ @Test
+ public void updateEnvCfg() {
+ //value from system env "OTEL_RESOURCE_ATTRIBUTES
+ String attributes = "service.name=service1,service.namespace=namespace1";
+ SystemEnv.set("OTEL_RESOURCE_ATTRIBUTES", attributes);
+ Map envCfg = OtelSdkConfigs.updateEnvCfg();
+ Assert.assertEquals("service1", envCfg.get("name"));
+ Assert.assertEquals("namespace1", envCfg.get("system"));
+
+ // override by system env
+ SystemEnv.set("OTEL_SERVICE_NAME", "service2");
+ SystemEnv.set("OTEL_SERVICE_NAMESPACE", "namespace2");
+ envCfg = OtelSdkConfigs.updateEnvCfg();
+ Assert.assertEquals("service2", envCfg.get("name"));
+ Assert.assertEquals("namespace2", envCfg.get("system"));
+
+ // override by system property
+ System.setProperty("otel.service.name", "service3");
+ System.setProperty("otel.service.namespace", "namespace3");
+ envCfg = OtelSdkConfigs.updateEnvCfg();
+ Assert.assertEquals("service3", envCfg.get("name"));
+ Assert.assertEquals("namespace3", envCfg.get("system"));
+
+ }
+}
diff --git a/config/src/test/resources/user-spec.properties b/config/src/test/resources/user-spec.properties
new file mode 100644
index 00000000..f39e6ff8
--- /dev/null
+++ b/config/src/test/resources/user-spec.properties
@@ -0,0 +1,2 @@
+name=user-spec
+system=system-spec
diff --git a/config/src/test/resources/user-spec2.properties b/config/src/test/resources/user-spec2.properties
new file mode 100644
index 00000000..07de5a04
--- /dev/null
+++ b/config/src/test/resources/user-spec2.properties
@@ -0,0 +1,2 @@
+name=user-spec2
+system=system-spec2
diff --git a/core/src/main/java/com/megaease/easeagent/core/Bootstrap.java b/core/src/main/java/com/megaease/easeagent/core/Bootstrap.java
index bce58089..74dcbb9b 100644
--- a/core/src/main/java/com/megaease/easeagent/core/Bootstrap.java
+++ b/core/src/main/java/com/megaease/easeagent/core/Bootstrap.java
@@ -37,6 +37,7 @@
import com.megaease.easeagent.plugin.bridge.AgentInfo;
import com.megaease.easeagent.plugin.bridge.EaseAgent;
import com.megaease.easeagent.plugin.report.AgentReport;
+import com.megaease.easeagent.plugin.utils.common.StringUtils;
import com.megaease.easeagent.report.AgentReportAware;
import com.megaease.easeagent.report.DefaultAgentReport;
import lombok.SneakyThrows;
@@ -47,7 +48,6 @@
import net.bytebuddy.dynamic.loading.ClassInjector;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.utility.JavaModule;
-import org.apache.commons.lang3.StringUtils;
import javax.management.MBeanServer;
import javax.management.ObjectName;
@@ -64,9 +64,8 @@
public class Bootstrap {
private static final Logger LOGGER = LoggerFactory.getLogger(Bootstrap.class);
- private static final String AGENT_SERVER_PORT_KEY = "easeagent.server.port";
- private static final String AGENT_CONFIG_PATH = "easeagent.config.path";
- private static final String AGENT_SERVER_ENABLED_KEY = "easeagent.server.enabled";
+ private static final String AGENT_SERVER_PORT_KEY = ConfigFactory.AGENT_SERVER_PORT;
+ private static final String AGENT_SERVER_ENABLED_KEY = ConfigFactory.AGENT_SERVER_ENABLED;
private static final String AGENT_MIDDLEWARE_UPDATE = "easeagent.middleware.update";
@@ -91,7 +90,7 @@ public static void start(String args, Instrumentation inst, String javaAgentJarP
}
// initiate configuration
- String configPath = System.getProperty(AGENT_CONFIG_PATH);
+ String configPath = ConfigFactory.getConfigPath();
if (StringUtils.isEmpty(configPath)) {
configPath = args;
}
diff --git a/doc/user-manual.md b/doc/user-manual.md
index 6248afdb..cb8c5b05 100644
--- a/doc/user-manual.md
+++ b/doc/user-manual.md
@@ -64,6 +64,13 @@ Global configuration include dedicated parameters for controlling metrics and tr
Plugin level configuration provides more granular control and customizable configuration.
+## Configuring priority
+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
+
### Getting the configuration file
You may extract default configuration from the JAR file or create new properties from a blank file.
```
@@ -73,17 +80,32 @@ Run the user application with EaseAgent
```
$ export EASE_AGENT_PATH=[Replace with agent path]
$ java "-javaagent:${EASE_AGENT_PATH}/easeagent.jar" -Deaseagent.config.path=${EASE_AGENT_PATH}/agent.properties -jar user-app.jar
+
+or
+
+$ export EASE_AGENT_PATH=[Replace with agent path]
+$ export EASEAGENT_CONFIG_PATH=${EASE_AGENT_PATH}/agent.properties
+$ java "-javaagent:${EASE_AGENT_PATH}/easeagent.jar" -jar user-app.jar
```
### Global Configuration
+
+#### Agent Configuration
+
+| System property | Environment variable | Configuration File Key | Description |
+|-------------------|------------------------|------------------------|-------------------------------|
+| `easeagent.name` | `EASEAGENT_NAME` | `name` | Specify logical service name. |
+| `easeagent.system` | `EASEAGENT_SYSTEM` | `system` | Specify logical service system. |
+
#### Internal HTTP Server
EaseAgent opens port `9900` by default to receive configuration change notifications and Prometheus requests.
-| Key | Default Value | Description |
-| -------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `easeagent.server.enabled` | true | Enable Internal HTTP Server. `false` can disable it. EaseAgent will no longer accept any HTTP requests (`Prometheus`、`Health Check`、`Readiness Check`、`Agent Info`) when the Internal HTTP Server is disabled. User can add VM parameter:`-Deaseagent.server.enabled=[true or false]` to override. |
-| `easeagent.server.port` | 9900 | Internal HTTP Server port. User can add VM parameter:`-Deaseagent.server.port=[new port]` to override. |
+| System property | Environment variable | DefaultValue | Description |
+|----------------------------|---------------------------|------| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `easeagent.server.enabled` | `EASEAGENT_SERVER_ENABLED` | true | Enable Internal HTTP Server. `false` can disable it. EaseAgent will no longer accept any HTTP requests (`Prometheus`、`Health Check`、`Readiness Check`、`Agent Info`) when the Internal HTTP Server is disabled. User can add VM parameter:`-Deaseagent.server.enabled=[true or false]` to override. |
+| `easeagent.server.port` | `EASEAGENT_SERVER_PORT` | 9900 | Internal HTTP Server port. User can add VM parameter:`-Deaseagent.server.port=[new port]` to override. |
+
#### Output Data Server: Kafka and HTTP/Zipkin Server
Tracing and metric data can be output to kafka server.
@@ -372,6 +394,12 @@ After modification, User can run the application with EaseAgent.
$ export EASE_AGENT_PATH=[Replace with agent path]
$ java "-javaagent:${EASE_AGENT_PATH}/easeagent.jar -Deaseagent.log.conf=${EASE_AGENT_PATH}/easeagent-log4j2.xml" -jar user-app.jar
```
+or
+```
+$ export EASE_AGENT_PATH=[Replace with agent path]
+$ export EASEAGENT_LOG_CONF=/your/log4j2/config/filepath
+$ java "-javaagent:${EASE_AGENT_PATH}/easeagent.jar -jar user-app.jar
+```
### MDC
Easeagent automatically adds TraceId and SpanId to the MDC (Mapped Diagnostic Context) when creating a new Span. You can configure your slf4j or logback files by adding parameters to display these IDs, or retrieve them directly from the MDC in your code.
diff --git a/loader/src/main/java/com/megaease/easeagent/Main.java b/loader/src/main/java/com/megaease/easeagent/Main.java
index 319e7f90..915bfd4e 100644
--- a/loader/src/main/java/com/megaease/easeagent/Main.java
+++ b/loader/src/main/java/com/megaease/easeagent/Main.java
@@ -17,6 +17,7 @@
package com.megaease.easeagent;
+import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import lombok.SneakyThrows;
import org.springframework.boot.loader.LaunchedURLClassLoader;
@@ -48,6 +49,8 @@ public class Main {
private static final String PLUGINS = "plugins/";
private static final String LOGGING_PROPERTY = "Logging-Property";
private static final String EASEAGENT_LOG_CONF = "easeagent.log.conf";
+ private static final String EASEAGENT_LOG_CONF_ENV_KEY = "EASEAGENT_LOG_CONF";
+ private static final String DEFAULT_AGENT_LOG_CONF = "easeagent-log4j2.xml";
private static ClassLoader loader;
public static void premain(final String args, final Instrumentation inst) throws Exception {
@@ -124,8 +127,9 @@ private static void switchLoggingProperty(ClassLoader loader, String hostKey, Ca
t.setContextClassLoader(loader);
+ // get config from system properties
final String host = System.getProperty(hostKey);
- final String agent = System.getProperty(Main.EASEAGENT_LOG_CONF, "easeagent-log4j2.xml");
+ final String agent = getLogConfigPath();
// Redirect config of host to agent
System.setProperty(hostKey, agent);
@@ -143,6 +147,20 @@ private static void switchLoggingProperty(ClassLoader loader, String hostKey, Ca
}
}
+ private static String getLogConfigPath() {
+ String logConfigPath = System.getProperty(EASEAGENT_LOG_CONF);
+ if (Strings.isNullOrEmpty(logConfigPath)) {
+ logConfigPath = System.getenv(EASEAGENT_LOG_CONF_ENV_KEY);
+
+ }
+ // if not set, use default
+ if (Strings.isNullOrEmpty(logConfigPath)) {
+ logConfigPath = DEFAULT_AGENT_LOG_CONF;
+
+ }
+ return logConfigPath;
+ }
+
private static ArrayList nestArchiveUrls(JarFileArchive archive, String prefix) throws IOException {
ArrayList archives = Lists.newArrayList(
archive.getNestedArchives(entry -> !entry.isDirectory() && entry.getName().startsWith(prefix),
diff --git a/plugin-api/src/main/java/io/opentelemetry/sdk/resources/EaseAgentResource.java b/plugin-api/src/main/java/io/opentelemetry/sdk/resources/EaseAgentResource.java
index e55bffde..19740ee1 100644
--- a/plugin-api/src/main/java/io/opentelemetry/sdk/resources/EaseAgentResource.java
+++ b/plugin-api/src/main/java/io/opentelemetry/sdk/resources/EaseAgentResource.java
@@ -6,12 +6,13 @@
import com.megaease.easeagent.plugin.api.otlp.common.SemanticKey;
import com.megaease.easeagent.plugin.bridge.EaseAgent;
import io.opentelemetry.api.common.Attributes;
-import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME;
-import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAMESPACE;
import javax.annotation.Nullable;
import java.util.List;
+import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME;
+import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAMESPACE;
+
public class EaseAgentResource extends Resource implements ConfigChangeListener {
static volatile EaseAgentResource agentResource = null;