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

Http4s transaction changes #1006

Merged
merged 6 commits into from
Sep 27, 2022
Merged

Http4s transaction changes #1006

merged 6 commits into from
Sep 27, 2022

Conversation

richard-gibson
Copy link
Contributor

@richard-gibson richard-gibson commented Sep 9, 2022

Before contributing, please read our contributing guidelines and code of conduct.

Overview

This PR adds support for HTTP4s ember and blaze v0.23 client and server libs. It also fixes a bug where transaction activity was not being cleared from the request thread causing incorrect transaction metrics.

Related Github Issue

Include a link to the related GitHub issue, if applicable

Testing

The agent includes a suite of tests which should be used to
verify your changes don't break existing functionality. These tests will run with
Github Actions when a pull request is made. More details on running the tests locally can be found
here,

Checks

[N] Are your contributions backwards compatible with relevant frameworks and APIs? Removal of support transaction support for cats effect parTraverse was necessary to ensure Transaction Activity could be clear from threads after work.
Cats effect async features still have transaction support.
[N] Does your code contain any breaking changes? Please describe.
[Y] Does your code introduce any new dependencies? Please describe.
New instrumentation for HTTP4 blaze and ember v0.23 libs

@richard-gibson richard-gibson force-pushed the HTTP4S-transaction-changes branch 7 times, most recently from 2bb3ca4 to 506db31 Compare September 19, 2022 22:38
@richard-gibson richard-gibson force-pushed the HTTP4S-transaction-changes branch from 506db31 to 8be4f9b Compare September 19, 2022 22:51
@richard-gibson richard-gibson changed the title Http4 s transaction changes Http4s transaction changes Sep 20, 2022
override def execute(runnable: Runnable): Unit = {
delegate.execute(new TokenAwareRunnable(runnable))
}
override def reportFailure(cause: Throwable): Unit = delegate.reportFailure(cause)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think so, we don't want to lose any custom reportFailure that could be specified by a user in the delegate Execution context

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, I was really tired at this point and missed that there is a TokenAwareRunnable in there.

Comment on lines 42 to 45
AgentBridge.getAgent.getLogger.log(Level.FINEST, s"[IOTick] Txn ${txn.hashCode()} cleared from Thread: ${Thread
.currentThread().getName}")
AgentBridge.getAgent.getLogger.log(Level.FINEST,
s"[IOTick] Txn ${txn.hashCode()} ${if(!txnCleared) "not"} cleared from Thread: ${Thread
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think only the 2nd log statement should be here. Or I am missing something.


def getTransaction(tokenAndRefCount: AgentBridge.TokenAndRefCount): Transaction =
if (tokenAndRefCount != null && tokenAndRefCount.token != null) tokenAndRefCount.token.getTransaction.asInstanceOf[Transaction]
else null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the usual alignment for an else statement like this?
it looks odd being in the same level as the function definition, while the beginning of the statement is one indentation level ahead.

@@ -0,0 +1,79 @@
package cats.effect.ec
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this class should be in the newrelic namespace

@@ -0,0 +1,15 @@
package cats.effect.ec
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class should be in the newrelic namespace.

@@ -10,12 +10,12 @@ dependencies {
implementation("org.typelevel:cats-effect_2.13:3.2.8")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file was moved. But I think it was meant to be copied.
Same with the next 3 files.

logTokenInfo(tokenAndRefCount, "setting token to thread");
AgentBridge.activeToken.set(tokenAndRefCount);
tokenAndRefCount.token.link();
public static void setThreadTokenAndRefCount(AtomicReference<AgentBridge.TokenAndRefCount> tokenAndRefCount, IOFiber<?> ioFiber) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason for this method receiving a AtomicReference while all others receive the TokenAndRefCount directly?

Comment on lines 39 to 42
if (fiberTokenEmpty && threadTokenAndRefCount != null) {
if (threadTokenAndRefCount != null) {
this.tokenAndRefCount.set(threadTokenAndRefCount)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the 2nd if statement is redundant

if (threadTokenAndRefCount != null) {
this.tokenAndRefCount.set(threadTokenAndRefCount)
}
incrementTokenRefCount(this.tokenAndRefCount.get())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the Weaver.callOriginal() running async and the decrement in done the reverse of this increment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a done method that is the last step to be called in IOFiber in both happy and failure paths. It is instrumented to decrement the token

@@ -0,0 +1,24 @@
package org.http4s.server.blaze;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change the package, to avoid confusion.

def genHttpApp[F[_] : Sync](httpApp: Kleisli[F, Request[F], Response[F]]): Kleisli[F, Request[F], Response[F]] =
Kleisli { req: Request[F] => nrRequestResponse(req, httpApp) }

def nrRequestResponse[F[_] : Sync](request: Request[F], httpAp: Kleisli[F, Request[F], Response[F]]): F[Response[F]] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parameter httpApp is missing a p

Sync[F].raiseError(throwable)
})

private def expireTokenIfNeceessary(token: Token): Unit =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra e on Necessary

response.headers.headers.find(_.name == CIString(name)).map(_.value).orNull

override def getHeaders(name: String): util.List[String] =
response.headers.headers.map(_.name.toString).asJava
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this filtering by the name?

response.headers.headers.find(_.name == CIString(name)).map(_.value).orNull

override def getHeaders(name: String): util.List[String] =
response.headers.headers.map(_.name.toString).asJava
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this filtering by name?

Comment on lines +19 to +27
seg <- Resource.eval(
construct {
val txn = AgentBridge.getAgent.getTransaction
logTokenInfo(AgentBridge.activeToken.get, s"client call for txn $txn")
val segment = txn.startSegment("HTTP4S client call")
segment.addOutboundRequestHeaders(new OutboundRequestWrapper(req))
segment
})
response <- client.run(req)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't these run async?

@@ -0,0 +1,21 @@
package org.http4s.server.blaze;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong package

settings.gradle Outdated
@@ -276,7 +286,8 @@ include 'instrumentation:scala-2.9.3'
include 'instrumentation:scala-2.12.0'
include 'instrumentation:scala-2.13.0'
include 'instrumentation:cats-effect-2'
include 'instrumentation:cats-effect-3'
include 'instrumentation:cats-effect-3.2'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably already fixed, but cats-effect-3 is missing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants