diff --git a/CHANGES.md b/CHANGES.md
index 20546251d..9152043cf 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -8,6 +8,7 @@ Release Notes.
* Support `Transaction` and fix duplicated methods enhancements for `jedis-2.x` plugin.
* Add ConsumerWrapper/FunctionWrapper to support CompletableFuture.x.thenAcceptAsync/thenApplyAsync.
* Build CLI from Docker instead of source codes, add alpine based Docker image.
+* Support set instance properties in json format.
#### Documentation
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java
index 4195d1943..46e109b8b 100755
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java
@@ -104,9 +104,18 @@ public class Config {
/**
* service instance properties e.g. agent.instance_properties[org]=apache
+ * Notice it will be overridden by `agent.instance_properties_json `, if the key duplication.
+ * For example: e.g. agent.instance_properties_json = {"org": "apache-skywalking"}
*/
+ @Deprecated
public static Map INSTANCE_PROPERTIES = new HashMap<>();
+ /**
+ * service instance properties in json format.
+ * e.g. agent.instance_properties_json = {"org": "apache-skywalking"}
+ */
+ public static String INSTANCE_PROPERTIES_JSON = "";
+
/**
* How depth the agent goes, when log cause exceptions.
*/
@@ -169,7 +178,8 @@ public class Config {
*/
public static long HEARTBEAT_PERIOD = 30;
/**
- * The agent sends the instance properties to the backend every `collector.heartbeat_period * collector.properties_report_period_factor` seconds
+ * The agent sends the instance properties to the backend every `collector.heartbeat_period *
+ * collector.properties_report_period_factor` seconds
*/
public static int PROPERTIES_REPORT_PERIOD_FACTOR = 10;
/**
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/ServiceManagementClient.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/ServiceManagementClient.java
index 707b7e625..f1299559b 100755
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/ServiceManagementClient.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/ServiceManagementClient.java
@@ -19,7 +19,6 @@
package org.apache.skywalking.apm.agent.core.remote;
import io.grpc.Channel;
-import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
@@ -35,6 +34,7 @@ import org.apache.skywalking.apm.agent.core.jvm.LoadedLibraryCollector;
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
import org.apache.skywalking.apm.agent.core.os.OSUtil;
+import org.apache.skywalking.apm.agent.core.util.InstanceJsonPropertiesUtil;
import org.apache.skywalking.apm.network.common.v3.Commands;
import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
import org.apache.skywalking.apm.network.management.v3.InstancePingPkg;
@@ -69,14 +69,7 @@ public class ServiceManagementClient implements BootService, Runnable, GRPCChann
public void prepare() {
ServiceManager.INSTANCE.findService(GRPCChannelManager.class).addChannelListener(this);
- SERVICE_INSTANCE_PROPERTIES = new ArrayList<>();
-
- for (String key : Config.Agent.INSTANCE_PROPERTIES.keySet()) {
- SERVICE_INSTANCE_PROPERTIES.add(KeyStringValuePair.newBuilder()
- .setKey(key)
- .setValue(Config.Agent.INSTANCE_PROPERTIES.get(key))
- .build());
- }
+ SERVICE_INSTANCE_PROPERTIES = InstanceJsonPropertiesUtil.parseProperties();
}
@Override
@@ -108,7 +101,8 @@ public class ServiceManagementClient implements BootService, Runnable, GRPCChann
if (GRPCChannelStatus.CONNECTED.equals(status)) {
try {
if (managementServiceBlockingStub != null) {
- if (Math.abs(sendPropertiesCounter.getAndAdd(1)) % Config.Collector.PROPERTIES_REPORT_PERIOD_FACTOR == 0) {
+ if (Math.abs(
+ sendPropertiesCounter.getAndAdd(1)) % Config.Collector.PROPERTIES_REPORT_PERIOD_FACTOR == 0) {
managementServiceBlockingStub
.withDeadlineAfter(GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS)
@@ -118,7 +112,8 @@ public class ServiceManagementClient implements BootService, Runnable, GRPCChann
.addAllProperties(OSUtil.buildOSInfo(
Config.OsInfo.IPV4_LIST_SIZE))
.addAllProperties(SERVICE_INSTANCE_PROPERTIES)
- .addAllProperties(LoadedLibraryCollector.buildJVMInfo())
+ .addAllProperties(
+ LoadedLibraryCollector.buildJVMInfo())
.build());
} else {
final Commands commands = managementServiceBlockingStub.withDeadlineAfter(
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/InstanceJsonPropertiesUtil.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/InstanceJsonPropertiesUtil.java
new file mode 100644
index 000000000..7862a53c4
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/InstanceJsonPropertiesUtil.java
@@ -0,0 +1,51 @@
+/*
+ * 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.apm.agent.core.util;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.apache.skywalking.apm.agent.core.conf.Config;
+import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
+import org.apache.skywalking.apm.util.StringUtil;
+
+public class InstanceJsonPropertiesUtil {
+ private static final Gson GSON = new Gson();
+
+ public static List parseProperties() {
+ List properties = new ArrayList<>();
+
+ if (StringUtil.isNotEmpty(Config.Agent.INSTANCE_PROPERTIES_JSON)) {
+ Config.Agent.INSTANCE_PROPERTIES.putAll(
+ GSON.fromJson(
+ Config.Agent.INSTANCE_PROPERTIES_JSON,
+ new TypeToken