wu-sheng closed pull request #1919: feat:support set config from system.envs.
URL: https://github.com/apache/incubator-skywalking/pull/1919
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/docs/en/setup/backend/backend-setting-override.md
b/docs/en/setup/backend/backend-setting-override.md
index 7207cc379e..8714aed541 100644
--- a/docs/en/setup/backend/backend-setting-override.md
+++ b/docs/en/setup/backend/backend-setting-override.md
@@ -1,13 +1,14 @@
# Setting Override
-SkyWalking backend supports setting overrides by system properties.
+SkyWalking backend supports setting overrides by system properties and system
environment variables.
You could override the settings in `application.yml`
-- System properties key rule
+## System properties key rule
**ModuleName**.**ProviderName**.**SettingKey**.
- Example
Override `restHost` in this setting segment
+
```yaml
core:
default:
@@ -20,5 +21,32 @@ core:
Use command arg
```
--core.default.restHost=172.0.4.12
-```
\ No newline at end of file
+-Dcore.default.restHost=172.0.4.12
+```
+
+## System environment variables
+- Example
+
+ Override `restHost` in this setting segment through environment variables
+
+```yaml
+core:
+ default:
+ restHost: ${REST_HOST:0.0.0.0}
+ restPort: 12800
+ restContextPath: /
+ gRPCHost: 0.0.0.
+ gRPCPort: 11800
+```
+
+If the `REST_HOST ` environment variable exists in your operating system and
its value is `172.0.4.12`,
+then the value of `restHost` here will be overwritten to `172.0.4.12`,
otherwise, it will be set to `0.0.0.0`.
+
+By the way, Placeholder nesting is also supported, like
`${REST_HOST:${ANOTHER_REST_HOST:127.0.0.1}}`.
+In this case, if the `REST_HOST ` environment variable not exists, but the
```REST_ANOTHER_REST_HOSTHOST```
+environment variable exists and its value is `172.0.4.12`, then the value of
`restHost` here will be overwritten to `172.0.4.12`,
+otherwise, it will be set to `127.0.0.1`.
+
+
+
+
diff --git a/oap-server/server-library/library-util/pom.xml
b/oap-server/server-library/library-util/pom.xml
index c4a8d0d966..87ca944fb6 100644
--- a/oap-server/server-library/library-util/pom.xml
+++ b/oap-server/server-library/library-util/pom.xml
@@ -17,7 +17,8 @@
~
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>server-library</artifactId>
<groupId>org.apache.skywalking</groupId>
@@ -34,5 +35,16 @@
<artifactId>joda-time</artifactId>
<version>${joda-time.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.yaml</groupId>
+ <artifactId>snakeyaml</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.stefanbirkner</groupId>
+ <artifactId>system-rules</artifactId>
+ <version>1.18.0</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
-</project>
\ No newline at end of file
+</project>
diff --git
a/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/PlaceholderConfigurerSupport.java
b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/PlaceholderConfigurerSupport.java
new file mode 100644
index 0000000000..4ef02e95db
--- /dev/null
+++
b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/PlaceholderConfigurerSupport.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.library.util;
+
+/**
+ * @author jian.tan
+ */
+public class PlaceholderConfigurerSupport {
+
+ /** Default placeholder prefix: {@value} */
+ public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";
+
+ /** Default placeholder suffix: {@value} */
+ public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";
+
+ /** Default value separator: {@value} */
+ public static final String DEFAULT_VALUE_SEPARATOR = ":";
+}
diff --git
a/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/PropertyPlaceholderHelper.java
b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/PropertyPlaceholderHelper.java
new file mode 100644
index 0000000000..60d6c4a175
--- /dev/null
+++
b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/PropertyPlaceholderHelper.java
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.library.util;
+
+import com.google.common.base.Strings;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import org.apache.logging.log4j.core.util.Assert;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utility class for working with Strings that have placeholder values in
them. A placeholder takes the form {@code
+ * ${name}}. Using {@code PropertyPlaceholderHelper} these placeholders can be
substituted for user-supplied values. <p>
+ * Values for substitution can be supplied using a {@link Properties} instance
or using a {@link PlaceholderResolver}.
+ */
+public class PropertyPlaceholderHelper {
+ private static final Logger logger =
LoggerFactory.getLogger(PropertyPlaceholderHelper.class);
+
+ private static final Map<String, String> WELL_KNOWN_SIMPLE_PREFIXES = new
HashMap<>(4);
+
+ static {
+ WELL_KNOWN_SIMPLE_PREFIXES.put("}", "{");
+ WELL_KNOWN_SIMPLE_PREFIXES.put("]", "[");
+ WELL_KNOWN_SIMPLE_PREFIXES.put(")", "(");
+ }
+
+ private final String placeholderPrefix;
+
+ private final String placeholderSuffix;
+
+ private final String simplePrefix;
+
+ private final String valueSeparator;
+
+ private final boolean ignoreUnresolvablePlaceholders;
+
+ /**
+ * Creates a new {@code PropertyPlaceholderHelper} that uses the supplied
prefix and suffix.
+ *
+ * @param placeholderPrefix the prefix that denotes the start of a
placeholder
+ * @param placeholderSuffix the suffix that denotes the end of a
placeholder
+ * @param valueSeparator the separating character between the placeholder
variable and the associated default value,
+ * if any
+ * @param ignoreUnresolvablePlaceholders indicates whether unresolvable
placeholders should be ignored ({@code
+ * true}) or cause an exception ({@code false})
+ */
+ public PropertyPlaceholderHelper(String placeholderPrefix, String
placeholderSuffix,
+ String valueSeparator, boolean ignoreUnresolvablePlaceholders) {
+ Assert.requireNonEmpty(placeholderPrefix, "'placeholderPrefix' must
not be null");
+ Assert.requireNonEmpty(placeholderSuffix, "'placeholderSuffix' must
not be null");
+ this.placeholderPrefix = placeholderPrefix;
+ this.placeholderSuffix = placeholderSuffix;
+ String simplePrefixForSuffix =
WELL_KNOWN_SIMPLE_PREFIXES.get(this.placeholderSuffix);
+ if (simplePrefixForSuffix != null &&
this.placeholderPrefix.endsWith(simplePrefixForSuffix)) {
+ this.simplePrefix = simplePrefixForSuffix;
+ } else {
+ this.simplePrefix = this.placeholderPrefix;
+ }
+ this.valueSeparator = valueSeparator;
+ this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
+ }
+
+ /**
+ * Replaces all placeholders of format {@code ${name}} with the
corresponding property from the supplied {@link
+ * Properties}.
+ *
+ * @param value the value containing the placeholders to be replaced
+ * @param properties the {@code Properties} to use for replacement
+ * @return the supplied value with placeholders replaced inline
+ */
+ public String replacePlaceholders(String value, final Properties
properties) {
+ Assert.requireNonEmpty(properties, "'properties' must not be null");
+ return replacePlaceholders(value, placeholderName ->
this.getConfigValue(placeholderName, properties));
+ }
+
+ private String getConfigValue(String key, final Properties properties) {
+ String value = System.getProperty(key);
+ if (Strings.isNullOrEmpty(value)) {
+ value = System.getenv(key);
+ }
+ if (Strings.isNullOrEmpty(value)) {
+ value = properties.getProperty(key);
+ }
+ return value;
+ }
+
+ /**
+ * Replaces all placeholders of format {@code ${name}} with the value
returned from the supplied {@link
+ * PlaceholderResolver}.
+ *
+ * @param value the value containing the placeholders to be replaced
+ * @param placeholderResolver the {@code PlaceholderResolver} to use for
replacement
+ * @return the supplied value with placeholders replaced inline
+ */
+ public String replacePlaceholders(String value, PlaceholderResolver
placeholderResolver) {
+ Assert.requireNonEmpty(value, "'value' must not be null");
+ return parseStringValue(value, placeholderResolver, new
HashSet<String>());
+ }
+
+ protected String parseStringValue(String value, PlaceholderResolver
placeholderResolver,
+ Set<String> visitedPlaceholders) {
+
+ StringBuilder result = new StringBuilder(value);
+
+ int startIndex = value.indexOf(this.placeholderPrefix);
+ while (startIndex != -1) {
+ int endIndex = findPlaceholderEndIndex(result, startIndex);
+ if (endIndex != -1) {
+ String placeholder = result.substring(startIndex +
this.placeholderPrefix.length(), endIndex);
+ String originalPlaceholder = placeholder;
+ if (!visitedPlaceholders.add(originalPlaceholder)) {
+ throw new IllegalArgumentException(
+ "Circular placeholder reference '" +
originalPlaceholder + "' in property definitions");
+ }
+ // Recursive invocation, parsing placeholders contained in the
placeholder key.
+ placeholder = parseStringValue(placeholder,
placeholderResolver, visitedPlaceholders);
+ // Now obtain the value for the fully resolved key...
+ String propVal =
placeholderResolver.resolvePlaceholder(placeholder);
+ if (propVal == null && this.valueSeparator != null) {
+ int separatorIndex =
placeholder.indexOf(this.valueSeparator);
+ if (separatorIndex != -1) {
+ String actualPlaceholder = placeholder.substring(0,
separatorIndex);
+ String defaultValue =
placeholder.substring(separatorIndex + this.valueSeparator.length());
+ propVal =
placeholderResolver.resolvePlaceholder(actualPlaceholder);
+ if (propVal == null) {
+ propVal = defaultValue;
+ }
+ }
+ }
+ if (propVal != null) {
+ // Recursive invocation, parsing placeholders contained in
the
+ // previously resolved placeholder value.
+ propVal = parseStringValue(propVal, placeholderResolver,
visitedPlaceholders);
+ result.replace(startIndex, endIndex +
this.placeholderSuffix.length(), propVal);
+ if (logger.isTraceEnabled()) {
+ logger.trace("Resolved placeholder '" + placeholder +
"'");
+ }
+ startIndex = result.indexOf(this.placeholderPrefix,
startIndex + propVal.length());
+ } else if (this.ignoreUnresolvablePlaceholders) {
+ // Proceed with unprocessed value.
+ startIndex = result.indexOf(this.placeholderPrefix,
endIndex + this.placeholderSuffix.length());
+ } else {
+ throw new IllegalArgumentException("Could not resolve
placeholder '" +
+ placeholder + "'" + " in value \"" + value + "\"");
+ }
+ visitedPlaceholders.remove(originalPlaceholder);
+ } else {
+ startIndex = -1;
+ }
+ }
+ return result.toString();
+ }
+
+ private int findPlaceholderEndIndex(CharSequence buf, int startIndex) {
+ int index = startIndex + this.placeholderPrefix.length();
+ int withinNestedPlaceholder = 0;
+ while (index < buf.length()) {
+ if (StringUtils.substringMatch(buf, index,
this.placeholderSuffix)) {
+ if (withinNestedPlaceholder > 0) {
+ withinNestedPlaceholder--;
+ index = index + this.placeholderSuffix.length();
+ } else {
+ return index;
+ }
+ } else if (StringUtils.substringMatch(buf, index,
this.simplePrefix)) {
+ withinNestedPlaceholder++;
+ index = index + this.simplePrefix.length();
+ } else {
+ index++;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Strategy interface used to resolve replacement values for placeholders
contained in Strings.
+ */
+ public interface PlaceholderResolver {
+
+ /**
+ * Resolve the supplied placeholder name to the replacement value.
+ *
+ * @param placeholderName the name of the placeholder to resolve
+ * @return the replacement value, or {@code null} if no replacement is
to be made
+ */
+ String resolvePlaceholder(String placeholderName);
+ }
+}
diff --git
a/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/StringUtils.java
b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/StringUtils.java
index 2d425c46b9..1375c8098e 100644
---
a/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/StringUtils.java
+++
b/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/StringUtils.java
@@ -36,4 +36,16 @@ public static boolean isNotEmpty(Object str) {
public static String getOrDefault(String value, String defaultValue) {
return value == null ? defaultValue : value;
}
+
+ public static boolean substringMatch(CharSequence str, int index,
CharSequence substring) {
+ if (index + substring.length() > str.length()) {
+ return false;
+ }
+ for (int i = 0; i < substring.length(); i++) {
+ if (str.charAt(index + i) != substring.charAt(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git
a/oap-server/server-library/library-util/src/test/java/org/apache/skywalking/oap/server/library/util/PropertyPlaceholderHelperTest.java
b/oap-server/server-library/library-util/src/test/java/org/apache/skywalking/oap/server/library/util/PropertyPlaceholderHelperTest.java
new file mode 100644
index 0000000000..81fb6d7c75
--- /dev/null
+++
b/oap-server/server-library/library-util/src/test/java/org/apache/skywalking/oap/server/library/util/PropertyPlaceholderHelperTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.library.util;
+
+import java.io.FileNotFoundException;
+import java.io.Reader;
+import java.util.Map;
+import java.util.Properties;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.EnvironmentVariables;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * @author jian.tan
+ */
+public class PropertyPlaceholderHelperTest {
+ private PropertyPlaceholderHelper placeholderHelper;
+ private Properties properties = new Properties();
+ private final Yaml yaml = new Yaml();
+
+ /**
+ * The EnvironmentVariables rule allows you to set environment variables
for your test. All changes to environment
+ * variables are reverted after the test.
+ */
+ @Rule
+ public final EnvironmentVariables environmentVariables = new
EnvironmentVariables().set("REST_PORT", "12801");
+
+ @SuppressWarnings("unchecked")
+ @Before
+ public void init() throws FileNotFoundException {
+ Reader applicationReader = ResourceUtils.read("application.yml");
+ Map<String, Map<String, Map<String, ?>>> moduleConfig =
yaml.loadAs(applicationReader, Map.class);
+ if (CollectionUtils.isNotEmpty(moduleConfig)) {
+ moduleConfig.forEach((moduleName, providerConfig) -> {
+ if (providerConfig.size() > 0) {
+ providerConfig.forEach((name, propertiesConfig) -> {
+ if (propertiesConfig != null) {
+ propertiesConfig.forEach((key, value) ->
properties.put(key, value));
+ }
+ });
+ }
+ });
+ }
+ placeholderHelper =
+ new
PropertyPlaceholderHelper(PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_PREFIX,
+ PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_SUFFIX,
+ PlaceholderConfigurerSupport.DEFAULT_VALUE_SEPARATOR, true);
+ }
+
+ @Test
+ public void testDataType() {
+ //tests that do not use ${name} to set config.
+ Assert.assertEquals("grpc.skywalking.incubator.apache.org",
+
yaml.load(placeholderHelper.replacePlaceholders(properties.getProperty("gRPCHost"),
properties)));
+
+ //tests that use ${REST_HOST:0.0.0.0} but not set REST_HOST in
environmentVariables.
+ Assert.assertEquals("0.0.0.0",
+
yaml.load(placeholderHelper.replacePlaceholders(properties.getProperty("restHost"),
properties)));
+
+ //tests that use ${REST_PORT:12800} and set REST_PORT in
environmentVariables.
+ Assert.assertEquals(12801,
+
yaml.load(placeholderHelper.replacePlaceholders(properties.getProperty("restPort"),
properties)));
+ }
+
+ @After
+ public void afterTest() {
+ //revert environment variables changes after the test for safe.
+ environmentVariables.clear("REST_HOST");
+ }
+}
diff --git
a/oap-server/server-library/library-util/src/test/resources/application.yml
b/oap-server/server-library/library-util/src/test/resources/application.yml
new file mode 100644
index 0000000000..aa1855a72e
--- /dev/null
+++ b/oap-server/server-library/library-util/src/test/resources/application.yml
@@ -0,0 +1,82 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF 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.
+
+cluster:
+ standalone:
+# zookeeper:
+# hostPort: localhost:2181
+# # Retry Policy
+# baseSleepTimeMs: 1000 # initial amount of time to wait between retries
+# maxRetries: 3 # max number of times to retry
+# kubernetes:
+# watchTimeoutSeconds: 60
+# namespace: default
+# labelSelector: app=collector,release=skywalking
+# uidEnvName: SKYWALKING_COLLECTOR_UID
+core:
+ default:
+ restHost: ${REST_HOST:0.0.0.0}
+ restPort: ${REST_PORT:12800}
+ restContextPath: ${REST_CONTEXT_PATH:/}
+ gRPCHost: grpc.skywalking.incubator.apache.org
+ gRPCPort: ${GRPC_PORT:11800}
+ downsampling:
+ - Hour
+ - Day
+ - Month
+ # Set a timeout on metric data. After the timeout has expired, the metric
data will automatically be deleted.
+ recordDataTTL: ${RECORD_DATA_TTL:90} # Unit is minute
+ minuteMetricsDataTTL: ${MINUTE_METRIC_DATA_TTL:90} # Unit is minute
+ hourMetricsDataTTL: ${HOUR_METRIC_DATA_TTL:36} # Unit is hour
+ dayMetricsDataTTL: ${DAY_METRIC_DATA_TTL:45} # Unit is day
+ monthMetricsDataTTL: ${MONTH_METRIC_DATA_TTL:18} # Unit is month
+storage:
+ elasticsearch:
+ clusterNodes: ${ES_CLUSTER_ADDRESS:localhost:9200}
+ indexShardsNumber: ${ES_INDEX_SHARDS_NUMBER:2}
+ indexReplicasNumber: ${ES_INDEX_REPLICAS_NUMBER:0}
+ # Batch process setting, refer to
https://www.elastic.co/guide/en/elasticsearch/client/java-api/5.5/java-docs-bulk-processor.html
+ bulkActions: ${ES_BULK_ACTIONS:2000} # Execute the bulk every 2000 requests
+ bulkSize: ${ES_BULK_SIZE:20} # flush the bulk every 20mb
+ flushInterval: ${ES_FLUSH_INTERVAL:10} # flush the bulk every 10 seconds
whatever the number of requests
+ concurrentRequests: ${ES_CONCURRENT_REQUESTS:2} # the number of concurrent
requests
+# h2:
+# driver: org.h2.jdbcx.JdbcDataSource
+# url: jdbc:h2:mem:skywalking-oap-db
+# user: sa
+receiver-register:
+ default:
+receiver-trace:
+ default:
+ bufferPath: ${RECEIVER_BUFFER_PATH:../trace-buffer/} # Path to trace
buffer files, suggest to use absolute path
+ bufferOffsetMaxFileSize: ${RECEIVER_BUFFER_OFFSET_MAX_FILE_SIZE:100} #
Unit is MB
+ bufferDataMaxFileSize: ${RECEIVER_BUFFER_DATA_MAX_FILE_SIZE:500} # Unit is
MB
+ bufferFileCleanWhenRestart:
${RECEIVER_BUFFER_FILE_CLEAN_WHEN_RESTART:false}
+receiver-jvm:
+ default:
+service-mesh:
+ default:
+ bufferPath: ${SERVICE_MESH_BUFFER_PATH:../mesh-buffer/} # Path to trace
buffer files, suggest to use absolute path
+ bufferOffsetMaxFileSize: ${SERVICE_MESH_OFFSET_MAX_FILE_SIZE:100} # Unit
is MB
+ bufferDataMaxFileSize: ${SERVICE_MESH_BUFFER_DATA_MAX_FILE_SIZE:500} #
Unit is MB
+ bufferFileCleanWhenRestart:
${SERVICE_MESH_BUFFER_FILE_CLEAN_WHEN_RESTART:false}
+istio-telemetry:
+ default:
+query:
+ graphql:
+ path: ${QUERY_GRAPHQL_PATH:/graphql}
+alarm:
+ default:
diff --git a/oap-server/server-starter/src/main/assembly/application.yml
b/oap-server/server-starter/src/main/assembly/application.yml
index f6612620a3..f97c9e8fff 100644
--- a/oap-server/server-starter/src/main/assembly/application.yml
+++ b/oap-server/server-starter/src/main/assembly/application.yml
@@ -17,73 +17,73 @@
cluster:
standalone:
# Please check your ZooKeeper is 3.5+, However, it is also compatible with
ZooKeeper 3.4.x. Replace the ZooKeeper 3.5+
- # library in the oap-libs folder with your ZooKeeper 3.4.x libraru.
+ # library the oap-libs folder with your ZooKeeper 3.4.x library.
# zookeeper:
-# hostPort: localhost:2181
-# # Retry Policy
-# baseSleepTimeMs: 1000 # initial amount of time to wait between retries
-# maxRetries: 3 # max number of times to retry
+# hostPort: ${SW_CLUSTER_ZK_HOST_PORT:localhost:2181}
+# #Retry Policy
+# baseSleepTimeMs: ${SW_CLUSTER_ZK_SLEEP_TIME:1000} # initial amount of
time to wait between retries
+# maxRetries: ${SW_CLUSTER_ZK_MAX_RETRIES:3} # max number of times to retry
# kubernetes:
-# watchTimeoutSeconds: 60
-# namespace: default
-# labelSelector: app=collector,release=skywalking
-# uidEnvName: SKYWALKING_COLLECTOR_UID
+# watchTimeoutSeconds: ${SW_CLUSTER_K8S_WATCH_TIMEOUT:60}
+# namespace: ${SW_CLUSTER_K8S_NAMESPACE:default}
+# labelSelector: ${SW_CLUSTER_K8S_LABEL:app=collector,release=skywalking}
+# uidEnvName: ${SW_CLUSTER_K8S_UID:SKYWALKING_COLLECTOR_UID}
core:
default:
- restHost: 0.0.0.0
- restPort: 12800
- restContextPath: /
- gRPCHost: 0.0.0.0
- gRPCPort: 11800
+ restHost: ${SW_CORE_REST_HOST:0.0.0.0}
+ restPort: ${SW_CORE_REST_PORT:12800}
+ restContextPath: ${SW_CORE_REST_CONTEXT_PATH:/}
+ gRPCHost: ${SW_CORE_GRPC_HOST:0.0.0.0}
+ gRPCPort: ${SW_CORE_GRPC_PORT:11800}
downsampling:
- Hour
- Day
- Month
# Set a timeout on metric data. After the timeout has expired, the metric
data will automatically be deleted.
- recordDataTTL: 90 # Unit is minute
- minuteMetricsDataTTL: 90 # Unit is minute
- hourMetricsDataTTL: 36 # Unit is hour
- dayMetricsDataTTL: 45 # Unit is day
- monthMetricsDataTTL: 18 # Unit is month
+ recordDataTTL: ${SW_CORE_RECORD_DATA_TTL:90} # Unit is minute
+ minuteMetricsDataTTL: ${SW_CORE_MINUTE_METRIC_DATA_TTL:90} # Unit is minute
+ hourMetricsDataTTL: ${SW_CORE_HOUR_METRIC_DATA_TTL:36} # Unit is hour
+ dayMetricsDataTTL: ${SW_CORE_DAY_METRIC_DATA_TTL:45} # Unit is day
+ monthMetricsDataTTL: ${SW_CORE_MONTH_METRIC_DATA_TTL:18} # Unit is month
storage:
h2:
- driver: org.h2.jdbcx.JdbcDataSource
- url: jdbc:h2:mem:skywalking-oap-db
- user: sa
+ driver: ${SW_STORAGE_H2_DRIVER:org.h2.jdbcx.JdbcDataSource}
+ url: ${SW_STORAGE_H2_URL:jdbc:h2:mem:skywalking-oap-db}
+ user: ${SW_STORAGE_H2_USER:sa}
# elasticsearch:
-# clusterNodes: localhost:9200
-# indexShardsNumber: 2
-# indexReplicasNumber: 0
+# clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
+# indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:2}
+# indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:0}
# # Batch process setting, refer to
https://www.elastic.co/guide/en/elasticsearch/client/java-api/5.5/java-docs-bulk-processor.html
-# bulkActions: 2000 # Execute the bulk every 2000 requests
-# bulkSize: 20 # flush the bulk every 20mb
-# flushInterval: 10 # flush the bulk every 10 seconds whatever the number
of requests
-# concurrentRequests: 2 # the number of concurrent requests
+# bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:2000} # Execute the bulk every
2000 requests
+# bulkSize: ${SW_STORAGE_ES_BULK_SIZE:20} # flush the bulk every 20mb
+# flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:10} # flush the bulk every
10 seconds whatever the number of requests
+# concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:2} # the number
of concurrent requests
receiver-register:
default:
receiver-trace:
default:
- bufferPath: ../trace-buffer/ # Path to trace buffer files, suggest to use
absolute path
- bufferOffsetMaxFileSize: 100 # Unit is MB
- bufferDataMaxFileSize: 500 # Unit is MB
- bufferFileCleanWhenRestart: false
+ bufferPath: ${SW_RECEIVER_BUFFER_PATH:../trace-buffer/} # Path to trace
buffer files, suggest to use absolute path
+ bufferOffsetMaxFileSize: ${SW_RECEIVER_BUFFER_OFFSET_MAX_FILE_SIZE:100} #
Unit is MB
+ bufferDataMaxFileSize: ${SW_RECEIVER_BUFFER_DATA_MAX_FILE_SIZE:500} # Unit
is MB
+ bufferFileCleanWhenRestart:
${SW_RECEIVER_BUFFER_FILE_CLEAN_WHEN_RESTART:false}
receiver-jvm:
default:
service-mesh:
default:
- bufferPath: ../mesh-buffer/ # Path to mesh telemetry data buffer files,
suggest to use absolute path
- bufferOffsetMaxFileSize: 100 # Unit is MB
- bufferDataMaxFileSize: 500 # Unit is MB
- bufferFileCleanWhenRestart: false
+ bufferPath: ${SW_SERVICE_MESH_BUFFER_PATH:../mesh-buffer/} # Path to
trace buffer files, suggest to use absolute path
+ bufferOffsetMaxFileSize: ${SW_SERVICE_MESH_OFFSET_MAX_FILE_SIZE:100} #
Unit is MB
+ bufferDataMaxFileSize: ${SW_SERVICE_MESH_BUFFER_DATA_MAX_FILE_SIZE:500} #
Unit is MB
+ bufferFileCleanWhenRestart:
${SW_SERVICE_MESH_BUFFER_FILE_CLEAN_WHEN_RESTART:false}
istio-telemetry:
default:
#receiver_zipkin:
# default:
-# host: 0.0.0.0
-# port: 9411
-# contextPath: /
+# host: ${SW_RECEIVER_ZIPKIN_HOST:0.0.0.0}
+# port: ${SW_RECEIVER_ZIPKIN_PORT:9411}
+# contextPath: ${SW_RECEIVER_ZIPKIN_CONTEXT_PATH:/}
query:
graphql:
- path: /graphql
+ path: ${SW_QUERY_GRAPHQL_PATH:/graphql}
alarm:
default:
diff --git
a/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ApplicationConfigLoader.java
b/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ApplicationConfigLoader.java
index dbedbf6a4f..5d93503d92 100644
---
a/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ApplicationConfigLoader.java
+++
b/oap-server/server-starter/src/main/java/org/apache/skywalking/oap/server/starter/config/ApplicationConfigLoader.java
@@ -18,22 +18,22 @@
package org.apache.skywalking.oap.server.starter.config;
+import java.io.FileNotFoundException;
+import java.io.Reader;
+import java.util.Map;
+import java.util.Properties;
import
org.apache.skywalking.oap.server.library.module.ApplicationConfiguration;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
+import
org.apache.skywalking.oap.server.library.util.PlaceholderConfigurerSupport;
+import org.apache.skywalking.oap.server.library.util.PropertyPlaceholderHelper;
import org.apache.skywalking.oap.server.library.util.ResourceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;
-import java.io.FileNotFoundException;
-import java.io.Reader;
-import java.util.Map;
-import java.util.Properties;
-
/**
- * Initialize collector settings with following sources.
- * Use application.yml as primary setting,
- * and fix missing setting by default settings in application-default.yml.
+ * Initialize collector settings with following sources. Use application.yml
as primary setting, and fix missing setting
+ * by default settings in application-default.yml.
*
* At last, override setting by system.properties and system.envs if the key
matches moduleName.provideName.settingKey.
*
@@ -68,7 +68,13 @@ private void loadConfig(ApplicationConfiguration
configuration) throws ConfigFil
if (propertiesConfig != null) {
propertiesConfig.forEach((key, value) -> {
properties.put(key, value);
- logger.info("The property with key: {},
value: {}, in {} provider", key, value, name);
+ PropertyPlaceholderHelper helper =
+ new
PropertyPlaceholderHelper(PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_PREFIX,
+
PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_SUFFIX,
+
PlaceholderConfigurerSupport.DEFAULT_VALUE_SEPARATOR, true);
+ final Object replaceValue =
yaml.load(helper.replacePlaceholders(value + "", properties));
+ properties.replace(key, replaceValue);
+ logger.info("The property with key: {},
value: {}, in {} provider", key, replaceValue.toString(), name);
});
}
moduleConfiguration.addProviderConfiguration(name,
properties);
diff --git a/oap-server/server-starter/src/main/resources/application.yml
b/oap-server/server-starter/src/main/resources/application.yml
index 47f0463d0d..d94a82ae41 100644
--- a/oap-server/server-starter/src/main/resources/application.yml
+++ b/oap-server/server-starter/src/main/resources/application.yml
@@ -19,71 +19,71 @@ cluster:
# Please check your ZooKeeper is 3.5+, However, it is also compatible with
ZooKeeper 3.4.x. Replace the ZooKeeper 3.5+
# library the oap-libs folder with your ZooKeeper 3.4.x library.
# zookeeper:
-# hostPort: localhost:2181
+# hostPort: ${SW_CLUSTER_ZK_HOST_PORT:localhost:2181}
# #Retry Policy
-# baseSleepTimeMs: 1000 # initial amount of time to wait between retries
-# maxRetries: 3 # max number of times to retry
+# baseSleepTimeMs: ${SW_CLUSTER_ZK_SLEEP_TIME:1000} # initial amount of
time to wait between retries
+# maxRetries: ${SW_CLUSTER_ZK_MAX_RETRIES:3} # max number of times to retry
# kubernetes:
-# watchTimeoutSeconds: 60
-# namespace: default
-# labelSelector: app=collector,release=skywalking
-# uidEnvName: SKYWALKING_COLLECTOR_UID
+# watchTimeoutSeconds: ${SW_CLUSTER_K8S_WATCH_TIMEOUT:60}
+# namespace: ${SW_CLUSTER_K8S_NAMESPACE:default}
+# labelSelector: ${SW_CLUSTER_K8S_LABEL:app=collector,release=skywalking}
+# uidEnvName: ${SW_CLUSTER_K8S_UID:SKYWALKING_COLLECTOR_UID}
core:
default:
- restHost: 0.0.0.0
- restPort: 12800
- restContextPath: /
- gRPCHost: 0.0.0.0
- gRPCPort: 11800
+ restHost: ${SW_CORE_REST_HOST:0.0.0.0}
+ restPort: ${SW_CORE_REST_PORT:12800}
+ restContextPath: ${SW_CORE_REST_CONTEXT_PATH:/}
+ gRPCHost: ${SW_CORE_GRPC_HOST:0.0.0.0}
+ gRPCPort: ${SW_CORE_GRPC_PORT:11800}
downsampling:
- Hour
- Day
- Month
# Set a timeout on metric data. After the timeout has expired, the metric
data will automatically be deleted.
- recordDataTTL: 90 # Unit is minute
- minuteMetricsDataTTL: 90 # Unit is minute
- hourMetricsDataTTL: 36 # Unit is hour
- dayMetricsDataTTL: 45 # Unit is day
- monthMetricsDataTTL: 18 # Unit is month
+ recordDataTTL: ${SW_CORE_RECORD_DATA_TTL:90} # Unit is minute
+ minuteMetricsDataTTL: ${SW_CORE_MINUTE_METRIC_DATA_TTL:90} # Unit is minute
+ hourMetricsDataTTL: ${SW_CORE_HOUR_METRIC_DATA_TTL:36} # Unit is hour
+ dayMetricsDataTTL: ${SW_CORE_DAY_METRIC_DATA_TTL:45} # Unit is day
+ monthMetricsDataTTL: ${SW_CORE_MONTH_METRIC_DATA_TTL:18} # Unit is month
storage:
elasticsearch:
- clusterNodes: localhost:9200
- indexShardsNumber: 2
- indexReplicasNumber: 0
+ clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
+ indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:2}
+ indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:0}
# Batch process setting, refer to
https://www.elastic.co/guide/en/elasticsearch/client/java-api/5.5/java-docs-bulk-processor.html
- bulkActions: 2000 # Execute the bulk every 2000 requests
- bulkSize: 20 # flush the bulk every 20mb
- flushInterval: 10 # flush the bulk every 10 seconds whatever the number of
requests
- concurrentRequests: 2 # the number of concurrent requests
+ bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:2000} # Execute the bulk every
2000 requests
+ bulkSize: ${SW_STORAGE_ES_BULK_SIZE:20} # flush the bulk every 20mb
+ flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:10} # flush the bulk every
10 seconds whatever the number of requests
+ concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:2} # the number of
concurrent requests
# h2:
-# driver: org.h2.jdbcx.JdbcDataSource
-# url: jdbc:h2:mem:skywalking-oap-db
-# user: sa
+# driver: ${SW_STORAGE_H2_DRIVER:org.h2.jdbcx.JdbcDataSource}
+# url: ${SW_STORAGE_H2_URL:jdbc:h2:mem:skywalking-oap-db}
+# user: ${SW_STORAGE_H2_USER:sa}
receiver-register:
default:
receiver-trace:
default:
- bufferPath: ../trace-buffer/ # Path to trace buffer files, suggest to use
absolute path
- bufferOffsetMaxFileSize: 100 # Unit is MB
- bufferDataMaxFileSize: 500 # Unit is MB
- bufferFileCleanWhenRestart: false
+ bufferPath: ${SW_RECEIVER_BUFFER_PATH:../trace-buffer/} # Path to trace
buffer files, suggest to use absolute path
+ bufferOffsetMaxFileSize: ${SW_RECEIVER_BUFFER_OFFSET_MAX_FILE_SIZE:100} #
Unit is MB
+ bufferDataMaxFileSize: ${SW_RECEIVER_BUFFER_DATA_MAX_FILE_SIZE:500} # Unit
is MB
+ bufferFileCleanWhenRestart:
${SW_RECEIVER_BUFFER_FILE_CLEAN_WHEN_RESTART:false}
receiver-jvm:
default:
service-mesh:
default:
- bufferPath: ../mesh-buffer/ # Path to trace buffer files, suggest to use
absolute path
- bufferOffsetMaxFileSize: 100 # Unit is MB
- bufferDataMaxFileSize: 500 # Unit is MB
- bufferFileCleanWhenRestart: false
+ bufferPath: ${SW_SERVICE_MESH_BUFFER_PATH:../mesh-buffer/} # Path to
trace buffer files, suggest to use absolute path
+ bufferOffsetMaxFileSize: ${SW_SERVICE_MESH_OFFSET_MAX_FILE_SIZE:100} #
Unit is MB
+ bufferDataMaxFileSize: ${SW_SERVICE_MESH_BUFFER_DATA_MAX_FILE_SIZE:500} #
Unit is MB
+ bufferFileCleanWhenRestart:
${SW_SERVICE_MESH_BUFFER_FILE_CLEAN_WHEN_RESTART:false}
istio-telemetry:
default:
receiver_zipkin:
default:
- host: 0.0.0.0
- port: 9411
- contextPath: /
+ host: ${SW_RECEIVER_ZIPKIN_HOST:0.0.0.0}
+ port: ${SW_RECEIVER_ZIPKIN_PORT:9411}
+ contextPath: ${SW_RECEIVER_ZIPKIN_CONTEXT_PATH:/}
query:
graphql:
- path: /graphql
+ path: ${SW_QUERY_GRAPHQL_PATH:/graphql}
alarm:
default:
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services