This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-java.git


The following commit(s) were added to refs/heads/main by this push:
     new 92b076c281 Enhance redisson plugin to adopt uniform tags (#438)
92b076c281 is described below

commit 92b076c2819783b34e4d7de0d1b8532381386683
Author: xzyJavaX <[email protected]>
AuthorDate: Wed Jan 11 23:09:19 2023 +0800

    Enhance redisson plugin to adopt uniform tags (#438)
---
 CHANGES.md                                         |   1 +
 .../apm/agent/core/context/tag/Tags.java           |   5 +
 .../v3/RedisConnectionMethodInterceptor.java       |  64 +++++++-----
 .../plugin/redisson/v3/RedissonPluginConfig.java   | 116 +++++++++++++++++++++
 apm-sniffer/config/agent.config                    |   4 +
 .../service-agent/java-agent/configurations.md     |   2 +
 .../redisson-scenario/config/expectedData.yaml     |  15 +--
 7 files changed, 174 insertions(+), 33 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index c7b7e6353c..bd8dd18ef4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -26,6 +26,7 @@ Release Notes.
 * Put `Agent-Version` property reading in the premain stage to avoid deadlock 
when using `jarsigner`.
 * Add a config `agent.enable`(default: true) to support disabling the agent 
through system property `-Dskywalking.agent.disable=false` 
   or system environment variable setting `SW_AGENT_ENABLE=false`. 
+* Enhance redisson plugin to adopt uniform tags.
 
 #### Documentation
 
diff --git 
a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java
 
b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java
index 2cce4ba9e3..df6988c5eb 100644
--- 
a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java
+++ 
b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java
@@ -130,6 +130,11 @@ public final class Tags {
      */
     public static final StringTag CACHE_KEY = new StringTag(18, "cache.key");
 
+    /**
+     * CACHE_INSTANCE records the cache instance
+     */
+    public static final StringTag CACHE_INSTANCE = new StringTag(20, 
"cache.instance");
+
     public static final String VAL_LOCAL_SPAN_AS_LOGIC_ENDPOINT = 
"{\"logic-span\":true}";
 
     public static final StringTag SQL_PARAMETERS = new StringTag(19, 
"db.sql.parameters");
diff --git 
a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java
 
b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java
index 5a62afe325..60956c7a64 100644
--- 
a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java
+++ 
b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java
@@ -18,7 +18,6 @@
 
 package org.apache.skywalking.apm.plugin.redisson.v3;
 
-import io.netty.buffer.ByteBuf;
 import io.netty.channel.Channel;
 import org.apache.skywalking.apm.agent.core.context.ContextManager;
 import org.apache.skywalking.apm.agent.core.context.tag.Tags;
@@ -32,6 +31,7 @@ import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceM
 import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
 import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
 import org.apache.skywalking.apm.plugin.redisson.v3.util.ClassUtil;
+import org.apache.skywalking.apm.util.StringUtil;
 import org.redisson.client.RedisClient;
 import org.redisson.client.RedisConnection;
 import org.redisson.client.protocol.CommandData;
@@ -39,6 +39,7 @@ import org.redisson.client.protocol.CommandsData;
 
 import java.lang.reflect.Method;
 import java.net.InetSocketAddress;
+import java.util.Optional;
 
 public class RedisConnectionMethodInterceptor implements 
InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor {
 
@@ -58,43 +59,29 @@ public class RedisConnectionMethodInterceptor implements 
InstanceMethodsAroundIn
         InetSocketAddress remoteAddress = (InetSocketAddress) 
channel.remoteAddress();
         String dbInstance = remoteAddress.getAddress().getHostAddress() + ":" 
+ remoteAddress.getPort();
 
-        StringBuilder dbStatement = new StringBuilder();
         String operationName = "Redisson/";
+        String command = "";
+        Object[] arguments = new Object[0];
 
         if (allArguments[0] instanceof CommandsData) {
             operationName = operationName + "BATCH_EXECUTE";
-            CommandsData commands = (CommandsData) allArguments[0];
-            for (CommandData commandData : commands.getCommands()) {
-                addCommandData(dbStatement, commandData);
-                dbStatement.append(";");
-            }
+            command = "BATCH_EXECUTE";
         } else if (allArguments[0] instanceof CommandData) {
             CommandData commandData = (CommandData) allArguments[0];
-            String command = commandData.getCommand().getName();
+            command = commandData.getCommand().getName();
             operationName = operationName + command;
-            addCommandData(dbStatement, commandData);
+            arguments = commandData.getParams();
         }
 
         AbstractSpan span = ContextManager.createExitSpan(operationName, peer);
         span.setComponent(ComponentsDefine.REDISSON);
-        Tags.DB_TYPE.set(span, "Redis");
-        Tags.DB_INSTANCE.set(span, dbInstance);
-        Tags.DB_STATEMENT.set(span, dbStatement.toString());
-        SpanLayer.asCache(span);
-    }
+        Tags.CACHE_TYPE.set(span, "Redis");
+        Tags.CACHE_INSTANCE.set(span, dbInstance);
+        Tags.CACHE_CMD.set(span, command);
 
-    private void addCommandData(StringBuilder dbStatement, CommandData 
commandData) {
-        dbStatement.append(commandData.getCommand().getName());
-        if (RedissonPluginConfig.Plugin.Redisson.TRACE_REDIS_PARAMETERS && 
commandData.getParams() != null) {
-            for (Object param : commandData.getParams()) {
-                dbStatement.append(DELIMITER_SPACE);
-                String paramStr = param instanceof ByteBuf ? QUESTION_MARK : 
String.valueOf(param.toString());
-                if (paramStr.length() > 
RedissonPluginConfig.Plugin.Redisson.REDIS_PARAMETER_MAX_LENGTH) {
-                    paramStr = paramStr.substring(0, 
RedissonPluginConfig.Plugin.Redisson.REDIS_PARAMETER_MAX_LENGTH) + ABBR;
-                }
-                dbStatement.append(paramStr);
-            }
-        }
+        getKey(arguments).ifPresent(key -> Tags.CACHE_KEY.set(span, key));
+        parseOperation(command.toLowerCase()).ifPresent(op -> 
Tags.CACHE_OP.set(span, op));
+        SpanLayer.asCache(span);
     }
 
     @Override
@@ -131,4 +118,29 @@ public class RedisConnectionMethodInterceptor implements 
InstanceMethodsAroundIn
         }
         objInst.setSkyWalkingDynamicField(peer);
     }
+
+    private Optional<String> getKey(Object[] allArguments) {
+        if (!RedissonPluginConfig.Plugin.Redisson.TRACE_REDIS_PARAMETERS) {
+            return Optional.empty();
+        }
+        if (allArguments.length == 0) {
+            return Optional.empty();
+        }
+        Object argument = allArguments[0];
+        // include null
+        if (!(argument instanceof String)) {
+            return Optional.empty();
+        }
+        return Optional.of(StringUtil.cut((String) argument, 
RedissonPluginConfig.Plugin.Redisson.REDIS_PARAMETER_MAX_LENGTH));
+    }
+
+    private Optional<String> parseOperation(String cmd) {
+        if 
(RedissonPluginConfig.Plugin.Redisson.OPERATION_MAPPING_READ.contains(cmd)) {
+            return Optional.of("read");
+        }
+        if 
(RedissonPluginConfig.Plugin.Redisson.OPERATION_MAPPING_WRITE.contains(cmd)) {
+            return Optional.of("write");
+        }
+        return Optional.empty();
+    }
 }
