Closed boriskogan81 closed 5 years ago
When the agent boots up with logLevel: 'trace'
it will output a lot of information about which modules it's shimming. Could I get you to paste that log output here?
Sure!
Thanks. That all looks ok. I was mostly curious to see if it correctly picked up the http
module as that's required in order to be notified about incoming HTTP requests (without which the agent will not be able to automatically create transactions).
For each incoming HTTP request, the agent should log this debug output:
intercepted request event call to http.Server.prototype.emit
Do you see that?
Nope.
🤔 That's odd. This would explain why there are no active transactions, and hence why the agent can't build any spans. But I can't see how this would happen unless your application isn't using the built in HTTP server from Node.js core.
Would it be possible for you to create a small test application that issolates this problem so we can better debug it?
If I just run an express server returning Hello World as per the basic express docs, and add the apm agent, it works.
Hold on-I'm using SPDY to wrap the app to allow HTTP2 connections. Could this be it?
In your application that has this problem, would it be possible for you to do the following:
logLevel: 'trace'
That way I can see more of what happens around the time where the HTTP request is handled by the app.
That's it.
This works:
app
.listen(httpConfig.port, httpConfig.host, (error) => {
if (error) {
console.error(error);
return process.exit(1);
}
logger.info(`Security center API running on`, {host: httpConfig.host, port: httpConfig.port});
});
This fails:
spdy
.createServer(options, app)
.listen(httpConfig.port, httpConfig.host, (error) => {
if (error) {
logger.error(`Backend spdy server failed `, {error});
apm.captureError(error)
return process.exit(1);
}
logger.info(`Security center API running`, {host: httpConfig.host, port: httpConfig.port});
});
Oh, didn't see your SPDY/HTTP2 comment... never mind. That might be the issue
So how can I make this work with SPDY?
Good question. I think SPDY uses the underlying net
module and operates on the raw TCP socket. If you used the built in http2
from Node.js core, it should work, but I don't think it does with the spdy
module - which would also explain your issue.
For this to work you will have to start and stop transactions manually. For more information on how to do that, see the Custom Transactions part of our documentation.
Okay. Let's say that I have a flow like this: 1) An HTTP2 request comes through on a SPDY route. I set up a custom transaction. 2) I then send an HTTP2 request to another service from within that route. 3) The other service gets this request.
How do I get the transaction from this second request inside the route of the second service?
I have a similar question about Kafka, using Kafka Node, but that should probably be a separate issue.
If I understand your question correctly, then you're asking about distributed tracing, i.e. how to tie two or more transactions together in a trace that spans multiple services?
To do that, each outgoing HTTP request needs to have a special header with information about the ongoing trace. By default, the Node.js agent will add this header for you on all outgoing HTTP/HTTPS requests. But I think maybe we don't support that for HTTP2. I'll have to look more into this.
On the receiving end, the agent will automatically pick up this HTTP header if the request is using HTTP/HTTPS - but again, not HTTP2 if I recall correctly.
We have a PR open to make it possible for you to manually add these headers to outgoing requests, but right now there's, unfortunately, no public API for this.
To continue a trace when starting a new transaction manually, you can use the 3rd options
argument to supply the parent using the childOf
option: https://www.elastic.co/guide/en/apm/agent/nodejs/current/agent-api.html#apm-start-transaction
But bottom line is that there's no public API ready yet for you to serialize the data when making the outgoing HTTP2 request. So you either have to resort to using a private API (which might break later) or wait a little till we release a version which support this (which should be soon).
That is exactly what I'm asking.
How soon do you think the version will come out?
I hope next week - but no promises.
In the meantime, you could use this code here for inspiration on how to add the header manually yourself (this is the code that currently adds it to outgoing HTTP requests):
FYI: The API for getting the traceparent
is now public and has just landed in v2.9.0:
3 new getters have been added from which you can get the traceparent
string:
agent.currentTraceparent
span.traceparent
transaction.traceparent
Did you try out the new traceparent
api?
Yes, works great, thanks!
I am trying to set up the agent in my Node app. I am not seeing logs; when I set logLevel to trace, I see these sorts of errors:
(on a route which makes a call to an Elasticsearch instance):
(on a route which makes a call to a MySQL backend):
Expected behavior I'd like to trace transactions with the APM agent.
Environment (please complete the following information)
How are you starting the agent? (please tick one of the boxes)
[x] Calling
agent.start()
directly (e.g.require('elastic-apm-node').start(...)
)[ ] Requiring
elastic-apm-node/start
from within the source code[ ] Starting node with
-r elastic-apm-node/start
Agent config options
Click to expand
package.json
dependencies:Click to expand