elastic / elastic/apm-agent-nodejs

Can not capture transaction name on multi-middleware

Open
#3,630 2 comments 0 reactions 0 assignees View on GitHub
agent-nodejs awaiting reply community
Dominant language
JavaScript
Stars
594
Forks
244
Avg merge
1d 8h
Merged PRs (30d)
16

Description

I will directly simplify this problem with sample code.

Once I delved into the code a bit I simplified it to this level.

I also reviewed instrumentation here. It looks inside the request object in the Express Route, but if there is a route in the form of Express.Use (which may not be the best practice, but Express performs all route operations related to it without any problems.) Then, if a response is returned in any of the middleware except the last one, APM cannot capture the transaction name there. It appears as an unnamed transaction - unknown route.

As you can see kibana logs here:

![image](https://github.com/elastic/apm-agent-nodejs/assets/41375111/ed9876a5-62c9-47b1-98fe-950209af8f9e)

And the source code which you can reproduce.
I may contribute it

app.js
```app.js
const express = require('express');
const logger = require('morgan');
require('elastic-apm-node').start({
active: true,
breakdownMetrics: true,
captureBody: 'all',
captureErrorLogStackTraces: 'always',
captureExceptions: true,
captureSpanStackTraces: true,
cloudProvider: 'aws',
environment: 'test',
errorOnAbortedRequests: true,
frameworkName: 'Express',
ignoreUrls: ['/', '/swagger-json', '/metrics'],
instrument: true,
instrumentIncomingHTTPRequests: true,
logLevel: 'debug',
logUncaughtExceptions: true,
serverUrl: 'http://localhost:8200',
serviceName: 'elastic-apm-test',
serviceVersion: '0.0.1',
sourceLinesErrorAppFrames: 30,
sourceLinesErrorLibraryFrames: 0,
sourceLinesSpanAppFrames: 30,
sourceLinesSpanLibraryFrames: 0,
stackTraceLimit: 50,
});

const app = express();

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({extended: false}));

async function resSend(req, res, next) {
console.log({
path: req.path,
baseUrl: req.baseUrl,
originalUrl: req.originalUrl,
})
res.json({
msg: 'ok',
});
}

app.use(
'/one/two',
resSend,
)

module.exports = app;
```

www
```js
#!/usr/bin/env node

var app = require('./app');
var debug = require('debug')('express-elastic-bug-poc:server');
var http = require('http');

var port = normalizePort(process.env.PORT || '4000');
app.set('port', port);

var server = http.createServer(app);

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
return val;
}

if (port >= 0) {
return port;
}
return false;
}

function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}

var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;

// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}

/**
* Event listener for HTTP server "listening" event.
*/

function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
console.log('Listening on', bind)
}
```

package.json
```package.json
{
"name": "express-elastic-bug-poc",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node www"
},
"dependencies": {
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"elastic-apm-node": "^4.0.0",
"express": "~4.18.1",
"morgan": "~1.9.1"
}
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.