Skip to content

Commit 2815d02

Browse files
committed
feat: support methods provided by redisTemplate
1 parent 5b6fdb3 commit 2815d02

8 files changed

+209
-17
lines changed

arex-instrumentation/redis/arex-spring-data-redis/src/main/java/io/arex/inst/spring/data/redis/MethodCollector.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ public class MethodCollector {
2424
"rangeByScoreWithScores", "rangeByLex", "reverseRangeByScore", "reverseRangeByScoreWithScores",
2525
"rank", "reverseRank", "removeRange", "removeRangeByScore", "score", "count", "zCard",
2626
// DefaultHashOperations
27-
"keys", "values", "entries", "randomKey", "randomEntry", "randomKeys", "randomEntries","delete"
27+
"keys", "values", "entries", "randomKey", "randomEntry", "randomKeys", "randomEntries", "delete",
28+
// RedisTemplate
29+
"hasKey", "unlink", "expire", "expireAt", "getExpire", "persist", "dump", "type"
2830
};
2931

3032
static final String[] TWO_OBJECT_KEY = new String[]{
@@ -33,14 +35,18 @@ public class MethodCollector {
3335
// DefaultSetOperations
3436
"difference", "differenceAndStore", "intersect", "intersectAndStore", "union", "unionAndStore",
3537
// DefaultHashOperations
36-
"hasKey", "increment", "lengthOfValue", "get", "put", "putIfAbsent"
38+
"hasKey", "increment", "lengthOfValue", "get", "put", "putIfAbsent",
39+
// RedisTemplate
40+
"renameIfAbsent"
3741
};
3842

3943
static final String[] COLLECTION_KEY = new String[]{
4044
// DefaultValueOperations
4145
"multiGet",
4246
// DefaultSetOperations
43-
"difference", "differenceAndStore", "intersect", "intersectAndStore", "union", "unionAndStore"
47+
"difference", "differenceAndStore", "intersect", "intersectAndStore", "union", "unionAndStore",
48+
// RedisTemplate
49+
"countExistingKeys", "delete", "unlink"
4450
};
4551

4652
static final String[] MAP_KEY = new String[]{

arex-instrumentation/redis/arex-spring-data-redis/src/main/java/io/arex/inst/spring/data/redis/SpringDataRedisModuleInstrumentation.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package io.arex.inst.spring.data.redis;
22

3-
import static java.util.Collections.singletonList;
3+
import static java.util.Arrays.asList;
44
import com.google.auto.service.AutoService;
5-
import io.arex.inst.extension.ModuleDescription;
65
import io.arex.inst.extension.ModuleInstrumentation;
76
import io.arex.inst.extension.TypeInstrumentation;
87
import java.util.List;
@@ -18,6 +17,8 @@ public SpringDataRedisModuleInstrumentation() {
1817

1918
@Override
2019
public List<TypeInstrumentation> instrumentationTypes() {
21-
return singletonList(new SpringDataRedisInstrumentation());
20+
return asList(
21+
new SpringDataRedisTemplateInstrumentation(),
22+
new SpringDataRedisOperationsInstrumentation());
2223
}
2324
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
import org.springframework.data.redis.core.RedisTemplate;
1616

1717
/**
18-
* SpringDataRedisInstrumentation
18+
* SpringDataRedisOperationsInstrumentation
1919
*/
20-
public class SpringDataRedisInstrumentation extends TypeInstrumentation {
20+
public class SpringDataRedisOperationsInstrumentation extends TypeInstrumentation {
2121

2222
@Override
2323
protected ElementMatcher<TypeDescription> typeMatcher() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package io.arex.inst.spring.data.redis;
2+
3+
import static java.util.Arrays.asList;
4+
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
5+
import io.arex.agent.bootstrap.model.MockResult;
6+
import io.arex.inst.extension.MethodInstrumentation;
7+
import io.arex.inst.extension.TypeInstrumentation;
8+
import io.arex.inst.redis.common.RedisKeyUtil;
9+
import java.util.List;
10+
import java.util.Objects;
11+
import net.bytebuddy.asm.Advice;
12+
import net.bytebuddy.description.type.TypeDescription;
13+
import net.bytebuddy.implementation.bytecode.assign.Assigner;
14+
import net.bytebuddy.matcher.ElementMatcher;
15+
import org.springframework.data.redis.core.RedisTemplate;
16+
17+
/**
18+
* SpringDataRedisTemplateInstrumentation
19+
*/
20+
public class SpringDataRedisTemplateInstrumentation extends TypeInstrumentation {
21+
22+
@Override
23+
protected ElementMatcher<TypeDescription> typeMatcher() {
24+
return namedOneOf("org.springframework.data.redis.core.RedisTemplate");
25+
}
26+
27+
@Override
28+
public List<MethodInstrumentation> methodAdvices() {
29+
return asList(MethodCollector.arg1IsObjectKey(OneKeyAdvice.class.getName()),
30+
MethodCollector.arg1IsCollectionKey(OneKeyAdvice.class.getName()),
31+
MethodCollector.arg1AndArg2AreObjectKey(TwoKeysAdvice.class.getName()));
32+
}
33+
34+
public static class OneKeyAdvice {
35+
36+
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class, suppress = Throwable.class)
37+
public static boolean onEnter(@Advice.This RedisTemplate template,
38+
@Advice.Origin("#m") String methodName,
39+
@Advice.Argument(0) Object key,
40+
@Advice.Local("mockResult") MockResult mockResult) {
41+
mockResult = RedisTemplateProvider.methodOnEnter(Objects.toString(template.getConnectionFactory()),
42+
methodName, RedisKeyUtil.generate(key));
43+
return mockResult != null && mockResult.notIgnoreMockResult();
44+
}
45+
46+
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
47+
public static void onExit(@Advice.This RedisTemplate template,
48+
@Advice.Origin("#m") String methodName,
49+
@Advice.Argument(0) Object key,
50+
@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result,
51+
@Advice.Thrown(readOnly = false, typing = Assigner.Typing.DYNAMIC) Throwable throwable,
52+
@Advice.Local("mockResult") MockResult mockResult) {
53+
if (mockResult != null && mockResult.notIgnoreMockResult()) {
54+
if (mockResult.getThrowable() != null) {
55+
throwable = mockResult.getThrowable();
56+
} else {
57+
result = mockResult.getResult();
58+
}
59+
return;
60+
}
61+
RedisTemplateProvider.methodOnExit(Objects.toString(template.getConnectionFactory()), methodName,
62+
RedisKeyUtil.generate(key), result, throwable);
63+
}
64+
}
65+
66+
public static class TwoKeysAdvice {
67+
68+
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class, suppress = Throwable.class)
69+
public static boolean onEnter(@Advice.This RedisTemplate template,
70+
@Advice.Origin("#m") String methodName,
71+
@Advice.Argument(0) Object key,
72+
@Advice.Argument(1) Object otherKey,
73+
@Advice.Local("mockResult") MockResult mockResult) {
74+
mockResult = RedisTemplateProvider.methodOnEnter(Objects.toString(template.getConnectionFactory()),
75+
methodName, RedisKeyUtil.generate(key, otherKey));
76+
return mockResult != null && mockResult.notIgnoreMockResult();
77+
}
78+
79+
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
80+
public static void onExit(@Advice.This RedisTemplate template,
81+
@Advice.Origin("#m") String methodName,
82+
@Advice.Argument(0) Object key,
83+
@Advice.Argument(1) Object otherKey,
84+
@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result,
85+
@Advice.Thrown(readOnly = false, typing = Assigner.Typing.DYNAMIC) Throwable throwable,
86+
@Advice.Local("mockResult") MockResult mockResult) {
87+
if (mockResult != null && mockResult.notIgnoreMockResult()) {
88+
if (mockResult.getThrowable() != null) {
89+
throwable = mockResult.getThrowable();
90+
} else {
91+
result = mockResult.getResult();
92+
}
93+
return;
94+
}
95+
RedisTemplateProvider.methodOnExit(Objects.toString(template.getConnectionFactory()), methodName,
96+
RedisKeyUtil.generate(key, otherKey), result, throwable);
97+
}
98+
}
99+
}

arex-instrumentation/redis/arex-spring-data-redis/src/test/java/io/arex/inst/spring/data/redis/MethodCollectorTest.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,18 @@ public class MethodCollectorTest {
1414
"incrementScore", "reverseRange", "rangeWithScores", "reverseRangeWithScores", "rangeByScore",
1515
"rangeByScoreWithScores", "rangeByLex", "reverseRangeByScore", "reverseRangeByScoreWithScores", "rank",
1616
"reverseRank", "removeRange", "removeRangeByScore", "score", "count", "zCard", "keys", "values", "entries",
17-
"randomKey", "randomEntry", "randomKeys", "randomEntries", "delete"
17+
"randomKey", "randomEntry", "randomKeys", "randomEntries", "delete", "hasKey", "unlink", "expire", "expireAt",
18+
"getExpire", "persist", "dump", "type"
1819
};
1920

2021
private static final String[] TWO_OBJECT_KEY_TEST = new String[]{
2122
"rightPopAndLeftPush", "difference", "differenceAndStore", "intersect", "intersectAndStore", "union",
22-
"unionAndStore", "hasKey", "increment", "lengthOfValue", "get", "put", "putIfAbsent"
23+
"unionAndStore", "hasKey", "increment", "lengthOfValue", "get", "put", "putIfAbsent", "renameIfAbsent"
2324
};
2425

2526
private static final String[] COLLECTION_KEY_TEST = new String[]{
26-
"multiGet", "difference", "differenceAndStore", "intersect", "intersectAndStore", "union", "unionAndStore"
27+
"multiGet", "difference", "differenceAndStore", "intersect", "intersectAndStore", "union", "unionAndStore",
28+
"countExistingKeys", "delete", "unlink"
2729
};
2830

2931
private static final String[] MAP_KEY_TEST = new String[]{

arex-instrumentation/redis/arex-spring-data-redis/src/test/java/io/arex/inst/spring/data/redis/SpringDataRedisModuleInstrumentationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ class SpringDataRedisModuleInstrumentationTest {
88
@Test
99
void instrumentationTypes() {
1010
SpringDataRedisModuleInstrumentation instrumentation = new SpringDataRedisModuleInstrumentation();
11-
assertEquals(instrumentation.instrumentationTypes().size(),1);
11+
assertEquals(instrumentation.instrumentationTypes().size(), 2);
1212
}
1313
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import static org.junit.jupiter.api.Assertions.assertNotNull;
77
import com.google.common.collect.Lists;
88
import io.arex.agent.bootstrap.model.MockResult;
9-
import io.arex.inst.spring.data.redis.SpringDataRedisInstrumentation.OneKeyAdvice;
10-
import io.arex.inst.spring.data.redis.SpringDataRedisInstrumentation.TwoKeysAdvice;
9+
import io.arex.inst.spring.data.redis.SpringDataRedisOperationsInstrumentation.OneKeyAdvice;
10+
import io.arex.inst.spring.data.redis.SpringDataRedisOperationsInstrumentation.TwoKeysAdvice;
1111
import java.util.List;
1212
import org.junit.jupiter.api.AfterAll;
1313
import org.junit.jupiter.api.BeforeAll;
@@ -18,9 +18,9 @@
1818
import org.springframework.data.redis.core.RedisTemplate;
1919

2020
@ExtendWith(MockitoExtension.class)
21-
class SpringDataRedisInstrumentationTest {
21+
class SpringDataRedisOperationsInstrumentationTest {
2222

23-
private static SpringDataRedisInstrumentation target;
23+
private static SpringDataRedisOperationsInstrumentation target;
2424
private static RedisTemplate redisTemplate = new RedisTemplate();
2525
private static final String KEY = "key";
2626
private static final String RESTULT = "result";
@@ -30,7 +30,7 @@ class SpringDataRedisInstrumentationTest {
3030
@BeforeAll
3131
static void setUp() {
3232
redisTemplate = Mockito.mock(RedisTemplate.class);
33-
target = new SpringDataRedisInstrumentation();
33+
target = new SpringDataRedisOperationsInstrumentation();
3434
}
3535

3636

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package io.arex.inst.spring.data.redis;
2+
3+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
4+
import static org.junit.jupiter.api.Assertions.assertEquals;
5+
import static org.junit.jupiter.api.Assertions.assertFalse;
6+
import static org.junit.jupiter.api.Assertions.assertNotNull;
7+
8+
import com.google.common.collect.Lists;
9+
import io.arex.agent.bootstrap.model.MockResult;
10+
import io.arex.inst.spring.data.redis.SpringDataRedisTemplateInstrumentation.OneKeyAdvice;
11+
import io.arex.inst.spring.data.redis.SpringDataRedisTemplateInstrumentation.TwoKeysAdvice;
12+
import java.util.List;
13+
import org.junit.jupiter.api.AfterAll;
14+
import org.junit.jupiter.api.BeforeAll;
15+
import org.junit.jupiter.api.Test;
16+
import org.junit.jupiter.api.extension.ExtendWith;
17+
import org.mockito.Mockito;
18+
import org.mockito.junit.jupiter.MockitoExtension;
19+
import org.springframework.data.redis.core.RedisTemplate;
20+
21+
@ExtendWith(MockitoExtension.class)
22+
class SpringDataRedisTemplateInstrumentationTest {
23+
24+
private static SpringDataRedisTemplateInstrumentation target;
25+
private static RedisTemplate redisTemplate = new RedisTemplate();
26+
private static final String KEY = "key";
27+
private static final String RESTULT = "result";
28+
private static final String OTHER_KEY = "otherKey";
29+
private static final String METHOD_NAME = "getExpire";
30+
31+
@BeforeAll
32+
static void setUp() {
33+
redisTemplate = Mockito.mock(RedisTemplate.class);
34+
target = new SpringDataRedisTemplateInstrumentation();
35+
}
36+
37+
38+
@AfterAll
39+
static void tearDown() {
40+
Mockito.clearAllCaches();
41+
}
42+
43+
@Test
44+
void methodAdvices() {
45+
assertEquals(3, target.methodAdvices().size());
46+
}
47+
48+
@Test
49+
void typeMatcher() {
50+
assertNotNull(target.typeMatcher());
51+
}
52+
53+
@Test
54+
void oneKeyAdvice() {
55+
// onEnter
56+
assertFalse(OneKeyAdvice.onEnter(redisTemplate, METHOD_NAME, KEY, MockResult.success(true, "mock")));
57+
// test methodOnExit at different mockReuslts
58+
getMockResults().forEach(mockResult -> {
59+
assertDoesNotThrow(() -> OneKeyAdvice.onExit(redisTemplate, METHOD_NAME, KEY, RESTULT, null, mockResult));
60+
}
61+
);
62+
}
63+
64+
@Test
65+
void twoKeysAdvice() {
66+
// onEnter
67+
assertFalse(
68+
TwoKeysAdvice.onEnter(redisTemplate, METHOD_NAME, KEY, OTHER_KEY, MockResult.success(true, "mock")));
69+
// test methodOnExit at different mockReuslts
70+
getMockResults().forEach(mockResult -> {
71+
assertDoesNotThrow(
72+
() -> TwoKeysAdvice.onExit(redisTemplate, METHOD_NAME, KEY, OTHER_KEY, RESTULT, null, mockResult));
73+
}
74+
);
75+
}
76+
77+
private static List<MockResult> getMockResults() {
78+
return Lists.newArrayList(
79+
MockResult.success(true, "mock"),
80+
MockResult.success(false, "mock"),
81+
MockResult.success(new Throwable()),
82+
null);
83+
}
84+
}

0 commit comments

Comments
 (0)