Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove akka-http-core bindAndHandle instrumentation #850

Merged
merged 1 commit into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions instrumentation/akka-http-core-0.4/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#Akka HTTP core instrumentation

##HttpExt Instrumentation
Instrumentation for Akka HTTP Core is carried out in the `akka.http.scaladsl.HttpExt` class that serves as the
main entry point for a server. 2 convenience methods from `HttpExt` that can be used to start an HTTP server have
been instrumented, they are :

- ` bindAndHandleAsync`: Convenience method which starts a new HTTP server at the given endpoint and uses handler that is a function recieving an `HttpRequest` and returning a `Future[HttpResponse]`
- ` bindAndHandleSync`: Convenience method which starts a new HTTP server at the given endpoint and uses handler that is a function recieving an `HttpRequest` and returning a `HttpResponse`


It has been decide that intrumentation is not extended for `bindAndHandle` which starts a new HTTP server using a
`akka.stream.scaladsl.Flow` instance. This is due to a clash in the Akka Http Routing DSL instrumentation.


Users wishing to start an HTTP Server from an `akka.stream.scaladsl.Flow` can use the following workarround

```scala
val flow: Flow[HttpRequest, HttpResponse, NotUsed] = ???
val asyncHandler: HttpRequest => Future[HttpResponse] = request => Source.single(request).via(flow).runWith(Sink.head)
Http().bindAndHandleAsync(asyncHandler, host, port)
```

This workarround is not needed for users using calling `bindAndHandle` using `akka.http.scaladsl.Route` from the
Akka Http Routing DSL. Instrumentation should work in the same way being called from the other conveniencs methods
to start an HTTP Server


28 changes: 28 additions & 0 deletions instrumentation/akka-http-core-0.7/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#Akka HTTP core instrumentation

##HttpExt Instrumentation
Instrumentation for Akka HTTP Core is carried out in the `akka.http.scaladsl.HttpExt` class that serves as the
main entry point for a server. 2 convenience methods from `HttpExt` that can be used to start an HTTP server have
been instrumented, they are :

- ` bindAndHandleAsync`: Convenience method which starts a new HTTP server at the given endpoint and uses handler that is a function recieving an `HttpRequest` and returning a `Future[HttpResponse]`
- ` bindAndHandleSync`: Convenience method which starts a new HTTP server at the given endpoint and uses handler that is a function recieving an `HttpRequest` and returning a `HttpResponse`


It has been decide that intrumentation is not extended for `bindAndHandle` which starts a new HTTP server using a
`akka.stream.scaladsl.Flow` instance. This is due to a clash in the Akka Http Routing DSL instrumentation.


Users wishing to start an HTTP Server from an `akka.stream.scaladsl.Flow` can use the following workarround

```scala
val flow: Flow[HttpRequest, HttpResponse, NotUsed] = ???
val asyncHandler: HttpRequest => Future[HttpResponse] = request => Source.single(request).via(flow).runWith(Sink.head)
Http().bindAndHandleAsync(asyncHandler, host, port)
```

This workarround is not needed for users using calling `bindAndHandle` using `akka.http.scaladsl.Route` from the
Akka Http Routing DSL. Instrumentation should work in the same way being called from the other conveniencs methods
to start an HTTP Server


28 changes: 28 additions & 0 deletions instrumentation/akka-http-core-1.0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#Akka HTTP core instrumentation

##HttpExt Instrumentation
Instrumentation for Akka HTTP Core is carried out in the `akka.http.scaladsl.HttpExt` class that serves as the
main entry point for a server. 2 convenience methods from `HttpExt` that can be used to start an HTTP server have
been instrumented, they are :

- ` bindAndHandleAsync`: Convenience method which starts a new HTTP server at the given endpoint and uses handler that is a function recieving an `HttpRequest` and returning a `Future[HttpResponse]`
- ` bindAndHandleSync`: Convenience method which starts a new HTTP server at the given endpoint and uses handler that is a function recieving an `HttpRequest` and returning a `HttpResponse`


It has been decide that intrumentation is not extended for `bindAndHandle` which starts a new HTTP server using a
`akka.stream.scaladsl.Flow` instance. This is due to a clash in the Akka Http Routing DSL instrumentation.


