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";
}