Skip to content

Commit 8b356a8

Browse files
author
Doug Hilpipre
committed
baseline
1 parent 40e56b1 commit 8b356a8

20 files changed

Lines changed: 364 additions & 285 deletions

File tree

ktor-client-cio-2.0.2/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ dependencies {
1616
tasks.jar {
1717
manifest {
1818
attributes(
19-
"Implementation-Title" to "com.newrelic.instrumentation.labs.ktor-client-cio",
19+
"Implementation-Title" to "com.newrelic.instrumentation.labs.ktor-client-cio-2.0.2",
2020
"Implementation-Vendor" to "New Relic Labs",
2121
"Implementation-Vendor-Id" to "com.newrelic.labs",
2222
"Implementation-Version" to 1.0
@@ -25,5 +25,5 @@ tasks.jar {
2525
}
2626

2727
verifyInstrumentation {
28-
passes("io.ktor:ktor-client-cio-jvm:[2.0.2,)")
28+
passesOnly("io.ktor:ktor-client-cio-jvm:[2.0.2,3.2.0)")
2929
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.ktor.client.engine.cio;
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 io.ktor.client.request.HttpRequestData;
7+
import io.ktor.client.request.HttpResponseData;
8+
import kotlin.coroutines.Continuation;
9+
10+
@Weave(originalName = "io.ktor.client.engine.cio.CIOEngine")
11+
public class CIOEngine_Instrumentation {
12+
13+
@Trace(dispatcher = true)
14+
public Object execute(HttpRequestData requestData, Continuation<? super HttpResponseData> continuation) {
15+
return Weaver.callOriginal();
16+
}
17+
18+
@Trace(dispatcher = true)
19+
public void close() {
20+
Weaver.callOriginal();
21+
}
22+
23+
}
Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,58 @@
11
package io.ktor.client.engine.cio;
22

3-
import com.newrelic.api.agent.Trace;
3+
import com.newrelic.api.agent.*;
4+
import com.newrelic.api.agent.weaver.NewField;
45
import com.newrelic.api.agent.weaver.Weave;
56
import com.newrelic.api.agent.weaver.Weaver;
7+
import com.sun.jndi.toolkit.url.UrlUtil;
68
import io.ktor.client.request.HttpRequestData;
79
import io.ktor.client.request.HttpResponseData;
10+
import io.ktor.http.Url;
11+
import kotlin.Unit;
812
import kotlin.coroutines.Continuation;
913
import kotlin.coroutines.CoroutineContext;
14+
import java.net.Proxy;
15+
import java.net.URI;
16+
17+
import kotlin.jvm.functions.Function0;
1018

1119
@Weave(originalName = "io.ktor.client.engine.cio.Endpoint")
1220
public class Endpoint_Instrumentation {
1321

22+
@NewField
23+
private Segment segment = null;
24+
25+
public Endpoint_Instrumentation(String host, int port, Proxy proxy, boolean secure, CIOEngineConfig config, ConnectionFactory connectionFactory,
26+
CoroutineContext coroutineContext, Function0<Unit> onDone) {
27+
28+
}
29+
1430
@Trace
1531
public Object execute(HttpRequestData request, CoroutineContext coroutineContext, Continuation<? super HttpResponseData> continuation) {
32+
Url url = request.getUrl();
33+
URI uri = URI.create(url.toString());
34+
HttpParameters httpParameters = HttpParameters.library("Ktor-CIO-Client").uri(uri).procedure(request.getMethod().toString()).noInboundHeaders().build();
35+
segment = NewRelic.getAgent().getTransaction().startSegment("CIOClientRequest");
36+
segment.reportAsExternal(httpParameters);
37+
return Weaver.callOriginal();
38+
}
39+
40+
@Trace
41+
private Object makePipelineRequest(RequestTask requestTask, Continuation<? super Unit> continuation) {
1642
return Weaver.callOriginal();
1743
}
1844

45+
@Trace
46+
private Object makeDedicatedRequest(HttpRequestData requestData, CoroutineContext coroutineContext, Continuation<? super HttpResponseData> continuation) {
47+
return Weaver.callOriginal();
48+
}
49+
50+
@Trace(dispatcher = true)
51+
public void close() {
52+
if(segment != null) {
53+
segment.end();
54+
segment = null;
55+
}
56+
Weaver.callOriginal();
57+
}
1958
}

ktor-client-cio-2.0.2/src/main/java/io/ktor/client/engine/cio/UtilsKt_Instrumentation.java

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,39 @@
1616
import kotlin.coroutines.Continuation;
1717
import kotlin.coroutines.CoroutineContext;
1818

19+
import java.util.logging.Level;
20+
1921
@Weave(originalName = "io.ktor.client.engine.cio.UtilsKt")
2022
public class UtilsKt_Instrumentation {
2123

2224
@Trace(dispatcher = true)
2325
public static Object writeRequest(HttpRequestData requestData, ByteWriteChannel writeChannel, CoroutineContext coroutineContext, boolean overProxy, boolean closeChannel, Continuation<? super Unit> continuation) {
24-
TokenContext tokenContext = NRTokenContextKt.getTokenContextOrNull(coroutineContext);
25-
if(tokenContext == null) {
26-
Token token = NewRelic.getAgent().getTransaction().getToken();
27-
if(token != null) {
28-
if(token.isActive()) {
29-
NRTokenContextKt.addTokenContext(coroutineContext, token);
30-
} else {
31-
token.expire();
32-
token = null;
33-
}
34-
}
35-
}
26+
NewRelic.getAgent().getLogger().log(Level.FINER, new Exception("call to writeRequest"),"Writing request : {0}", requestData);
27+
// TokenContext tokenContext = NRTokenContextKt.getTokenContextOrNull(coroutineContext);
28+
// if(tokenContext == null) {
29+
// Token token = NewRelic.getAgent().getTransaction().getToken();
30+
// if(token != null) {
31+
// if(token.isActive()) {
32+
// NRTokenContextKt.addTokenContext(coroutineContext, token);
33+
// } else {
34+
// token.expire();
35+
// token = null;
36+
// }
37+
// }
38+
// }
3639
return Weaver.callOriginal();
3740
}
3841

3942
@Trace(dispatcher = true)
4043
public static Object readResponse(GMTDate date, HttpRequestData requestData, ByteReadChannel readChannel, ByteWriteChannel writeChannel, CoroutineContext coroutineContext, Continuation<? super HttpResponseData> continuation) {
41-
TokenContext tokenContext = NRTokenContextKt.getTokenContextOrNull(coroutineContext);
42-
if(tokenContext != null) {
43-
Token token = tokenContext.getToken();
44-
token.linkAndExpire();
45-
token = null;
46-
NRTokenContextKt.removeTokenContext(coroutineContext);
47-
}
44+
NewRelic.getAgent().getLogger().log(Level.FINER, new Exception("call to readResponse"),"Reading response for : {0}", requestData);
45+
// TokenContext tokenContext = NRTokenContextKt.getTokenContextOrNull(coroutineContext);
46+
// if(tokenContext != null) {
47+
// Token token = tokenContext.getToken();
48+
// token.linkAndExpire();
49+
// token = null;
50+
// NRTokenContextKt.removeTokenContext(coroutineContext);
51+
// }
4852
return Weaver.callOriginal();
4953
}
5054
}
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,29 @@
1-
// Build.gradle generated for instrumentation module ktor-server-setup
1+
// Build.gradle generated for instrumentation module ktor-client-cio
22

33
apply(plugin = "java")
44

55
dependencies {
6-
// Declare a dependency on each JAR you want to instrument
7-
// Example:
8-
// implementation("javax.servlet:servlet-api:2.5")
9-
6+
implementation("io.ktor:ktor-client-cio-jvm:3.2.0")
107
// New Relic Java Agent dependencies
118
implementation("com.newrelic.agent.java:newrelic-agent:9.1.0")
129
implementation("com.newrelic.agent.java:newrelic-api:9.1.0")
13-
implementation(fileTree("../test-lib"){
10+
implementation("com.newrelic.agent.java:agent-bridge:9.1.0")
11+
implementation(fileTree("../test-lib") {
1412
include("*.jar")
1513
})
1614
}
1715

1816
tasks.jar {
1917
manifest {
2018
attributes(
21-
"Implementation-Title" to "com.newrelic.instrumentation.labs.ktor-server-setup",
19+
"Implementation-Title" to "com.newrelic.instrumentation.labs.ktor-client-cio-3.2.0",
2220
"Implementation-Vendor" to "New Relic Labs",
2321
"Implementation-Vendor-Id" to "com.newrelic.labs",
24-
"Implementation-Version" to 1.0,
25-
"Agent-Class" to "com.newrelic.instrumentation.labs.ktor.server.KtorServerPremain"
26-
)
22+
"Implementation-Version" to 1.0
23+
)
2724
}
2825
}
2926

3027
verifyInstrumentation {
28+
passesOnly("io.ktor:ktor-client-cio-jvm:[3.2.0,)")
3129
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.ktor.client.engine.cio;
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 io.ktor.client.request.HttpRequestData;
7+
import io.ktor.client.request.HttpResponseData;
8+
import kotlin.coroutines.Continuation;
9+
10+
@Weave(originalName = "io.ktor.client.engine.cio.CIOEngine")
11+
public class CIOEngine_Instrumentation {
12+
13+
@Trace(dispatcher = true)
14+
public Object execute(HttpRequestData requestData, Continuation<? super HttpResponseData> continuation) {
15+
return Weaver.callOriginal();
16+
}
17+
18+
@Trace(dispatcher = true)
19+
public void close() {
20+
Weaver.callOriginal();
21+
}
22+
23+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package io.ktor.client.engine.cio;
2+
3+
import com.newrelic.api.agent.*;
4+
import com.newrelic.api.agent.weaver.NewField;
5+
import com.newrelic.api.agent.weaver.Weave;
6+
import com.newrelic.api.agent.weaver.Weaver;
7+
import com.sun.jndi.toolkit.url.UrlUtil;
8+
import io.ktor.client.request.HttpRequestData;
9+
import io.ktor.client.request.HttpResponseData;
10+
import io.ktor.client.request.UnixSocketSettings;
11+
import io.ktor.http.Url;
12+
import kotlin.Unit;
13+
import kotlin.coroutines.Continuation;
14+
import kotlin.coroutines.CoroutineContext;
15+
16+
import java.net.Proxy;
17+
import java.net.URI;
18+
19+
import kotlin.jvm.functions.Function0;
20+
21+
@Weave(originalName = "io.ktor.client.engine.cio.Endpoint")
22+
public class Endpoint_Instrumentation {
23+
24+
@NewField
25+
private Segment segment = null;
26+
27+
public Endpoint_Instrumentation(String host, int port, Proxy proxy, boolean secure, CIOEngineConfig config, ConnectionFactory connectionFactory,
28+
CoroutineContext coroutineContext, Function0<Unit> onDone, UnixSocketSettings unixSocketSettings) {
29+
30+
}
31+
32+
@Trace
33+
public Object execute(HttpRequestData request, CoroutineContext coroutineContext, Continuation<? super HttpResponseData> continuation) {
34+
if (request != null && segment == null) {
35+
Url url = request.getUrl();
36+
String urlString = null;
37+
if (url != null) {
38+
urlString = url.toString();
39+
URI uri = URI.create(url.toString());
40+
HttpParameters httpParameters = HttpParameters.library("Ktor-CIO-Client").uri(uri).procedure(request.getMethod().toString()).noInboundHeaders().build();
41+
segment = NewRelic.getAgent().getTransaction().startSegment("CIOClientRequest");
42+
segment.reportAsExternal(httpParameters);
43+
}
44+
}
45+
return Weaver.callOriginal();
46+
}
47+
48+
@Trace
49+
private Object makePipelineRequest(RequestTask requestTask, Continuation<? super Unit> continuation) {
50+
return Weaver.callOriginal();
51+
}
52+
53+
@Trace
54+
private Object makeDedicatedRequest(HttpRequestData requestData, CoroutineContext coroutineContext, Continuation<? super HttpResponseData> continuation) {
55+
return Weaver.callOriginal();
56+
}
57+
58+
@Trace(dispatcher = true)
59+
public void close() {
60+
if (segment != null) {
61+
segment.end();
62+
segment = null;
63+
}
64+
Weaver.callOriginal();
65+
}
66+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package io.ktor.client.engine.cio;
2+
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.Weave;
7+
import com.newrelic.api.agent.weaver.Weaver;
8+
import com.newrelic.instrumentation.labs.ktor.cio.NRTokenContextKt;
9+
import com.newrelic.instrumentation.labs.ktor.cio.TokenContext;
10+
import io.ktor.client.request.HttpRequestData;
11+
import io.ktor.client.request.HttpResponseData;
12+
import io.ktor.util.date.GMTDate;
13+
import io.ktor.utils.io.ByteReadChannel;
14+
import io.ktor.utils.io.ByteWriteChannel;
15+
import kotlin.Unit;
16+
import kotlin.coroutines.Continuation;
17+
import kotlin.coroutines.CoroutineContext;
18+
19+
import java.util.logging.Level;
20+
21+
@Weave(originalName = "io.ktor.client.engine.cio.UtilsKt")
22+
public class UtilsKt_Instrumentation {
23+
24+
@Trace(dispatcher = true)
25+
public static Object writeRequest(HttpRequestData requestData, ByteWriteChannel writeChannel, CoroutineContext coroutineContext, boolean overProxy, boolean closeChannel, Continuation<? super Unit> continuation) {
26+
NewRelic.getAgent().getLogger().log(Level.FINER, new Exception("call to writeRequest"),"Writing request : {0}", requestData);
27+
// TokenContext tokenContext = NRTokenContextKt.getTokenContextOrNull(coroutineContext);
28+
// if(tokenContext == null) {
29+
// Token token = NewRelic.getAgent().getTransaction().getToken();
30+
// if(token != null) {
31+
// if(token.isActive()) {
32+
// NRTokenContextKt.addTokenContext(coroutineContext, token);
33+
// } else {
34+
// token.expire();
35+
// token = null;
36+
// }
37+
// }
38+
// }
39+
return Weaver.callOriginal();
40+
}
41+
42+
@Trace(dispatcher = true)
43+
public static Object readResponse(GMTDate date, HttpRequestData requestData, ByteReadChannel readChannel, ByteWriteChannel writeChannel, CoroutineContext coroutineContext, Continuation<? super HttpResponseData> continuation) {
44+
NewRelic.getAgent().getLogger().log(Level.FINER, new Exception("call to readResponse"),"Reading response for : {0}", requestData);
45+
// TokenContext tokenContext = NRTokenContextKt.getTokenContextOrNull(coroutineContext);
46+
// if(tokenContext != null) {
47+
// Token token = tokenContext.getToken();
48+
// token.linkAndExpire();
49+
// token = null;
50+
// NRTokenContextKt.removeTokenContext(coroutineContext);
51+
// }
52+
return Weaver.callOriginal();
53+
}
54+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.newrelic.instrumentation.labs.ktor.cio
2+
3+
import kotlin.coroutines.AbstractCoroutineContextElement
4+
import kotlin.coroutines.CoroutineContext
5+
6+
import kotlin.coroutines.*
7+
import com.newrelic.api.agent.Token
8+
9+
data class TokenContext(val token: Token)
10+
11+
class TokenContextElement(val context: TokenContext) : AbstractCoroutineContextElement(Key) {
12+
companion object Key : CoroutineContext.Key<TokenContextElement>
13+
}
14+
15+
fun CoroutineContext.getTokenContext(): TokenContext? = this[TokenContextElement]?.context
16+
17+
fun CoroutineContext.getTokenContextOrNull(): TokenContext? = this[TokenContextElement]?.context
18+
19+
fun addTokenContext(context : CoroutineContext, token : Token) : CoroutineContext {
20+
val tokenContext = TokenContext(token)
21+
return context + TokenContextElement(tokenContext)
22+
}
23+
24+
fun removeTokenContext(context : CoroutineContext) : CoroutineContext {
25+
val tokenContext = context.getTokenContextOrNull();
26+
if (tokenContext != null) {
27+
val token = tokenContext.token
28+
token.expire()
29+
30+
return context.minusKey(TokenContextElement.Key)
31+
}
32+
return context
33+
}

0 commit comments

Comments
 (0)