newrelic / node-newrelic

New Relic Node.js agent code base. Developers are welcome to create pull requests here, please see our contributing guidelines. For New Relic technical support, please go to http://support.newrelic.com.
Apache License 2.0
968 stars 397 forks source link

Add function transactionHandler.pause() and transactionHandler.resume() #723

Open drobnikj opened 3 years ago

drobnikj commented 3 years ago

Is your feature request related to a problem? Please describe.

In Apify we are using the new relic node js agent to monitor API servers. We have endpoints, where customers can use parameter which wait until their job starts by passing waitForFinish=secs, example. We want to exclude this waiting time from transaction timing as it just waiting till job finish.

Feature Description

I'm trying to find a way how to exclude this waiting time from transaction stats. It would be great to have the ability to do that using transactionHandler.pause() and transactionHandler.resume() function or any other way around.

Describe Alternatives

I could not find any alternatives, if you have any let me know 🙏 .

Priority

Really Want

michaelgoin commented 3 years ago

Hi @drobnikj,

Thank you for the feature request.

I'd like double-check I understand the particular scenario / problem.

It sounds like you have an API endpoint that if waitForFinish=<seconds> is supplied, that endpoint will not return a response until the job has finished or <seconds> has passed for timeout. You'd like to exclude this time from the transaction's response time, as this time is not relevant to the performance of that API endpoint. Is that correct?

I think your recommendation for handling via API seems reasonable, although has the chance for some confusion by potential users.

Currently, to pull this off... I think you'd have to ignore the initial transaction and then start a new web transaction, which requires some plumbing. You could also instrument the wait time and use that segment as an indicator you are not concerned about how much time that took, but obviously that won't prevent the transactions from standing out.

Does make me wonder if any agents have had to solve for a similar scenario already. Something for us to look into.

drobnikj commented 3 years ago

Thanks for your response.

It sounds like you have an API endpoint that if waitForFinish=<seconds> is supplied, that endpoint will not return a response until the job has finished or <seconds> has passed for timeout. You'd like to exclude this time from the transaction's response time, as this time is not relevant to the performance of that API endpoint. Is that correct?

Yes, that is correct.

I think you'd have to ignore the initial transaction and then start a new web transaction, which requires some plumbing.

It sounds like a good workaround. I'm using express and transactions are instrumentation itself by the NR agent. Do you have any code example of how I can simply create a new transaction behave as previously ignored transaction in the context of express handler?

michaelgoin commented 3 years ago

[EDIT]: The APIs below do not work because the ignored transaction continues to get propagated and is reused instead of actually creating a new transaction.

This is probably going to depend somewhat on where all of this is taking place but here's some pieces to work with...

const newrelic = require('newrelic')

// ...

// ignores the current transaction. 
const transactionHandle = newrelic.getTransaction()
transactionHandle.ignore()

// ...

// Create new web transaction
newrelic.startWebTransaction('the/url/', () => {
  // grab this immediately to keep transaction open
  const newTransaction = newrelic.getTransaction()

  // ...

  // pass the new transaction handle to where you end your request
  newTransaction.end()
})

Depending on where these pieces are injected, the regular express instrumentation may or may not kick in to do the various naming and auto-middleware capture. If it does not, then unfortunately you'll need to manually instrument middleware and name the transaction via setTransactionName (or turn off enforce backstop and set the initial name based off of express details).

Our API docs may prove helpful:

Not going to be super straightforward, unfortunately.

michaelgoin commented 3 years ago

@drobnikj just tried this out to try to put together a better express specific example... and turns out this isn't going to work.

Unfortunately, the ignored transaction will continue to be used so everything will be ignored.

While I probably could help you use the instrumentation API to hack some things together, I don't think any approach is going to give you a full 1:1 coverage of what was there before. We just don't have a good story for this use case.

drobnikj commented 3 years ago

No problem, looking forward to some feature, which will cover this case.

kmudduluru commented 2 months ago

triaged

workato-integration[bot] commented 2 months ago

https://new-relic.atlassian.net/browse/NR-292123