Users wishing to start an HTTP Server from an `akka.stream.scaladsl.Flow` can use the following workarround

```scala
val flow: Flow[HttpRequest, HttpResponse, NotUsed] = ???
val asyncHandler: HttpRequest => Future[HttpResponse] = request => Source.single(request).via(flow).runWith(Sink.head)
Http().bindAndHandleAsync(asyncHandler, host, port)
```

This workarround is not needed for users using calling `bindAndHandle` using `akka.http.scaladsl.Route` from the
Akka Http Routing DSL. Instrumentation should work in the same way being called from the other conveniencs methods
to start an HTTP Server


28 changes: 28 additions & 0 deletions instrumentation/akka-http-core-10.0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#Akka HTTP core instrumentation

##HttpExt Instrumentation
Instrumentation for Akka HTTP Core is carried out in the `akka.http.scaladsl.HttpExt` class that serves as the
main entry point for a server. 2 convenience methods from `HttpExt` that can be used to start an HTTP server have
been instrumented, they are :

- ` bindAndHandleAsync`: Convenience method which starts a new HTTP server at the given endpoint and uses handler that is a function recieving an `HttpRequest` and returning a `Future[HttpResponse]`
- ` bindAndHandleSync`: Convenience method which starts a new HTTP server at the given endpoint and uses handler that is a function recieving an `HttpRequest` and returning a `HttpResponse`


It has been decide that intrumentation is not extended for `bindAndHandle` which starts a new HTTP server using a
`akka.stream.scaladsl.Flow` instance. This is due to a clash in the Akka Http Routing DSL instrumentation.


Users wishing to start an HTTP Server from an `akka.stream.scaladsl.Flow` can use the following workarround

```scala
val flow: Flow[HttpRequest, HttpResponse, NotUsed] = ???
val asyncHandler: HttpRequest => Future[HttpResponse] = request => Source.single(request).via(flow).runWith(Sink.head)
Http().bindAndHandleAsync(asyncHandler, host, port)
```

This workarround is not needed for users using calling `bindAndHandle` using `akka.http.scaladsl.Route` from the
Akka Http Routing DSL. Instrumentation should work in the same way being called from the other conveniencs methods
to start an HTTP Server


2 changes: 0 additions & 2 deletions instrumentation/akka-http-core-10.0/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ dependencies {
implementation("org.scala-lang:scala-library:2.11.12")
implementation("com.typesafe.akka:akka-http-core_2.11:10.0.0")
implementation("com.typesafe.akka:akka-actor_2.11:2.3.14")
testImplementation("com.typesafe.akka:akka-http-spray-json_2.11:10.0.0")
testImplementation("com.typesafe.akka:akka-http_2.11:10.0.0")
}

