Skip to content

Commit 39a2a53

Browse files
authored
Merge pull request #27 from newrelic/ktor_fixes
added ignores for CoroutineScope to ignore selected Coroutines, neede…
2 parents a107caf + c294d4b commit 39a2a53

File tree

9 files changed

+330
-122
lines changed

9 files changed

+330
-122
lines changed

Kotlin-Coroutines_1.4/src/main/java/com/newrelic/instrumentation/kotlin/coroutines_14/Utils.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
import kotlin.coroutines.jvm.internal.BaseContinuationImpl;
1717
import kotlinx.coroutines.AbstractCoroutine;
1818
import kotlinx.coroutines.CoroutineName;
19+
import kotlinx.coroutines.CoroutineScope;
1920
import kotlinx.coroutines.DispatchedTask;
2021

2122
public class Utils implements AgentConfigListener {
2223

2324
private static final List<String> ignoredContinuations = new ArrayList<String>();
25+
private static final List<String> ignoredScopes = new ArrayList<>();
2426
private static final String CONTIGNORECONFIG = "Coroutines.ignores.continuations";
27+
private static final String SCOPESIGNORECONFIG = "Coroutines.ignores.scopes";
2528
private static final String DISPATCHEDIGNORECONFIG = "Coroutines.ignores.dispatched";
2629
private static final String DELAYED_ENABLED_CONFIG = "Coroutines.delayed.enabled";
2730

@@ -95,6 +98,32 @@ private static void loadConfig(Config config) {
9598
if (ignores != null && !ignores.isEmpty()) {
9699
DispatchedTaskIgnores.configure(ignores);
97100
}
101+
ignores = config.getValue(SCOPESIGNORECONFIG);
102+
if (ignores != null && !ignores.isEmpty()) {
103+
ignoredScopes.clear();
104+
String[] ignoresList = ignores.split(",");
105+
106+
for(String ignore : ignoresList) {
107+
if (!ignoredScopes.contains(ignore)) {
108+
ignoredScopes.add(ignore);
109+
NewRelic.getAgent().getLogger().log(Level.FINE, "Will ignore CoroutineScopes named {0}", ignore);
110+
}
111+
}
112+
} else if(!ignoredScopes.isEmpty()) {
113+
ignoredScopes.clear();
114+
}
115+
116+
}
117+
118+
public static boolean ignoreScope(CoroutineScope scope) {
119+
CoroutineContext ctx = scope.getCoroutineContext();
120+
String name = getCoroutineName(ctx);
121+
String className = scope.getClass().getName();
122+
return ignoreScope(className) || ignoreScope(name);
123+
}
124+
125+
public static boolean ignoreScope(String coroutineScope) {
126+
return ignoredScopes.contains(coroutineScope);
98127
}
99128

100129
public static boolean ignoreContinuation(String cont_string) {
@@ -193,4 +222,4 @@ public static <T> String getContinuationString(Continuation<T> continuation) {
193222

194223
return null;
195224
}
196-
}
225+
}

Kotlin-Coroutines_1.4/src/main/java/kotlinx/coroutines/BuildersKt.java

Lines changed: 73 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package kotlinx.coroutines;
22

