Skip to content

Commit d8b0374

Browse files
authored
Merge pull request #4 from newrelic-experimental/support-7.x
updates to support version 7.x
2 parents 30acf2a + c78ca1f commit d8b0374

11 files changed

Lines changed: 233 additions & 2 deletions

File tree

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
rootProject.name = 'spring-async-instrumentation'
22
include 'spring-async'
3+
include 'spring-async-7.0'
34
include 'spring-web-async'

spring-async-7.0/build.gradle

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
// Build.gradle generated for instrumentation module spring-web-async
3+
4+
apply plugin: 'java'
5+
6+
targetCompatibility = JavaVersion.VERSION_17
7+
8+
dependencies {
9+
implementation 'org.springframework:spring-core:7.0.0'
10+
11+
// New Relic Java Agent dependencies
12+
implementation 'com.newrelic.agent.java:newrelic-agent:8.4.0'
13+
implementation 'com.newrelic.agent.java:newrelic-api:8.4.0'
14+
implementation 'com.newrelic.agent.java:agent-bridge:8.4.0'
15+
implementation fileTree(include: ['*.jar'], dir: '../test-lib')
16+
}
17+
18+
jar {
19+
manifest {
20+
attributes 'Implementation-Title': 'com.newrelic.instrumentation.spring-async'
21+
attributes 'Implementation-Vendor': 'New Relic'
22+
attributes 'Implementation-Vendor-Id': 'com.newrelic'
23+
attributes 'Implementation-Version': 1.0
24+
}
25+
}
26+
27+
verifyInstrumentation {
28+
passesOnly 'org.springframework:spring-core:[7.0.0,)'
29+
excludeRegex '.*M.*'
30+
excludeRegex '.*RC.*'
31+
32+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.newrelic.instrumentation.spring.async;
2+
3+
import java.util.concurrent.Callable;
4+
5+
import com.newrelic.agent.bridge.AgentBridge;
6+
import com.newrelic.api.agent.NewRelic;
7+
import com.newrelic.api.agent.Token;
8+
import com.newrelic.api.agent.Trace;
9+
10+
public class NRCallableWrapper<V> implements Callable<V> {
11+
12+
private Callable<V> delegate = null;
13+
private Token token = null;
14+
private static boolean isTransformed = false;
15+
16+
public NRCallableWrapper(Callable<V> d, Token t) {
17+
delegate = d;
18+
token = t;
19+
if(!isTransformed) {
20+
AgentBridge.instrumentation.retransformUninstrumentedClass(getClass());
21+
isTransformed = true;
22+
}
23+
}
24+
25+
@Override
26+
@Trace(async = true)
27+
public V call() throws Exception {
28+
if(token != null) {
29+
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","SpringAsync","Callable");
30+
token.linkAndExpire();
31+
token = null;
32+
}
33+
return delegate.call();
34+
}
35+
36+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.newrelic.instrumentation.spring.async;
2+
3+
import com.newrelic.agent.bridge.AgentBridge;
4+
import com.newrelic.api.agent.NewRelic;
5+
import com.newrelic.api.agent.Token;
6+
import com.newrelic.api.agent.Trace;
7+
8+
public class NRRunnableWrapper implements Runnable {
9+
10+
private static boolean isTransformed = false;
11+
private Runnable delegate = null;
12+
private Token token = null;
13+
14+
public NRRunnableWrapper(Runnable r, Token t) {
15+
delegate = r;
16+
token = t;
17+
if(!isTransformed) {
18+
isTransformed = true;
19+
AgentBridge.instrumentation.retransformUninstrumentedClass(getClass());
20+
}
21+
}
22+
23+
@Override
24+
@Trace(async = true)
25+
public void run() {
26+
if(token != null) {
27+
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","SpringAsync","Runnable");
28+
token.linkAndExpire();
29+
token = null;
30+
}
31+
delegate.run();
32+
}
33+
34+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.newrelic.instrumentation.spring.async;
2+
3+
import java.util.concurrent.Callable;
4+
5+
import com.newrelic.api.agent.NewRelic;
6+
import com.newrelic.api.agent.Token;
7+
8+
public class Utils {
9+
10+
public static Runnable getWrappedRunnable(Runnable r) {
11+
12+
if(r instanceof NRRunnableWrapper) return null;
13+
14+
String packageName = r.getClass().getPackage().getName();
15+
if(packageName.startsWith("com.newrelic") || packageName.startsWith("com.nr")) return null;
16+
17+
Token token = NewRelic.getAgent().getTransaction().getToken();
18+
if(token != null && token.isActive()) {
19+
return new NRRunnableWrapper(r, token);
20+
} else if(token != null) {
21+
token.expire();
22+
token = null;
23+
}
24+
return null;
25+
}
26+
27+
public static <V> Callable<V> getWrappedCallable(Callable<V> c) {
28+
29+
if(c instanceof NRCallableWrapper) return null;
30+
31+
String packageName = c.getClass().getPackage().getName();
32+
if(packageName.startsWith("com.newrelic") || packageName.startsWith("com.nr")) return null;
33+
34+
Token token = NewRelic.getAgent().getTransaction().getToken();
35+
if(token != null && token.isActive()) {
36+
return new NRCallableWrapper<V>(c, token);
37+
} else if(token != null) {
38+
token.expire();
39+
token = null;
40+
}
41+
return null;
42+
}
43+
44+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.springframework.core.task;
2+
3+
import com.newrelic.api.agent.weaver.MatchType;
4+
import com.newrelic.api.agent.weaver.Weave;
5+
import com.newrelic.api.agent.weaver.Weaver;
6+
import com.newrelic.instrumentation.spring.async.Utils;
7+
8+
import java.util.concurrent.Callable;
9+
import java.util.concurrent.Future;
10+
11+
@Weave(originalName = "org.springframework.core.task.AsyncTaskExecutor", type = MatchType.Interface)
12+
public class AsyncTaskExecutor_Instrumentation {
13+
14+
public void execute(Runnable task, long startTimeout) {
15+
Runnable wrapper = Utils.getWrappedRunnable(task);
16+
if(wrapper != null) {
17+
task = wrapper;
18+
}
19+
Weaver.callOriginal();
20+
}
21+
22+
public Future<?> submit(Runnable task) {
23+
Runnable wrapper = Utils.getWrappedRunnable(task);
24+
if(wrapper != null) {
25+
task = wrapper;
26+
}
27+
return Weaver.callOriginal();
28+
}
29+
30+
public <V> Future<V> submit(Callable<V> task) {
31+
Callable<V> wrapper = Utils.getWrappedCallable(task);
32+
if(wrapper != null) {
33+
task = wrapper;
34+
}
35+
return Weaver.callOriginal();
36+
}
37+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.springframework.core.task;
2+
3+
import com.newrelic.api.agent.Trace;
4+
import com.newrelic.api.agent.weaver.Weave;
5+
import com.newrelic.api.agent.weaver.Weaver;
6+
7+
@Weave(originalName = "org.springframework.core.task.SyncTaskExecutor")
8+
public class SyncTaskExecutor_Instrumentation {
9+
10+
@Trace
11+
public <V, E extends Exception> V execute(TaskCallback<V, E> task) {
12+
return Weaver.callOriginal();
13+
}
14+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.springframework.core.task;
2+
3+
import com.newrelic.api.agent.Trace;
4+
import com.newrelic.api.agent.weaver.MatchType;
5+
import com.newrelic.api.agent.weaver.Weave;
6+
import com.newrelic.api.agent.weaver.Weaver;
7+
8+
@Weave(originalName = "org.springframework.core.task.TaskCallback", type = MatchType.Interface)
9+
public class TaskCallback_Instrumentation<V, E extends Exception> {
10+
11+
@Trace
12+
public V call() throws E {
13+
return Weaver.callOriginal();
14+
}
15+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.springframework.core.task;
2+
3+
import com.newrelic.api.agent.weaver.MatchType;
4+
import com.newrelic.api.agent.weaver.Weave;
5+
import com.newrelic.api.agent.weaver.Weaver;
6+
import com.newrelic.instrumentation.spring.async.Utils;
7+
8+
@Weave(originalName = "org.springframework.core.task.TaskExecutor", type = MatchType.Interface)
9+
public class TaskExecutor_Instrumentation {
10+
11+
public void execute(Runnable task) {
12+
Runnable wrapper = Utils.getWrappedRunnable(task);
13+
if(wrapper != null) {
14+
task = wrapper;
15+
}
16+
Weaver.callOriginal();
17+
}
18+
}

spring-async/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jar {
2323
}
2424

2525
verifyInstrumentation {
26-
passesOnly 'org.springframework:spring-core:[4.0.0.RELEASE,)'
26+
passesOnly 'org.springframework:spring-core:[4.0.0.RELEASE,7.0.0)'
2727
excludeRegex '.*M.*'
2828
excludeRegex '.*RC.*'
2929

0 commit comments

Comments
 (0)