diff --git a/micronaut-http-server-netty-4.5/build.gradle b/micronaut-http-server-netty-4.5/build.gradle index a7dba76..8b864bc 100644 --- a/micronaut-http-server-netty-4.5/build.gradle +++ b/micronaut-http-server-netty-4.5/build.gradle @@ -26,7 +26,7 @@ jar { } verifyInstrumentation { - passes 'io.micronaut:micronaut-http-server-netty:[4.5.0,)' + passes 'io.micronaut:micronaut-http-server-netty:[4.5.0,4.6.0)' excludeRegex '.*RC.' excludeRegex '.*M.' } diff --git a/micronaut-http-server-netty-4.6/build.gradle b/micronaut-http-server-netty-4.6/build.gradle new file mode 100644 index 0000000..93d016a --- /dev/null +++ b/micronaut-http-server-netty-4.6/build.gradle @@ -0,0 +1,32 @@ + +// Build.gradle generated for instrumentation module micronaut-http-netty-2 + +apply plugin: 'java' + +targetCompatibility=JavaVersion.VERSION_17 + +dependencies { + implementation 'io.micronaut:micronaut-http-server-netty:4.6.0' + implementation group: 'io.projectreactor', name: 'reactor-core', version: '3.5.11' + + // New Relic Java Agent dependencies + implementation 'com.newrelic.agent.java:newrelic-agent:7.4.0' + implementation 'com.newrelic.agent.java:newrelic-api:7.4.0' + implementation fileTree(include: ['*.jar'], dir: '../libs') + implementation fileTree(include: ['*.jar'], dir: '../test-lib') +} + +jar { + manifest { + attributes 'Implementation-Title': 'com.newrelic.instrumentation.labs.micronaut-http-server-netty-4.6' + attributes 'Implementation-Vendor': 'New Relic Labs' + attributes 'Implementation-Vendor-Id': 'com.newrelic.labs' + attributes 'Implementation-Version': 1.0 + } +} + +verifyInstrumentation { + passes 'io.micronaut:micronaut-http-server-netty:[4.6.0,)' + excludeRegex '.*RC.' + excludeRegex '.*M.' +} diff --git a/micronaut-http-server-netty-4.6/src/main/java/com/newrelic/instrumentation/micronaut/netty_45/NRBiConsumerWrapper.java b/micronaut-http-server-netty-4.6/src/main/java/com/newrelic/instrumentation/micronaut/netty_45/NRBiConsumerWrapper.java new file mode 100644 index 0000000..5d7ec3f --- /dev/null +++ b/micronaut-http-server-netty-4.6/src/main/java/com/newrelic/instrumentation/micronaut/netty_45/NRBiConsumerWrapper.java @@ -0,0 +1,40 @@ +package com.newrelic.instrumentation.micronaut.netty_45; + +import java.util.function.BiConsumer; + +import com.newrelic.agent.bridge.AgentBridge; +import com.newrelic.api.agent.NewRelic; +import com.newrelic.api.agent.Token; +import com.newrelic.api.agent.Trace; + +public class NRBiConsumerWrapper implements BiConsumer { + + BiConsumer delegate = null; + private Token token = null; + private static boolean isTransformed = false; + + public NRBiConsumerWrapper(BiConsumer d, Token t) { + delegate = d; + token = t; + if(!isTransformed) { + AgentBridge.instrumentation.retransformUninstrumentedClass(getClass()); + isTransformed = true; + } + } + + @Override + @Trace(async = true) + public void accept(R t, Throwable u) { + if(token != null) { + token.linkAndExpire(); + token = null; + } + if(u != null) { + NewRelic.noticeError(u); + } + if(delegate != null) { + delegate.accept(t, u); + } + } + +} diff --git a/micronaut-http-server-netty-4.6/src/main/java/com/newrelic/instrumentation/micronaut/netty_45/Utils.java b/micronaut-http-server-netty-4.6/src/main/java/com/newrelic/instrumentation/micronaut/netty_45/Utils.java new file mode 100644 index 0000000..0a74f46 --- /dev/null +++ b/micronaut-http-server-netty-4.6/src/main/java/com/newrelic/instrumentation/micronaut/netty_45/Utils.java @@ -0,0 +1,46 @@ +package com.newrelic.instrumentation.micronaut.netty_45; + +import java.util.Map; + +import io.micronaut.web.router.RouteMatch; + +public class Utils { + + public static void decorateWithRoute(RouteMatch routeMatch) { +// TracedMethod traced = NewRelic.getAgent().getTracedMethod(); +// if(routeMatch instanceof BasicObjectRouteMatch) { +// BasicObjectRouteMatch objMatch = (BasicObjectRouteMatch)routeMatch; +// Class declaringClass = objMatch.getDeclaringType(); +// traced.setMetricName("Custom","Micronaut","Netty","Route","Object", declaringClass.getSimpleName()); +// traced.addCustomAttribute("Declaring-Class", declaringClass.getName()); +// } else if(routeMatch instanceof UriRouteMatch) { +// UriRouteMatch uriRouteMatch = (UriRouteMatch)routeMatch; +// +// +// +// String uri = uriRouteMatch.getUri(); +// UriMatchTemplate matchTemplate = uriRouteMatch.getRoute().getUriMatchTemplate(); +// String pathString = matchTemplate != null ? matchTemplate.toPathString() : null; +// +// String uriTemplate = uriRouteMatch.toString(); +// String methodName = uriRouteMatch.getMethodName(); +// String name = uriRouteMatch.getName(); +// +// HashMap attributes = new HashMap(); +// addAttribute(attributes, "PathString", pathString); +// addAttribute(attributes, "Method-Name", methodName); +// addAttribute(attributes, "URI", uri); +// addAttribute(attributes, "URITemplate", uriTemplate); +// addAttribute(attributes, "Name", name); +// traced.addCustomAttributes(attributes); +// +// traced.setMetricName("Custom","Micronaut","Netty","Route","URI"); +// } + } + + public static void addAttribute(Map attributes, String key, Object value) { + if(attributes != null && key != null && !key.isEmpty() && value != null) { + attributes.put(key, value); + } + } +} diff --git a/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/reactive/execution/ReactorExecutionFlowImpl.java b/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/reactive/execution/ReactorExecutionFlowImpl.java new file mode 100644 index 0000000..16ab05b --- /dev/null +++ b/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/reactive/execution/ReactorExecutionFlowImpl.java @@ -0,0 +1,39 @@ +package io.micronaut.http.reactive.execution; + +import java.util.function.BiConsumer; + +import org.reactivestreams.Publisher; + +import com.newrelic.api.agent.Token; +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.weaver.NewField; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import com.newrelic.instrumentation.micronaut.netty_45.NRBiConsumerWrapper; + +import reactor.core.publisher.Mono; + +@Weave +abstract class ReactorExecutionFlowImpl { + + @NewField + protected Token token = null; + + ReactorExecutionFlowImpl(Publisher value) { + } + + ReactorExecutionFlowImpl(Mono value) { + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Trace(async = true) + public void onComplete(BiConsumer fn) { + if(token != null) { + token.link(); + NRBiConsumerWrapper wrapper = new NRBiConsumerWrapper(fn, token); + token = null; + fn = wrapper; + } + Weaver.callOriginal(); + } +} diff --git a/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/RoutingInBoundHandler.java b/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/RoutingInBoundHandler.java new file mode 100644 index 0000000..aeae5d1 --- /dev/null +++ b/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/RoutingInBoundHandler.java @@ -0,0 +1,18 @@ +package io.micronaut.http.server.netty; + +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +import io.micronaut.http.body.CloseableByteBody; +import io.micronaut.http.server.netty.handler.OutboundAccess; +import io.netty.channel.ChannelHandlerContext; + +@Weave +public abstract class RoutingInBoundHandler { + + @Trace(dispatcher = true) + public void accept(ChannelHandlerContext ctx, io.netty.handler.codec.http.HttpRequest request, CloseableByteBody body, OutboundAccess outboundAccess) { + Weaver.callOriginal(); + } +} diff --git a/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/handler/BlockingWriter.java b/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/handler/BlockingWriter.java new file mode 100644 index 0000000..1b7157d --- /dev/null +++ b/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/handler/BlockingWriter.java @@ -0,0 +1,8 @@ +package io.micronaut.http.server.netty.handler; + +import com.newrelic.api.agent.weaver.SkipIfPresent; + +@SkipIfPresent +class BlockingWriter { + +} diff --git a/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/handler/PipeliningServerHandler.java b/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/handler/PipeliningServerHandler.java new file mode 100644 index 0000000..e3a12bf --- /dev/null +++ b/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/handler/PipeliningServerHandler.java @@ -0,0 +1,109 @@ +package io.micronaut.http.server.netty.handler; + +import com.newrelic.api.agent.NewRelic; +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +import io.netty.channel.ChannelHandlerContext; + +@Weave +public abstract class PipeliningServerHandler { + + @Trace(dispatcher = true) + public void channelRead(ChannelHandlerContext ctx, Object msg) { + Weaver.callOriginal(); + } + + @Weave + private static class MessageInboundHandler { + + @Trace + void read(Object message) { + NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Micronaut","HTTP","Netty","InboundHander","MessageInboundHandler","read"); + Weaver.callOriginal(); + } + + } + + @Weave + private static class DecompressingInboundHandler { + + @Trace + void read(Object message) { + NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Micronaut","HTTP","Netty","InboundHander","DecompressingInboundHandler","read"); + Weaver.callOriginal(); + } + + } + + @Weave + private static class OptimisticBufferingInboundHandler { + + @Trace + void read(Object message) { + NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Micronaut","HTTP","Netty","InboundHander","OptimisticBufferingInboundHandler","read"); + Weaver.callOriginal(); + } + + } + + @Weave + private static class DroppingInboundHandler { + + @Trace + void read(Object message) { + NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Micronaut","HTTP","Netty","InboundHander","DroppingInboundHandler","read"); + Weaver.callOriginal(); + } + + } + + @Weave + private static class StreamingInboundHandler { + + @Trace + void read(Object message) { + NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Micronaut","HTTP","Netty","InboundHander","StreamingInboundHandler","read"); + Weaver.callOriginal(); + } + + } + + @Weave + private static class ContinueOutboundHandler { + + @Trace + void writeSome() { + NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Micronaut","HTTP","Netty","OutboundHander","ContinueOutboundHandler","writeSome"); + Weaver.callOriginal(); + } + } + + @Weave + private static class FullOutboundHandler { + + @Trace + void writeSome() { + NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Micronaut","HTTP","Netty","OutboundHander","FullOutboundHandler","writeSome"); + Weaver.callOriginal(); + } + } + + @Weave + private static class StreamingOutboundHandler { + + @Trace + void writeSome() { + NewRelic.getAgent().getTracedMethod().setMetricName("Custom","Micronaut","HTTP","Netty","OutboundHander","StreamingOutboundHandler","writeSome"); + Weaver.callOriginal(); + } + } + + @Weave + public static class OutboundAccessImpl { + + } + +} diff --git a/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/websocket/NettyServerWebSocketHandler.java b/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/websocket/NettyServerWebSocketHandler.java new file mode 100644 index 0000000..215dc1d --- /dev/null +++ b/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/websocket/NettyServerWebSocketHandler.java @@ -0,0 +1,16 @@ +package io.micronaut.http.server.netty.websocket; + +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +import io.netty.channel.ChannelHandlerContext; + +@Weave +public abstract class NettyServerWebSocketHandler { + + @Trace(dispatcher = true) + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { + Weaver.callOriginal(); + } +} diff --git a/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/websocket/NettyServerWebSocketUpgradeHandler.java b/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/websocket/NettyServerWebSocketUpgradeHandler.java new file mode 100644 index 0000000..ca96e46 --- /dev/null +++ b/micronaut-http-server-netty-4.6/src/main/java/io/micronaut/http/server/netty/websocket/NettyServerWebSocketUpgradeHandler.java @@ -0,0 +1,19 @@ +package io.micronaut.http.server.netty.websocket; + +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +import io.micronaut.http.body.CloseableByteBody; +import io.micronaut.http.server.netty.handler.OutboundAccess; +import io.netty.channel.ChannelHandlerContext; + +@Weave +public abstract class NettyServerWebSocketUpgradeHandler { + + @Trace(dispatcher = true) + public void accept(ChannelHandlerContext ctx, io.netty.handler.codec.http.HttpRequest request, CloseableByteBody body, OutboundAccess outboundAccess){ + Weaver.callOriginal(); + } + +} diff --git a/micronaut-http-server-netty-4.6/src/main/java/io/netty/channel/ChannelPipeline_Instrumentation.java b/micronaut-http-server-netty-4.6/src/main/java/io/netty/channel/ChannelPipeline_Instrumentation.java new file mode 100644 index 0000000..1471e89 --- /dev/null +++ b/micronaut-http-server-netty-4.6/src/main/java/io/netty/channel/ChannelPipeline_Instrumentation.java @@ -0,0 +1,14 @@ +package io.netty.channel; + +import com.newrelic.api.agent.Token; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.NewField; +import com.newrelic.api.agent.weaver.Weave; + +@Weave(type = MatchType.BaseClass, originalName = "io.netty.channel.ChannelPipeline") +public class ChannelPipeline_Instrumentation { + + @NewField + public Token micronautToken; + +} diff --git a/settings.gradle b/settings.gradle index 7433be0..a9235c3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,6 +5,7 @@ include 'micronaut-http-server-netty-4' include 'micronaut-http-server-netty-4.3' include 'micronaut-http-server-netty-4.4' include 'micronaut-http-server-netty-4.5' +include 'micronaut-http-server-netty-4.6' include 'micronaut-http' include 'micronaut-http-server' include 'micronaut-router'