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 88d8e6398f Support to trace redisson lock (#567)
88d8e6398f is described below

commit 88d8e6398fd3fe5684ca04bd77eaa40e69e099af
Author: peachisai <[email protected]>
AuthorDate: Sun Jul 2 21:16:23 2023 +0800

    Support to trace redisson lock (#567)
---
 CHANGES.md                                         |  1 +
 .../apm/agent/core/context/tag/Tags.java           | 16 ++++
 .../v3/RedissonHighLevelLockInterceptor.java       | 59 ++++++++++++++
 .../redisson/v3/RedissonLockInterceptor.java       | 59 ++++++++++++++
 .../v3/define/RedissonLockInstrumentation.java     | 91 ++++++++++++++++++++++
 .../src/main/resources/skywalking-plugin.def       |  3 +-
 .../redisson-scenario/config/expectedData.yaml     | 64 +++++++++++++++
 .../redisson/controller/CaseController.java        | 11 +++
 8 files changed, 303 insertions(+), 1 deletion(-)

diff --git a/CHANGES.md b/CHANGES.md
index 8b411b04c3..0e56e00149 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -140,6 +140,7 @@ Callable {
 * Add WebSphere Liberty 23.x plugin
 * Add Plugin to support aerospike Java client
 * Add ClickHouse parsing to the jdbc-common plugin.
+* Support to trace redisson lock
 
 #### 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 df6988c5eb..e538241368 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
@@ -139,6 +139,22 @@ public final class Tags {
 
     public static final StringTag SQL_PARAMETERS = new StringTag(19, 
"db.sql.parameters");
 
+    /**
+     * LOCK_NAME records the lock name such as redisson lock name
+     */
+    public static final StringTag LOCK_NAME = new StringTag(21, "lock.name");
+
+    /**
+     * LEASE_TIME represents the maximum time to hold the lock after it's 
acquisition
+     * in redisson plugin,it's unit is ms
+     */
+    public static final StringTag LEASE_TIME = new StringTag(22, "lease.time");
+
+    /**
+     * THREAD_ID records the thread id
+     */
+    public static final StringTag THREAD_ID = new StringTag(23, "thread.id");
+
     /**
      * Creates a {@code StringTag} with the given key and cache it, if it's 
created before, simply return it without
      * creating a new one.
diff --git 
a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonHighLevelLockInterceptor.java
 
b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonHighLevelLockInterceptor.java
new file mode 100644
index 0000000000..ef0a0585f5
--- /dev/null
+++ 
b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonHighLevelLockInterceptor.java
@@ -0,0 +1,59 @@
+/*
+ * 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.plugin.redisson.v3;
+
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.redisson.api.RLock;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.TimeUnit;
+
+public class RedissonHighLevelLockInterceptor implements 
InstanceMethodsAroundInterceptor {
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] 
allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws 
Throwable {
+        AbstractSpan span = ContextManager.createLocalSpan("Redisson/LOCK");
+        span.setComponent(ComponentsDefine.REDISSON);
+        SpanLayer.asCache(span);
+        RLock rLock = (RLock) objInst;
+        Tags.LOCK_NAME.set(span, rLock.getName());
+        Tags.CACHE_TYPE.set(span, "Redis");
+        TimeUnit unit = (TimeUnit) allArguments[2];
+        Tags.LEASE_TIME.set(span, String.valueOf(unit.toMillis((Long) 
allArguments[1])));
+        Tags.THREAD_ID.set(span, String.valueOf(allArguments[3]));
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, 
Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        ContextManager.stopSpan();
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, 
Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+        ContextManager.activeSpan().log(t);
+    }
+}
diff --git 
a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonLockInterceptor.java
 
b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonLockInterceptor.java
new file mode 100644
index 0000000000..77a31a28a4
--- /dev/null
+++ 
b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonLockInterceptor.java
@@ -0,0 +1,59 @@
+/*
+ * 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.plugin.redisson.v3;
+
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.redisson.api.RLock;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.TimeUnit;
+
+public class RedissonLockInterceptor implements 
InstanceMethodsAroundInterceptor {
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] 
allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws 
Throwable {
+        AbstractSpan span = ContextManager.createLocalSpan("Redisson/LOCK");
+        span.setComponent(ComponentsDefine.REDISSON);
+        SpanLayer.asCache(span);
+        RLock rLock = (RLock) objInst;
+        Tags.LOCK_NAME.set(span, rLock.getName());
+        Tags.CACHE_TYPE.set(span, "Redis");
+        TimeUnit unit = (TimeUnit) allArguments[1];
+        Tags.LEASE_TIME.set(span, String.valueOf(unit.toMillis((Long) 
allArguments[0])));
+        Tags.THREAD_ID.set(span, String.valueOf(allArguments[2]));
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, 
Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        ContextManager.stopSpan();
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, 
Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+        ContextManager.activeSpan().log(t);
+    }
+}
diff --git 
a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedissonLockInstrumentation.java
 
b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedissonLockInstrumentation.java
new file mode 100644
index 0000000000..f17c0af81d
--- /dev/null
+++ 
b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedissonLockInstrumentation.java
@@ -0,0 +1,91 @@
+/*
+ * 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.plugin.redisson.v3.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch;
+import org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch;
+import 
org.apache.skywalking.apm.agent.core.plugin.match.logical.LogicalMatchOperation;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static 
org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType;
+
+public class RedissonLockInstrumentation extends 
ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String REDISSON_LOCK_CLASS = 
"org.redisson.RedissonLock";
+
+    private static final String REDISSON_SPIN_LOCK_CLASS = 
"org.redisson.RedissonSpinLock";
+
+    private static final String REDISSON_LOCK_INTERCEPTOR = 
"org.apache.skywalking.apm.plugin.redisson.v3.RedissonLockInterceptor";
+
+    private static final String REDISSON_HIGH_LEVEL_LOCK_INTERCEPTOR = 
"org.apache.skywalking.apm.plugin.redisson.v3.RedissonHighLevelLockInterceptor";
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return 
LogicalMatchOperation.or(HierarchyMatch.byHierarchyMatch(REDISSON_LOCK_CLASS), 
MultiClassNameMatch.byMultiClassMatch(REDISSON_LOCK_CLASS, 
REDISSON_SPIN_LOCK_CLASS));
+    }
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[0];
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() 
{
+        return new InstanceMethodsInterceptPoint[]{
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> 
getMethodsMatcher() {
+                        return 
named("tryLockInnerAsync").and(takesArgumentWithType(1, 
"java.util.concurrent.TimeUnit"));
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return REDISSON_LOCK_INTERCEPTOR;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                },
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> 
getMethodsMatcher() {
+                        return 
named("tryLockInnerAsync").and(takesArgumentWithType(2, 
"java.util.concurrent.TimeUnit"));
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return REDISSON_HIGH_LEVEL_LOCK_INTERCEPTOR;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                }
+        };
+    }
+}
diff --git 
a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/resources/skywalking-plugin.def
 
b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/resources/skywalking-plugin.def
index fc7b5bf5aa..765de7cd42 100644
--- 
a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/resources/skywalking-plugin.def
+++ 
b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/resources/skywalking-plugin.def
@@ -16,4 +16,5 @@
 
 
redisson-3.x=org.apache.skywalking.apm.plugin.redisson.v3.define.ConnectionManagerInstrumentation
 
redisson-3.x=org.apache.skywalking.apm.plugin.redisson.v3.define.RedisConnectionInstrumentation
-redisson-3.x=org.apache.skywalking.apm.plugin.redisson.v3.define.RedisClientInstrumentation
\ No newline at end of file
+redisson-3.x=org.apache.skywalking.apm.plugin.redisson.v3.define.RedisClientInstrumentation
+redisson-3.x=org.apache.skywalking.apm.plugin.redisson.v3.define.RedissonLockInstrumentation
\ No newline at end of file
diff --git a/test/plugin/scenarios/redisson-scenario/config/expectedData.yaml 
b/test/plugin/scenarios/redisson-scenario/config/expectedData.yaml
index 2b54ed3b81..e925f320b2 100644
--- a/test/plugin/scenarios/redisson-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/redisson-scenario/config/expectedData.yaml
@@ -51,6 +51,70 @@ segmentItems:
       - {key: cache.instance, value: not null}
       - {key: cache.cmd, value: BATCH_EXECUTE}
       skipAnalysis: 'false'
+    - operationName: Redisson/EVAL
+      parentSpanId: 3
+      spanId: nq 0
+      spanLayer: Cache
+      startTime: not null
+      endTime: not null
+      componentId: 56
+      isError: false
+      spanType: Exit
+      peer: not null
+      tags:
+        - { key: cache.type, value: Redis }
+        - { key: cache.instance, value: not null }
+        - { key: cache.cmd, value: EVAL }
+        - { key: cache.key, value: not null }
+      skipAnalysis: 'false'
+    - operationName: Redisson/LOCK
+      parentSpanId: 0
+      spanId: nq 0
+      spanLayer: Cache
+      startTime: not null
+      endTime: not null
+      componentId: 56
+      isError: false
+      spanType: Local
+      peer: ''
+      tags:
+        - { key: lock.name, value: lock_a }
+        - { key: cache.type, value: Redis }
+        - { key: lease.time, value: not null }
+        - { key: thread.id, value: not null }
+      skipAnalysis: false
+    - operationName: Redisson/EVAL
+      parentSpanId: 5
+      spanId: nq 0
+      spanLayer: Cache
+      startTime: not null
+      endTime: not null
+      componentId: 56
+      isError: false
+      spanType: Exit
+      peer: not null
+      tags:
+        - { key: cache.type, value: Redis }
+        - { key: cache.instance, value: not null }
+        - { key: cache.cmd, value: EVAL }
+        - { key: cache.key, value: not null }
+      skipAnalysis: 'false'
+    - operationName: Redisson/LOCK
+      parentSpanId: 0
+      spanId: nq 0
+      spanLayer: Cache
+      startTime: not null
+      endTime: not null
+      componentId: 56
+      isError: false
+      spanType: Local
+      peer: ''
+      tags:
+        - { key: lock.name, value: lock_b }
+        - { key: cache.type, value: Redis }
+        - { key: lease.time, value: not null }
+        - { key: thread.id, value: not null }
+      skipAnalysis: false
     - operationName: GET:/case/redisson-case
       parentSpanId: -1
       spanId: 0
diff --git 
a/test/plugin/scenarios/redisson-scenario/src/main/java/test/apache/skywalking/apm/testcase/redisson/controller/CaseController.java
 
b/test/plugin/scenarios/redisson-scenario/src/main/java/test/apache/skywalking/apm/testcase/redisson/controller/CaseController.java
index e45d53ebba..ed12c59274 100644
--- 
a/test/plugin/scenarios/redisson-scenario/src/main/java/test/apache/skywalking/apm/testcase/redisson/controller/CaseController.java
+++ 
b/test/plugin/scenarios/redisson-scenario/src/main/java/test/apache/skywalking/apm/testcase/redisson/controller/CaseController.java
@@ -23,6 +23,7 @@ import javax.annotation.PostConstruct;
 import org.redisson.Redisson;
 import org.redisson.api.RBatch;
 import org.redisson.api.RBucket;
+import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
 import org.redisson.config.Config;
 import org.springframework.beans.factory.annotation.Value;
@@ -58,6 +59,16 @@ public class CaseController {
         batch.getBucket("batch_k_b").setAsync("batch_v_b");
         batch.getBucket("batch_k_b").expireAsync(20, TimeUnit.SECONDS);
         batch.execute();
+
+        RLock lockA = client.getLock("lock_a");
+        lockA.lock(10L, TimeUnit.SECONDS);
+        RLock lockB = client.getLock("lock_b");
+        try {
+            lockB.tryLock(10L, 20L, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
         return "Success";
     }
 

Reply via email to