Skip to content

Commit 65e5458

Browse files
committed
baseline
1 parent 6357e23 commit 65e5458

File tree

9 files changed

+246
-54
lines changed

9 files changed

+246
-54
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.newrelic.instrumentation.kotlin.coroutines;
2+
3+
import com.newrelic.agent.bridge.AgentBridge;
4+
import com.newrelic.api.agent.NewRelic;
5+
import com.newrelic.api.agent.Trace;
6+
7+
import kotlin.coroutines.Continuation;
8+
import kotlin.coroutines.CoroutineContext;
9+
10+
public class NRContinuationWrapper<T> implements Continuation<T> {
11+
12+
private Continuation<T> delegate = null;
13+
private static boolean isTransformed = false;
14+
15+
public NRContinuationWrapper(Continuation<T> d) {
16+
delegate = d;
17+
if(!isTransformed) {
18+
AgentBridge.instrumentation.retransformUninstrumentedClass(getClass());
19+
isTransformed = true;
20+
}
21+
}
22+
23+
@Override
24+
public CoroutineContext getContext() {
25+
return delegate.getContext();
26+
}
27+
28+
@Override
29+
@Trace(dispatcher=true)
30+
public void resumeWith(Object p0) {
31+
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","ContinuationWrapper","resumeWith",delegate.getClass().getSimpleName());
32+
delegate.resumeWith(p0);
33+
}
34+
35+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.newrelic.instrumentation.kotlin.coroutines;
2+
3+
import java.util.logging.Level;
4+
5+
import com.newrelic.agent.bridge.AgentBridge;
6+
import com.newrelic.api.agent.NewRelic;
7+
import com.newrelic.api.agent.Trace;
8+
9+
import kotlin.jvm.functions.Function1;
10+
11+
public class NRFunction1Wrapper<P1,R> implements Function1<P1, R> {
12+
13+
private Function1<P1, R> delegate = null;
14+
private String name = null;
15+
private static boolean isTransformed = false;
16+
17+
public NRFunction1Wrapper(Function1<P1, R> d, String n) {
18+
NewRelic.getAgent().getLogger().log(Level.FINE, "Wrapping Function1: {0} using name: {1}", d,n);
19+
delegate = d;
20+
name = n;
21+
if(!isTransformed) {
22+
isTransformed = true;
23+
AgentBridge.instrumentation.retransformUninstrumentedClass(getClass());
24+
}
25+
}
26+
27+
@Override
28+
@Trace(dispatcher=true)
29+
public R invoke(P1 p1) {
30+
if(name != null) NewRelic.getAgent().getTracedMethod().setMetricName("Custom","WrappedSuspend",name);
31+
if(delegate != null) {
32+
return delegate.invoke(p1);
33+
}
34+
return null;
35+
}
36+
37+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.newrelic.instrumentation.kotlin.coroutines;
2+
3+
import java.util.logging.Level;
4+
5+
import com.newrelic.agent.bridge.AgentBridge;
6+
import com.newrelic.api.agent.NewRelic;
7+
import com.newrelic.api.agent.Trace;
8+
9+
import kotlin.coroutines.Continuation;
10+
import kotlin.coroutines.jvm.internal.BaseContinuationImpl;
11+
import kotlin.jvm.functions.Function2;
12+
13+
public class NRFunction2Wrapper<P1, P2, R> implements Function2<P1, P2, R> {
14+
15+
private Function2<P1, P2, R> delegate = null;
16+
private String name = null;
17+
private static boolean isTransformed = false;
18+
19+
public NRFunction2Wrapper(Function2<P1, P2, R> d,String n) {
20+
NewRelic.getAgent().getLogger().log(Level.FINE, "Wrapping Function2: {0} - {1} using name: {2}", d, d.getClass().getName(),n);
21+
delegate = d;
22+
name = n;
23+
if(!isTransformed) {
24+
isTransformed = true;
25+
AgentBridge.instrumentation.retransformUninstrumentedClass(getClass());
26+
}
27+
}
28+
29+
@Override
30+
@Trace(dispatcher=true)
31+
public R invoke(P1 p1, P2 p2) {
32+
String nameStr = null;
33+
if(p2 instanceof Continuation) {
34+
Continuation continuation = (Continuation)p2;
35+
NRContinuationWrapper wrapper = new NRContinuationWrapper(continuation);
36+
p2 = (P2) wrapper;
37+
}
38+
if(nameStr == null) {
39+
nameStr = name;
40+
}
41+
if(nameStr != null) {
42+
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","WrappedSuspend",nameStr);
43+
}
44+
if(delegate != null) {
45+
return delegate.invoke(p1, p2);
46+
}
47+
return null;
48+
}
49+
50+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.newrelic.instrumentation.kotlin.coroutines;
2+
3+
public class Utils {
4+
5+
}

Kotlin-Coroutines_1.2/src/main/java/kotlinx/coroutines/AbstractCoroutine.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import com.newrelic.api.agent.weaver.MatchType;
66
import com.newrelic.api.agent.weaver.Weave;
77
import com.newrelic.api.agent.weaver.Weaver;
8+
import com.newrelic.instrumentation.kotlin.coroutines.NRFunction1Wrapper;
9+
import com.newrelic.instrumentation.kotlin.coroutines.NRFunction2Wrapper;
810

911
import kotlin.coroutines.Continuation;
1012
import kotlin.coroutines.CoroutineContext;
@@ -35,6 +37,8 @@ public final void start(CoroutineStart start, Function1<? super Continuation<? s
3537
if(name != null && !name.isEmpty()) {
3638
NewRelic.getAgent().getTracedMethod().setMetricName(new String[] {"Custom","Coroutine",name,"start"});
3739
}
40+
// NRFunction1Wrapper<? super Continuation<? super T>, ? extends Object> wrapper = new NRFunction1Wrapper(f,name);
41+
// f = wrapper;
3842
Weaver.callOriginal();
3943
}
4044

@@ -44,6 +48,8 @@ public final <R> void start(CoroutineStart start, R r, Function2<? super R, ? su
4448
if(name != null && !name.isEmpty()) {
4549
NewRelic.getAgent().getTracedMethod().setMetricName(new String[] {"Custom","Coroutine",name,"start"});
4650
}
51+
// NRFunction2Wrapper<? super R, ? super Continuation<? super T>, ? extends Object> wrapper = new NRFunction2Wrapper(f,name);
52+
// f = wrapper;
4753
Weaver.callOriginal();
4854
}
4955

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package kotlinx.coroutines;
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+
import com.newrelic.instrumentation.kotlin.coroutines.NRFunction2Wrapper;
7+
8+
import kotlin.Unit;
9+
import kotlin.coroutines.Continuation;
10+
import kotlin.coroutines.CoroutineContext;
11+
import kotlin.jvm.functions.Function2;
12+
13+
@Weave
14+
public class BuildersKt {
15+
16+
@Trace
17+
public static final <T> T runBlocking(CoroutineContext context, Function2<? super CoroutineScope, ? super Continuation<? super T>, ? extends Object> f) {
18+
if(!(f instanceof NRFunction2Wrapper)) {
19+
NRFunction2Wrapper<? super CoroutineScope, ? super Continuation<? super T>, ? extends Object> wrapper = new NRFunction2Wrapper(f,f.getClass().getName());
20+
f = wrapper;
21+
}
22+
return Weaver.callOriginal();
23+
}
24+
25+
@Trace
26+
public static final <T> Deferred<T> async(CoroutineScope scope, CoroutineContext context, CoroutineStart cStart, Function2<? super CoroutineScope, ? super Continuation<? super T>, ? extends Object> f) {
27+
if(!(f instanceof NRFunction2Wrapper)) {
28+
NRFunction2Wrapper<? super CoroutineScope, ? super Continuation<? super T>, ? extends Object> wrapper = new NRFunction2Wrapper(f,f.getClass().getName());
29+
f = wrapper;
30+
}
31+
return Weaver.callOriginal();
32+
}
33+
34+
@Trace
35+
public static final <T> Object invoke(CoroutineDispatcher dispatcher, Function2<? super CoroutineScope, ? super Continuation<? super T>, ? extends Object> f, Continuation<? super T> c) {
36+
if(!(f instanceof NRFunction2Wrapper)) {
37+
NRFunction2Wrapper<? super CoroutineScope, ? super Continuation<? super T>, ? extends Object> wrapper = new NRFunction2Wrapper(f,f.getClass().getName());
38+
f = wrapper;
39+
}
40+
return Weaver.callOriginal();
41+
}
42+
43+
@Trace
44+
public static final kotlinx.coroutines.Job launch(CoroutineScope scope, CoroutineContext context, CoroutineStart cStart, Function2<? super CoroutineScope, ? super Continuation<? super Unit>, ? extends Object> f) {
45+
if(!(f instanceof NRFunction2Wrapper)) {
46+
NRFunction2Wrapper<? super CoroutineScope, ? super Continuation<? super Unit>, ? extends Object> wrapper = new NRFunction2Wrapper(f,f.getClass().getName());
47+
f = wrapper;
48+
}
49+
return Weaver.callOriginal();
50+
}
51+
}

Kotlin-Coroutines_1.2/src/main/java/kotlinx/coroutines/CancellableContinuation.java

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package kotlinx.coroutines;
2+
3+
import java.util.logging.Level;
4+
5+
import com.newrelic.api.agent.NewRelic;
6+
import com.newrelic.api.agent.Token;
7+
import com.newrelic.api.agent.Trace;
8+
import com.newrelic.api.agent.weaver.NewField;
9+
import com.newrelic.api.agent.weaver.Weave;
10+
import com.newrelic.api.agent.weaver.Weaver;
11+
12+
import kotlin.coroutines.Continuation;
13+
14+
@Weave
15+
public abstract class CancellableContinuationImpl<T> extends DispatchedTask<T> {
16+
17+
@NewField
18+
public Token token = null;
19+
20+
public CancellableContinuationImpl(Continuation<? super T> c, int mode) {
21+
NewRelic.getAgent().getLogger().log(Level.FINE, new Exception("new CancellableContinuationImpl"), "created CancellableContinuationImpl with Continuation {0} on Thread: {1}",c, Thread.currentThread().getName());
22+
23+
}
24+
25+
public abstract boolean isActive();
26+
public abstract boolean isCompleted();
27+
public abstract boolean isCancelled();
28+
29+
@Trace
30+
public void resumeUndispatched(kotlinx.coroutines.CoroutineDispatcher d, T t) {
31+
Weaver.callOriginal();
32+
}
33+
34+
@Trace
35+
public void resumeUndispatchedWithException(kotlinx.coroutines.CoroutineDispatcher d, Throwable t) {
36+
NewRelic.noticeError(t);
37+
Weaver.callOriginal();
38+
}
39+
40+
}
Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,29 @@
11
package kotlinx.coroutines;
22

3-
//import com.newrelic.api.agent.NewRelic;
4-
//import com.newrelic.api.agent.Token;
5-
//import com.newrelic.api.agent.Trace;
6-
import com.newrelic.api.agent.weaver.MatchType;
7-
//import com.newrelic.api.agent.weaver.NewField;
3+
import java.util.logging.Level;
4+
5+
import com.newrelic.api.agent.NewRelic;
6+
import com.newrelic.api.agent.Trace;
87
import com.newrelic.api.agent.weaver.Weave;
9-
//import com.newrelic.api.agent.weaver.Weaver;
8+
import com.newrelic.api.agent.weaver.Weaver;
109

11-
@Weave(type=MatchType.BaseClass)
10+
@Weave
1211
public abstract class DispatchedTask<T> {
13-
14-
// @NewField
15-
// protected Token token = null;
16-
//
17-
// public DispatchedTask(int mode) {
18-
// if(token == null) {
19-
// Token t = NewRelic.getAgent().getTransaction().getToken();
20-
// if(t != null && t.isActive()) {
21-
// token = t;
22-
// } else if(t != null) {
23-
// t.expire();
24-
// t = null;
25-
// }
26-
// }
27-
// }
28-
//
29-
// @Trace(async=true)
30-
// public void run() {
31-
// if(token != null) {
32-
// token.linkAndExpire();
33-
// token = null;
34-
// }
35-
// Weaver.callOriginal();
36-
// }
12+
13+
@Trace(async=true)
14+
public void run() {
15+
if(this instanceof CancellableContinuationImpl) {
16+
CancellableContinuationImpl<T> cancelable = (CancellableContinuationImpl<T>)this;
17+
NewRelic.getAgent().getLogger().log(Level.FINE, "call to CancellableContinuationImpl.run(), token: {0}, active: {1}, cancelled: {2}, completed: {3}", cancelable.token, cancelable.isActive(), cancelable.isCancelled(),cancelable.isCompleted());
18+
if(cancelable.token != null) {
19+
cancelable.token.link();
20+
if(!cancelable.isActive() || cancelable.isCancelled() || cancelable.isCompleted()) {
21+
cancelable.token.expire();
22+
cancelable.token = null;
23+
}
24+
}
25+
}
26+
Weaver.callOriginal();
27+
}
3728

3829
}

0 commit comments

Comments
 (0)