33
import com.newrelic.api.agent.NewRelic;
4+
import com.newrelic.api.agent.Token;
45
import com.newrelic.api.agent.Trace;
56
import com.newrelic.api.agent.weaver.Weave;
67
import com.newrelic.api.agent.weaver.Weaver;
@@ -21,9 +22,14 @@ public class BuildersKt {
2122

2223
@Trace(dispatcher = true)
2324
public static final <T> T runBlocking(CoroutineContext context, Function2<? super CoroutineScope, ? super Continuation<? super T>, ? extends Object> block) {
24-
NRCoroutineToken nrContextToken = Utils.setToken(context);
25-
if(nrContextToken != null) {
26-
context = context.plus(nrContextToken);
25+
Token token = Utils.getToken(context);
26+
if(token != null) {
27+
token.link();
28+
} else {
29+
NRCoroutineToken nrContextToken = Utils.setToken(context);
30+
if(nrContextToken != null) {
31+
context = context.plus(nrContextToken);
32+
}
2733
}
2834
String name = Utils.getCoroutineName(context);
2935
if(name != null) {
@@ -43,23 +49,32 @@ public static final <T> T runBlocking(CoroutineContext context, Function2<? supe
4349

4450
@Trace(dispatcher = true)
4551
public static final <T> Deferred<T> async(CoroutineScope scope, CoroutineContext context, CoroutineStart cStart, Function2<? super CoroutineScope, ? super Continuation<? super T>, ? extends Object> block) {
46-
String name = Utils.getCoroutineName(context);
47-
if(name == null) {
48-
name = Utils.getCoroutineName(scope.getCoroutineContext());
49-
}
50-
if(name != null) {
51-
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Builders","async",name);
52-
} else {
53-
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Builders","async");
54-
}
52+
if (!Utils.ignoreScope(scope)) {
53+
String name = Utils.getCoroutineName(context);
54+
if(name == null) {
55+
name = Utils.getCoroutineName(scope.getCoroutineContext());
56+
}
57+
if(name != null) {
58+
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Builders","async",name);
59+
} else {
60+
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Builders","async");
61+
}
5562

56-
NRCoroutineToken nrContextToken = Utils.setToken(context);
57-
if(nrContextToken != null) {
58-
context = context.plus(nrContextToken);
59-
}
60-
if(!(block instanceof NRFunction2Wrapper)) {
61-
NRFunction2Wrapper<? super CoroutineScope, ? super Continuation<? super T>, ? extends Object> wrapper = new NRFunction2Wrapper(block);
62-
block = wrapper;
63+
Token token = Utils.getToken(context);
64+
if(token != null) {
65+
token.link();
66+
} else {
67+
NRCoroutineToken nrContextToken = Utils.setToken(context);
68+
if(nrContextToken != null) {
69+
context = context.plus(nrContextToken);
70+
}
71+
}
72+
if(!(block instanceof NRFunction2Wrapper)) {
73+
NRFunction2Wrapper<? super CoroutineScope, ? super Continuation<? super T>, ? extends Object> wrapper = new NRFunction2Wrapper(block);
74+
block = wrapper;
75+
}
76+
} else {
77+
NewRelic.getAgent().getTransaction().ignore();
6378
}
6479
return Weaver.callOriginal();
6580
}
@@ -86,24 +101,38 @@ public static final <T> Object invoke(CoroutineDispatcher dispatcher, Function2<
86101

87102
@Trace(dispatcher = true)
88103
public static final kotlinx.coroutines.Job launch(CoroutineScope scope, CoroutineContext context, CoroutineStart cStart, Function2<? super CoroutineScope, ? super Continuation<? super Unit>, ? extends Object> block) {
89-
NewRelic.getAgent().getTracedMethod().addCustomAttribute("CoroutineStart", cStart.name());
90-
String name = Utils.getCoroutineName(context);
91-
if(name == null) {
92-
name = Utils.getCoroutineName(scope.getCoroutineContext());
93-
}
94-
if(name != null) {
95-
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Builders","launch",name);
104+
if (!Utils.ignoreScope(scope)) {
105+
NewRelic.getAgent().getTracedMethod().addCustomAttribute("CoroutineStart", cStart.name());
106+
NewRelic.getAgent().getTracedMethod().addCustomAttribute("CoroutineScope-Class", scope.getClass().getName());
107+
108+
String name = Utils.getCoroutineName(context);
109+
if (name == null) {
110+
name = Utils.getCoroutineName(scope.getCoroutineContext());
111+
}
112+
if (name != null) {
113+
NewRelic.getAgent().getTracedMethod().setMetricName("Custom", "Builders", "launch", name);
114+
NewRelic.getAgent().getTracedMethod().addCustomAttribute("CoroutineName", name);
115+
} else {
116+
NewRelic.getAgent().getTracedMethod().setMetricName("Custom", "Builders", "launch");
117+
NewRelic.getAgent().getTracedMethod().addCustomAttribute("CoroutineName", "Could not determine");
118+
}
119+
NewRelic.getAgent().getTracedMethod().addCustomAttribute("Block", block.toString());
120+
Token token = Utils.getToken(context);
121+
if(token != null) {
122+
token.link();
123+
} else {
124+
NRCoroutineToken nrContextToken = Utils.setToken(context);
125+
if(nrContextToken != null) {
126+
context = context.plus(nrContextToken);
127+
}
128+
}
129+
if (!(block instanceof NRFunction2Wrapper)) {
130+
NRFunction2Wrapper<? super CoroutineScope, ? super Continuation<? super Unit>, ? extends Object> wrapper = new NRFunction2Wrapper(
131+
block);
132+
block = wrapper;
133+
}
96134
} else {
97-
NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Builders","launch");
98-
}
99-
NewRelic.getAgent().getTracedMethod().addCustomAttribute("Block", block.toString());
100-
NRCoroutineToken nrContextToken = Utils.setToken(context);
101-
if(nrContextToken != null) {
102-
context = context.plus(nrContextToken);
103-
}
104-
if(!(block instanceof NRFunction2Wrapper)) {
105-
NRFunction2Wrapper<? super CoroutineScope, ? super Continuation<? super Unit>, ? extends Object> wrapper = new NRFunction2Wrapper(block);
106-
block = wrapper;
135+
NewRelic.getAgent().getTransaction().ignore();
107136
}
108137
Job j = Weaver.callOriginal();
109138
return j;
@@ -121,9 +150,14 @@ public static final <T> Object withContext(CoroutineContext context,Function2<?
121150
NewRelic.getAgent().getTracedMethod().addCustomAttribute("Completion", completion.toString());
122151
}
123152

124-
NRCoroutineToken nrContextToken = Utils.setToken(context);
125-
if(nrContextToken != null) {
126-
context = context.plus(nrContextToken);
153+
Token token = Utils.getToken(context);
154+
if(token != null) {
155+
token.link();
156+
} else {
157+
NRCoroutineToken nrContextToken = Utils.setToken(context);
158+
if(nrContextToken != null) {
159+
context = context.plus(nrContextToken);
160+
}
127161
}
128162
if(!(block instanceof NRFunction2Wrapper)) {
129163
NRFunction2Wrapper<? super CoroutineScope, ? super Continuation<? super T>, ? extends Object> wrapper = new NRFunction2Wrapper(block);

Kotlin-Coroutines_1.5/src/main/java/com/newrelic/instrumentation/kotlin/coroutines_15/Utils.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
import kotlin.coroutines.jvm.internal.BaseContinuationImpl;
1717
import kotlinx.coroutines.AbstractCoroutine;
1818
import kotlinx.coroutines.CoroutineName;
19+
import kotlinx.coroutines.CoroutineScope;
1920
import kotlinx.coroutines.DispatchedTask;
2021

2122
public class Utils implements AgentConfigListener {
2223

2324
private static final List<String> ignoredContinuations = new ArrayList<String>();
25+
private static final List<String> ignoredScopes = new ArrayList<>();
2426
private static final String CONTIGNORECONFIG = "Coroutines.ignores.continuations";
27+
private static final String SCOPESIGNORECONFIG = "Coroutines.ignores.scopes";
2528
private static final String DISPATCHEDIGNORECONFIG = "Coroutines.ignores.dispatched";
2629
private static final String DELAYED_ENABLED_CONFIG = "Coroutines.delayed.enabled";
2730

@@ -95,6 +98,32 @@ private static void loadConfig(Config config) {
9598
if (ignores != null && !ignores.isEmpty()) {
9699
DispatchedTaskIgnores.configure(ignores);
97100
}
101+
ignores = config.getValue(SCOPESIGNORECONFIG);
102+
if (ignores != null && !ignores.isEmpty()) {
103+
ignoredScopes.clear();
104+
String[] ignoresList = ignores.split(",");
105+
106+
for(String ignore : ignoresList) {
107+
if (!ignoredScopes.contains(ignore)) {
108+
ignoredScopes.add(ignore);
109+
NewRelic.getAgent().getLogger().log(Level.FINE, "Will ignore CoroutineScopes named {0}", ignore);
110+
}
111+
}
112+
} else if(!ignoredScopes.isEmpty()) {
113+
ignoredScopes.clear();
114+
}
115+
116+
}
117+
118+
public static boolean ignoreScope(CoroutineScope scope) {
119+
CoroutineContext ctx = scope.getCoroutineContext();
120+
String name = getCoroutineName(ctx);
121+
String className = scope.getClass().getName();
122+
return ignoreScope(className) || ignoreScope(name);
123+
}
124+
125+
public static boolean ignoreScope(String coroutineScope) {
126+
return ignoredScopes.contains(coroutineScope);
98127
}
99128

100129
public static boolean ignoreContinuation(String cont_string) {
@@ -193,4 +222,4 @@ public static <T> String getContinuationString(Continuation<T> continuation) {
193222

194223
return null;
195224
}
196-
}
225+
}

0 commit comments

Comments
 (0)