verifyInstrumentation {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@
import akka.http.scaladsl.settings.ConnectionPoolSettings;
import akka.http.scaladsl.settings.ServerSettings;
import akka.stream.Materializer;
import akka.stream.scaladsl.Flow;
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Segment;
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.NewField;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import com.nr.instrumentation.akkahttpcore.AkkaHttpUtils;
Expand All @@ -27,58 +25,42 @@
@Weave(type = MatchType.ExactClass, originalName = "akka.http.scaladsl.HttpExt")
public class HttpExtInstrumentation {

@NewField
public boolean bindingInstrumented;
public Future<HttpInstrumentation.ServerBinding> bindAndHandleAsync(
Function1<HttpRequest, Future<HttpResponse>> handler,
String interfaceString, int port,
ConnectionContext connectionContext,
ServerSettings settings, int parallelism,
LoggingAdapter adapter, Materializer mat) {

public Future<HttpInstrumentation.ServerBinding> bindAndHandleAsync(
Function1<HttpRequest, Future<HttpResponse>> handler,
String interfaceString, int port,
ConnectionContext connectionContext,
ServerSettings settings, int parallelism,
LoggingAdapter adapter, Materializer mat) {
AsyncRequestHandler wrapperHandler = new AsyncRequestHandler(handler, mat.executionContext());
handler = wrapperHandler;

AsyncRequestHandler wrapperHandler = new AsyncRequestHandler(handler, mat.executionContext());
handler = wrapperHandler;
bindingInstrumented = true;
return Weaver.callOriginal();
}

public Future<HttpInstrumentation.ServerBinding> bindAndHandleSync(
Function1<HttpRequest, HttpResponse> handler,
String interfaceString, int port,
ConnectionContext connectionContext,
ServerSettings settings,
LoggingAdapter adapter, Materializer mat) {

SyncRequestHandler wrapperHandler = new SyncRequestHandler(handler);
handler = wrapperHandler;
bindingInstrumented = true;
return Weaver.callOriginal();
}

return Weaver.callOriginal();
}
public Future<HttpInstrumentation.ServerBinding> bindAndHandleSync(
Function1<HttpRequest, HttpResponse> handler,
String interfaceString, int port,
ConnectionContext connectionContext,
ServerSettings settings,
LoggingAdapter adapter, Materializer mat) {

public Future<HttpInstrumentation.ServerBinding> bindAndHandle(
Flow<HttpRequest, HttpResponse, Object> handler,
String _interface,
int port, ConnectionContext connectionContext,
ServerSettings settings, LoggingAdapter log, Materializer fm) {
SyncRequestHandler wrapperHandler = new SyncRequestHandler(handler);
handler = wrapperHandler;

if (!bindingInstrumented) {
handler = new FlowRequestHandler().instrumentFlow(handler, fm);
return Weaver.callOriginal();
}
return Weaver.callOriginal();
}

// We are weaving the singleRequestImpl method here rather than just singleRequest because the javadsl only flows through here
public Future<HttpResponse> singleRequest(HttpRequest httpRequest, HttpsConnectionContext connectionContext, ConnectionPoolSettings settings,
LoggingAdapter log, Materializer fm) {
final Segment segment = NewRelic.getAgent().getTransaction().startSegment("Akka", "singleRequest");
// We are weaving the singleRequestImpl method here rather than just singleRequest because the javadsl only flows through here
public Future<HttpResponse> singleRequest(HttpRequest httpRequest, HttpsConnectionContext connectionContext, ConnectionPoolSettings settings,
LoggingAdapter log, Materializer fm) {
final Segment segment = NewRelic.getAgent().getTransaction().startSegment("Akka", "singleRequest");

Future<HttpResponse> responseFuture = Weaver.callOriginal();
Future<HttpResponse> responseFuture = Weaver.callOriginal();

AkkaHttpUtils.finishSegmentOnComplete(httpRequest, responseFuture, segment);
AkkaHttpUtils.finishSegmentOnComplete(httpRequest, responseFuture, segment);

return responseFuture;
}
return responseFuture;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.WeaveAllConstructors;
import com.newrelic.api.agent.weaver.Weaver;
import scala.Function0;
import scala.concurrent.Future;
import scala.runtime.BoxedUnit;

import java.net.InetSocketAddress;
import java.util.logging.Level;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
import akka.http.scaladsl.model.HttpRequest;
import akka.http.scaladsl.model.HttpResponse;
import akka.stream.Materializer;
import akka.stream.scaladsl.Flow;
import com.newrelic.api.agent.weaver.NewField;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import scala.Function1;
Expand All @@ -20,30 +18,21 @@
@Weave(originalName = "akka.http.scaladsl.Http$IncomingConnection")
public class IncomingConnection {

@NewField
public boolean bindingInstrumented;
public void handleWithSyncHandler(Function1<HttpRequest, HttpResponse> func, Materializer mat) {

public void handleWithSyncHandler(Function1<HttpRequest, HttpResponse> func, Materializer mat) {
SyncRequestHandler wrapperHandler = new SyncRequestHandler(func);
bindingInstrumented = true;
SyncRequestHandler wrapperHandler = new SyncRequestHandler(func);
func = wrapperHandler;

func = wrapperHandler;
Weaver.callOriginal();
}
Weaver.callOriginal();
}

public void handleWithAsyncHandler(Function1<HttpRequest, Future<HttpResponse>> func, int parallel, Materializer mat) {
AsyncRequestHandler wrapperHandler = new AsyncRequestHandler(func, mat.executionContext());
bindingInstrumented = true;
public void handleWithAsyncHandler(Function1<HttpRequest, Future<HttpResponse>> func, int parallel, Materializer mat) {

func = wrapperHandler;
Weaver.callOriginal();
}
AsyncRequestHandler wrapperHandler = new AsyncRequestHandler(func, mat.executionContext());
func = wrapperHandler;

public Object handleWith(Flow<HttpRequest, HttpResponse, Object> handler, final Materializer fm) {
if(!bindingInstrumented) {
handler = new FlowRequestHandler().instrumentFlow(handler, fm);
Weaver.callOriginal();
}
return Weaver.callOriginal();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -139,20 +139,6 @@ class AkkaHttpCoreTest {
Assert.assertEquals("WebTransaction/AkkaHttpCore/akkaHandler", txName)
}

@Test
def asyncHandlerPlayFlowServerTest(): Unit = {
playServer.startFromFlow(port)

Http().singleRequest(HttpRequest(uri = baseUrl + "/asyncPing"))

val introspector: Introspector = InstrumentationTestRunner.getIntrospector
awaitFinishedTx(introspector, 1)
playServer.stop()
Assert.assertEquals(1, introspector.getFinishedTransactionCount())
val txName = introspector.getTransactionNames.iterator.next
Assert.assertEquals("WebTransaction/AkkaHttpCore/akkaHandler", txName)
}

@Test
def syncHandlerAkkaServerCatTest(): Unit = {
akkaServer.start(port, async = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import akka.event.Logging
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.HttpMethods._
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Source, _}
import akka.util.Timeout
Expand Down Expand Up @@ -60,19 +59,9 @@ class PlayServer() {
}, timeout.duration)
}

def startFromFlow(port: Int) = {
val routeFlow =
path("ping") {
get(onSuccess(Future("Hoops"))(complete(_)))
}

bindingFuture = Http().bindAndHandle(routeFlow, interface = "localhost", port)
Await.ready(bindingFuture, timeout.duration)
}

def stop() = {
if (bindingFuture != null) {
bindingFuture.flatMap(_.unbind()).onComplete(_ => system.terminate())
bindingFuture.flatMap(_.unbind()).onComplete(_ => system.shutdown())
}
}
}
28 changes: 28 additions & 0 deletions instrumentation/akka-http-core-10.2.0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#Akka HTTP core instrumentation

##HttpExt Instrumentation
Instrumentation for Akka HTTP Core is carried out in the `akka.http.scaladsl.HttpExt` class that serves as the
main entry point for a server. 2 convenience methods from `HttpExt` that can be used to start an HTTP server have
been instrumented, they are :

- ` bindAndHandleAsync`: Convenience method which starts a new HTTP server at the given endpoint and uses handler that is a function recieving an `HttpRequest` and returning a `Future[HttpResponse]`
- ` bindAndHandleSync`: Convenience method which starts a new HTTP server at the given endpoint and uses handler that is a function recieving an `HttpRequest` and returning a `HttpResponse`


It has been decide that intrumentation is not extended for `bindAndHandle` which starts a new HTTP server using a
`akka.stream.scaladsl.Flow` instance. This is due to a clash in the Akka Http Routing DSL instrumentation.


Users wishing to start an HTTP Server from an `akka.stream.scaladsl.Flow` can use the following workarround

```scala
val flow: Flow[HttpRequest, HttpResponse, NotUsed] = ???
val asyncHandler: HttpRequest => Future[HttpResponse] = request => Source.single(request).via(flow).runWith(Sink.head)
Http().bindAndHandleAsync(asyncHandler, host, port)
```

This workarround is not needed for users using calling `bindAndHandle` using `akka.http.scaladsl.Route` from the
Akka Http Routing DSL. Instrumentation should work in the same way being called from the other conveniencs methods
to start an HTTP Server


2 changes: 0 additions & 2 deletions instrumentation/akka-http-core-10.2.0/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ dependencies {
implementation(project(":agent-bridge"))
implementation("com.typesafe.akka:akka-http-core_2.12:10.2.1")
implementation("com.typesafe.akka:akka-stream_2.12:2.6.10")
testImplementation("com.typesafe.akka:akka-http-spray-json_2.12:10.2.1")
testImplementation("com.typesafe.akka:akka-http_2.12:10.2.1")
}

verifyInstrumentation {
Expand Down
Loading