generated from newrelic-experimental/java-instrumentation-template
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #35 from newrelic/support_1.9
updated to support Kotlin Coroutines 1.9
- Loading branch information
Showing
26 changed files
with
1,264 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
|
||
// Build.gradle generated for instrumentation module Kotlin-Coroutines_1.2 | ||
|
||
apply plugin: 'java' | ||
|
||
targetCompatibility = JavaVersion.VERSION_1_9 | ||
|
||
dependencies { | ||
implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.9.0' | ||
|
||
// New Relic Java Agent dependencies | ||
implementation 'com.newrelic.agent.java:newrelic-agent:6.0.0' | ||
implementation 'com.newrelic.agent.java:newrelic-api:6.0.0' | ||
implementation fileTree(include: ['*.jar'], dir: '../libs') | ||
} | ||
|
||
jar { | ||
manifest { | ||
attributes 'Implementation-Title': 'com.newrelic.instrumentation.labs.Kotlin-Coroutines_1.9' | ||
attributes 'Implementation-Vendor': 'New Relic Labs' | ||
attributes 'Implementation-Vendor-Id': 'com.newrelic.labs' | ||
attributes 'Implementation-Version': 2.0 | ||
} | ||
} | ||
|
||
verifyInstrumentation { | ||
passes 'org.jetbrains.kotlinx:kotlinx-coroutines-core:[1.9.0,)]' | ||
passes 'org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:[1.9.0,)' | ||
excludeRegex '.*SNAPSHOT' | ||
excludeRegex '.*alpha' | ||
excludeRegex '.*-eap-.*' | ||
excludeRegex '.*-native-.*' | ||
excludeRegex '.*-M[0-9]' | ||
excludeRegex '.*-rc' | ||
excludeRegex '.*-RC' | ||
excludeRegex '.*-RC[0-9]' | ||
excludeRegex '.*-Beta' | ||
} |
46 changes: 46 additions & 0 deletions
46
...rc/main/java/com/newrelic/instrumentation/kotlin/coroutines_17/DispatchedTaskIgnores.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package com.newrelic.instrumentation.kotlin.coroutines_17; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.logging.Level; | ||
|
||
import com.newrelic.api.agent.Config; | ||
import com.newrelic.api.agent.NewRelic; | ||
|
||
public class DispatchedTaskIgnores { | ||
|
||
private static List<String> ignoredTasks = new ArrayList<>(); | ||
private static final String DISPATCHEDIGNORECONFIG = "Coroutines.ignores.dispatched"; | ||
|
||
static { | ||
Config config = NewRelic.getAgent().getConfig(); | ||
String ignores = config.getValue(DISPATCHEDIGNORECONFIG); | ||
configure(ignores); | ||
|
||
} | ||
|
||
|
||
public static boolean ignoreDispatchedTask(String contString) { | ||
return ignoredTasks.contains(contString); | ||
} | ||
|
||
public static void addIgnore(String ignore) { | ||
if(!ignoredTasks.contains(ignore)) { | ||
ignoredTasks.add(ignore); | ||
NewRelic.getAgent().getLogger().log(Level.FINE, "Will ignore DispatchedTasks with continuation string {0}", ignore); | ||
} | ||
} | ||
|
||
public static void reset() { | ||
ignoredTasks.clear(); | ||
} | ||
|
||
protected static void configure(String result) { | ||
if(result == null || result.isEmpty()) return; | ||
String[] ignores = result.split(","); | ||
for(String ignore : ignores) { | ||
addIgnore(ignore); | ||
} | ||
} | ||
|
||
} |
51 changes: 51 additions & 0 deletions
51
...rc/main/java/com/newrelic/instrumentation/kotlin/coroutines_17/NRContinuationWrapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package com.newrelic.instrumentation.kotlin.coroutines_17; | ||
|
||
import com.newrelic.agent.bridge.AgentBridge; | ||
import com.newrelic.api.agent.NewRelic; | ||
import com.newrelic.api.agent.Token; | ||
import com.newrelic.api.agent.Trace; | ||
|
||
import kotlin.coroutines.Continuation; | ||
import kotlin.coroutines.CoroutineContext; | ||
|
||
public class NRContinuationWrapper<T> implements Continuation<T> { | ||
|
||
private Continuation<T> delegate = null; | ||
private String name = null; | ||
private static boolean isTransformed = false; | ||
|
||
public NRContinuationWrapper(Continuation<T> d, String n) { | ||
delegate = d; | ||
name = n; | ||
if(!isTransformed) { | ||
AgentBridge.instrumentation.retransformUninstrumentedClass(getClass()); | ||
isTransformed = true; | ||
} | ||
} | ||
|
||
@Override | ||
public CoroutineContext getContext() { | ||
return delegate.getContext(); | ||
} | ||
|
||
@Override | ||
@Trace(async=true) | ||
public void resumeWith(Object p0) { | ||
String contString = Utils.getContinuationString(delegate); | ||
if(contString != null && !contString.isEmpty()) { | ||
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","ContinuationWrapper","resumeWith",contString); | ||
} else if(name != null) { | ||
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","ContinuationWrapper","resumeWith",name); | ||
} else { | ||
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","ContinuationWrapper","resumeWith",p0.getClass().getName()); | ||
} | ||
Token t = Utils.getToken(getContext()); | ||
if(t != null) { | ||
t.link(); | ||
} | ||
if(delegate != null) { | ||
delegate.resumeWith(p0); | ||
} | ||
} | ||
|
||
} |
51 changes: 51 additions & 0 deletions
51
...1.9/src/main/java/com/newrelic/instrumentation/kotlin/coroutines_17/NRCoroutineToken.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package com.newrelic.instrumentation.kotlin.coroutines_17; | ||
|
||
import com.newrelic.api.agent.Token; | ||
|
||
import kotlin.coroutines.AbstractCoroutineContextElement; | ||
import kotlin.coroutines.CoroutineContext; | ||
|
||
public class NRCoroutineToken extends AbstractCoroutineContextElement | ||
{ | ||
public static Key key = new Key(); | ||
|
||
public NRCoroutineToken(Token t) { | ||
super(key); | ||
token = t; | ||
} | ||
|
||
private Token token = null; | ||
|
||
public static final class Key implements CoroutineContext.Key<NRCoroutineToken> { | ||
private Key() {} | ||
} | ||
|
||
public Token getToken() { | ||
return token; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return token.hashCode(); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if(this != obj ) { | ||
if(obj instanceof NRCoroutineToken) { | ||
NRCoroutineToken t = (NRCoroutineToken)obj; | ||
return t.token == token; | ||
} | ||
} else { | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "NRCoroutineToken"; | ||
} | ||
|
||
|
||
} |
36 changes: 36 additions & 0 deletions
36
...9/src/main/java/com/newrelic/instrumentation/kotlin/coroutines_17/NRFunction1Wrapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.newrelic.instrumentation.kotlin.coroutines_17; | ||
|
||
import com.newrelic.agent.bridge.AgentBridge; | ||
|
||
import kotlin.coroutines.Continuation; | ||
import kotlin.coroutines.jvm.internal.SuspendFunction; | ||
import kotlin.jvm.functions.Function1; | ||
|
||
public class NRFunction1Wrapper<P1, R> implements Function1<P1, R> { | ||
|
||
private Function1<P1, R> delegate = null; | ||
private static boolean isTransformed = false; | ||
|
||
public NRFunction1Wrapper(Function1<P1,R> d) { | ||
delegate = d; | ||
if(!isTransformed) { | ||
AgentBridge.instrumentation.retransformUninstrumentedClass(getClass()); | ||
isTransformed = true; | ||
} | ||
} | ||
|
||
@SuppressWarnings({ "rawtypes", "unchecked" }) | ||
@Override | ||
public R invoke(P1 p1) { | ||
if(p1 instanceof Continuation && !(p1 instanceof SuspendFunction)) { | ||
// wrap if needed | ||
if(!(p1 instanceof NRContinuationWrapper)) { | ||
String cont_string = Utils.getContinuationString((Continuation)p1); | ||
NRContinuationWrapper wrapper = new NRContinuationWrapper<>((Continuation)p1, cont_string); | ||
p1 = (P1) wrapper; | ||
} | ||
} | ||
return delegate != null ? delegate.invoke(p1) : null; | ||
} | ||
|
||
} |
40 changes: 40 additions & 0 deletions
40
...9/src/main/java/com/newrelic/instrumentation/kotlin/coroutines_17/NRFunction2Wrapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package com.newrelic.instrumentation.kotlin.coroutines_17; | ||
|
||
import com.newrelic.agent.bridge.AgentBridge; | ||
|
||
import kotlin.coroutines.Continuation; | ||
import kotlin.coroutines.jvm.internal.SuspendFunction; | ||
import kotlin.jvm.functions.Function2; | ||
|
||
public class NRFunction2Wrapper<P1, P2, R> implements Function2<P1, P2, R> { | ||
|
||
private Function2<P1, P2, R> delegate = null; | ||
private static boolean isTransformed = false; | ||
|
||
public NRFunction2Wrapper(Function2<P1, P2, R> d) { | ||
delegate = d; | ||
if(!isTransformed) { | ||
isTransformed = true; | ||
AgentBridge.instrumentation.retransformUninstrumentedClass(getClass()); | ||
} | ||
} | ||
|
||
@SuppressWarnings({ "rawtypes", "unchecked" }) | ||
@Override | ||
public R invoke(P1 p1, P2 p2) { | ||
|
||
if(p2 instanceof Continuation && !(p2 instanceof SuspendFunction)) { | ||
// wrap if needed | ||
String cont_string = Utils.getContinuationString((Continuation)p2); | ||
if(!(p2 instanceof NRContinuationWrapper) && !Utils.ignoreContinuation(cont_string)) { | ||
NRContinuationWrapper wrapper = new NRContinuationWrapper<>((Continuation)p2, cont_string); | ||
p2 = (P2) wrapper; | ||
} | ||
} | ||
if(delegate != null) { | ||
return delegate.invoke(p1, p2); | ||
} | ||
return null; | ||
} | ||
|
||
} |
53 changes: 53 additions & 0 deletions
53
...tines_1.9/src/main/java/com/newrelic/instrumentation/kotlin/coroutines_17/NRRunnable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.newrelic.instrumentation.kotlin.coroutines_17; | ||
|
||
import com.newrelic.agent.bridge.AgentBridge; | ||
import com.newrelic.api.agent.NewRelic; | ||
import com.newrelic.api.agent.Token; | ||
import com.newrelic.api.agent.Trace; | ||
|
||
import kotlin.coroutines.Continuation; | ||
import kotlinx.coroutines.DispatchedTask; | ||
|
||
public class NRRunnable implements Runnable { | ||
|
||
private Runnable delegate = null; | ||
private Token token = null; | ||
private static boolean isTransformed = false; | ||
|
||
public NRRunnable(Runnable r,Token t) { | ||
if(!isTransformed) { | ||
AgentBridge.instrumentation.retransformUninstrumentedClass(getClass()); | ||
isTransformed = true; | ||
} | ||
delegate = r; | ||
token = t; | ||
} | ||
|
||
@Override | ||
@Trace(async = true) | ||
public void run() { | ||
boolean nameSet = false; | ||
if(delegate != null && delegate instanceof DispatchedTask) { | ||
DispatchedTask<?> task = (DispatchedTask<?>)delegate; | ||
Continuation<?> cont_delegate = task.getDelegate$kotlinx_coroutines_core(); | ||
if(cont_delegate != null) { | ||
String cont_string = Utils.getContinuationString(cont_delegate); | ||
if(cont_string == null) cont_string = cont_delegate.getClass().getName(); | ||
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","DispatchedTask",Utils.getContinuationString(cont_delegate)); | ||
nameSet = true; | ||
} | ||
} | ||
if(!nameSet) { | ||
String delegateType = delegate != null ? delegate.getClass().getName() : "null"; | ||
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Kotlin","AsyncRunnableWrapper",delegateType); | ||
} | ||
if(token != null) { | ||
token.linkAndExpire(); | ||
token = null; | ||
} | ||
if(delegate != null) { | ||
delegate.run(); | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.