diff --git 
a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonPluginConfig.java
 
b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonPluginConfig.java
index f97c4a715b..52dedcb10a 100644
--- 
a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonPluginConfig.java
+++ 
b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonPluginConfig.java
@@ -20,6 +20,10 @@ package org.apache.skywalking.apm.plugin.redisson.v3;
 
 import org.apache.skywalking.apm.agent.core.boot.PluginConfig;
 
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
 public class RedissonPluginConfig {
     public static class Plugin {
         @PluginConfig(root = RedissonPluginConfig.class)
@@ -36,6 +40,118 @@ public class RedissonPluginConfig {
              * Set a negative number to save specified length of parameter 
string to the tag.
              */
             public static int REDIS_PARAMETER_MAX_LENGTH = 128;
+
+            /**
+             * Operation represent a cache span is "write" or "read" action , 
and "op"(operation) is tagged with key "cache.op" usually
+             * This config term define which command should be converted to 
write Operation .
+             *
+             * @see 
org.apache.skywalking.apm.agent.core.context.tag.Tags#CACHE_OP
+             * @see RedisConnectionMethodInterceptor#parseOperation(String)
+             */
+            public static Set<String> OPERATION_MAPPING_WRITE = new 
HashSet<>(Arrays.asList(
+                    "getset",
+                    "set",
+                    "setbit",
+                    "setex ",
+                    "setnx ",
+                    "setrange",
+                    "strlen ",
+                    "mset",
+                    "msetnx ",
+                    "psetex",
+                    "incr ",
+                    "incrby ",
+                    "incrbyfloat",
+                    "decr ",
+                    "decrby ",
+                    "append ",
+                    "hmset",
+                    "hset",
+                    "hsetnx ",
+                    "hincrby",
+                    "hincrbyfloat",
+                    "hdel",
+                    "rpoplpush",
+                    "rpush",
+                    "rpushx",
+                    "lpush",
+                    "lpushx",
+                    "lrem",
+                    "ltrim",
+                    "lset",
+                    "brpoplpush",
+                    "linsert",
+                    "sadd",
+                    "sdiff",
+                    "sdiffstore",
+                    "sinterstore",
+                    "sismember",
+                    "srem",
+                    "sunion",
+                    "sunionstore",
+                    "sinter",
+                    "zadd",
+                    "zincrby",
+                    "zinterstore",
+                    "zrange",
+                    "zrangebylex",
+                    "zrangebyscore",
+                    "zrank",
+                    "zrem",
+                    "zremrangebylex",
+                    "zremrangebyrank",
+                    "zremrangebyscore",
+                    "zrevrange",
+                    "zrevrangebyscore",
+                    "zrevrank",
+                    "zunionstore",
+                    "xadd",
+                    "xdel",
+                    "del",
+                    "xtrim"
+            ));
+            /**
+             * Operation represent a cache span is "write" or "read" action , 
and "op"(operation) is tagged with key "cache.op" usually
+             * This config term define which command should be converted to 
write Operation .
+             *
+             * @see 
org.apache.skywalking.apm.agent.core.context.tag.Tags#CACHE_OP
+             * @see RedisConnectionMethodInterceptor#parseOperation(String)
+             */
+            public static Set<String> OPERATION_MAPPING_READ = new 
HashSet<>(Arrays.asList(
+                    "getrange",
+                    "getbit ",
+                    "mget",
+                    "hvals",
+                    "hkeys",
+                    "hlen",
+                    "hexists",
+                    "hget",
+                    "hgetall",
+                    "hmget",
+                    "blpop",
+                    "brpop",
+                    "lindex",
+                    "llen",
+                    "lpop",
+                    "lrange",
+                    "rpop",
+                    "scard",
+                    "srandmember",
+                    "spop",
+                    "sscan",
+                    "smove",
+                    "zlexcount",
+                    "zscore",
+                    "zscan",
+                    "zcard",
+                    "zcount",
+                    "xget",
+                    "get",
+                    "xread",
+                    "xlen",
+                    "xrange",
+                    "xrevrange"
+            ));
         }
     }
 }
diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config
index 7124e2e8a0..2e7bc49160 100755
--- a/apm-sniffer/config/agent.config
+++ b/apm-sniffer/config/agent.config
@@ -305,3 +305,7 @@ 
plugin.jedis.operation_mapping_read=${SW_PLUGIN_JEDIS_OPERATION_MAPPING_READ:get
 
plugin.redisson.trace_redis_parameters=${SW_PLUGIN_REDISSON_TRACE_REDIS_PARAMETERS:false}
 # If set to positive number and plugin.redisson.trace_redis_parameters is set 
to true, Redis command parameters would be collected and truncated to this 
length.
 
plugin.redisson.redis_parameter_max_length=${SW_PLUGIN_REDISSON_REDIS_PARAMETER_MAX_LENGTH:128}
+# Specify which command should be converted to write operation
+plugin.redisson.operation_mapping_write=${SW_PLUGIN_REDISSON_OPERATION_MAPPING_WRITE:getset,set,setbit,setex,setnx,setrange,strlen,mset,msetnx,psetex,incr,incrby,incrbyfloat,decr,decrby,append,hmset,hset,hsetnx,hincrby,hincrbyfloat,hdel,rpoplpush,rpush,rpushx,lpush,lpushx,lrem,ltrim,lset,brpoplpush,linsert,sadd,sdiff,sdiffstore,sinterstore,sismember,srem,sunion,sunionstore,sinter,zadd,zincrby,zinterstore,zrange,zrangebylex,zrangebyscore,zrank,zrem,zremrangebylex,zremrangebyrank,zremrange
 [...]
+# Specify which command should be converted to read operation
+plugin.redisson.operation_mapping_read=${SW_PLUGIN_REDISSON_OPERATION_MAPPING_READ:getrange,getbit,mget,hvals,hkeys,hlen,hexists,hget,hgetall,hmget,blpop,brpop,lindex,llen,lpop,lrange,rpop,scard,srandmember,spop,sscan,smove,zlexcount,zscore,zscan,zcard,zcount,xget,get,xread,xlen,xrange,xrevrange}
\ No newline at end of file
diff --git a/docs/en/setup/service-agent/java-agent/configurations.md 
b/docs/en/setup/service-agent/java-agent/configurations.md
index c79c525d40..9669e9398f 100644
--- a/docs/en/setup/service-agent/java-agent/configurations.md
+++ b/docs/en/setup/service-agent/java-agent/configurations.md
@@ -112,6 +112,8 @@ This is the properties list supported in 
`agent/config/agent.config`.
 | `plugin.jedis.operation_mapping_read  `                         | Specify 
which command should be converted to `read` operation                           
                                                                                
                                                                                
                                                                                
                                                                                
                 [...]
 | `plugin.redisson.trace_redis_parameters`                        | If set to 
true, the parameters of Redis commands would be collected by Redisson agent.    
                                                                                
                                                                                
                                                                                
                                                                                
               [...]
 | `plugin.redisson.redis_parameter_max_length`                    | If set to 
positive number and `plugin.redisson.trace_redis_parameters` is set to `true`, 
Redis command parameters would be collected and truncated to this length.       
                                                                                
                                                                                
                                                                                
                [...]
+| `plugin.redisson.operation_mapping_write`                       | Specify 
which command should be converted to `write` operation                          
                                                                                
                                                                                
                                                                                
                                                                                
                 [...]
+| `plugin.redisson.operation_mapping_read  `                      | Specify 
which command should be converted to `read` operation                           
                                                                                
                                                                                
                                                                                
                                                                                
                 [...]
 | `plugin.neo4j.trace_cypher_parameters`                          | If set to 
true, the parameters of the cypher would be collected.                          
                                                                                
                                                                                
                                                                                
                                                                                
               [...]
 | `plugin.neo4j.cypher_parameters_max_length`                     | If set to 
positive number, the `db.cypher.parameters` would be truncated to this length, 
otherwise it would be completely saved, which may cause performance problem.    
                                                                                
                                                                                
                                                                                
                [...]
 | `plugin.neo4j.cypher_body_max_length`                           | If set to 
positive number, the `db.statement` would be truncated to this length, 
otherwise it would be completely saved, which may cause performance problem.    
                                                                                
                                                                                
                                                                                
                        [...]
diff --git a/test/plugin/scenarios/redisson-scenario/config/expectedData.yaml 
b/test/plugin/scenarios/redisson-scenario/config/expectedData.yaml
index 73b06f1c2e..2b54ed3b81 100644
--- a/test/plugin/scenarios/redisson-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/redisson-scenario/config/expectedData.yaml
@@ -30,9 +30,11 @@ segmentItems:
       spanType: Exit
       peer: not null
       tags:
-      - {key: db.type, value: Redis}
-      - {key: db.instance, value: not null}
-      - {key: db.statement, value: 'SET key_a ?'}
+      - {key: cache.type, value: Redis}
+      - {key: cache.instance, value: not null}
+      - {key: cache.cmd, value: SET}
+      - {key: cache.key, value: key_a}
+      - {key: cache.op, value: write}
       skipAnalysis: 'false'
     - operationName: Redisson/BATCH_EXECUTE
       parentSpanId: 0
@@ -45,10 +47,9 @@ segmentItems:
       spanType: Exit
       peer: not null
       tags:
-      - {key: db.type, value: Redis}
-      - {key: db.instance, value: not null}
-      - {key: db.statement, value: 'SET batch_k_a ?;SET batch_k_b ?;PEXPIRE 
batch_k_b
-          20000;'}
+      - {key: cache.type, value: Redis}
+      - {key: cache.instance, value: not null}
+      - {key: cache.cmd, value: BATCH_EXECUTE}
       skipAnalysis: 'false'
     - operationName: GET:/case/redisson-case
       parentSpanId: -1

Reply via email to