@Kesha_Shah Thanks for the question.
I think the confusion is whether the captured body is shown on the "transaction" object/document or the "error" object/document. When an Express handler errors, e.g.:
app.post('/err1', function (req, res, next) {
next(new Error('boom'))
})
app.post('/err2', function (req, res) {
throw new Error('boom thrown')
})
then the APM instrumentation for Express will (a) capture a transaction (like it does for any incoming request) and (b) a separate "error" object. When captureBody: "errors"
is configured, then it is only on the latter that the body is captured.
Here is a small Express app that shows it working.
// capturebody.example.js
const apm = require('elastic-apm-node').start({
// serverUrl: '...',
// secretToken: '...',
serviceName: 'capturebody-example',
apiRequestTime: '2s',
metricsInterval: '0s',
captureBody: 'errors'
})
const bodyParser = require('body-parser')
const express = require('express')
const app = express()
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: false}))
app.post('/ping', function (req, res) {
console.log(`received request: ${req.method} ${req.url}, content-type:${req.headers['content-type']}`)
res.send({ping: 'pong'})
})
app.post('/err1', function (req, res, next) {
console.log(`received request: ${req.method} ${req.url}, content-type:${req.headers['content-type']}`)
next(new Error('boom sent to next'))
})
app.post('/err2', function (req, res) {
console.log(`received request: ${req.method} ${req.url}, content-type:${req.headers['content-type']}`)
throw new Error('boom thrown')
})
app.listen({ port: 3000 }, async () => {
console.log('listening at <http://127.0.0.1:3000/>')
})
When I run that and call each of the endpoints:
curl -i http://127.0.0.1:3000/ping -d '{"foo":"bar"}' -H content-type:application/json
curl -i http://127.0.0.1:3000/err1 -d '{"foo":"bar"}' -H content-type:application/json
curl -i http://127.0.0.1:3000/err2 -d '{"foo":"bart"}' -H content-type:application/json
If you click on the transaction (the HTTP 5xx POST
green bar here):
then that document does not include the body. However, if you click on "> View related error", then that takes you to the "error" object:
Unfortunately, I don't believe the Kibana APM app has a UI for showing a possibly-captured request body. Instead you have to click "View occurrence in Discover" -- which is the raw UI for viewing any documents stored in the underlying Elasticsearch. There you find the http.request.body.original
in the document:
Improving this
- I think that the config var docs could be a little bit clearer here.
- I also wonder about changing two things in the implementation: (a) If a request body is not configured to be captured, then the
http.request.body
field should not be reported rather than reported as [REDACTED]
. (b) I wonder if we could have the body capturing for a transaction notice if there is a reported error that is associated with this transaction; if so and if captureBody: 'errors'
, then we capture the body on the transaction object as well. I think that is what you would have expected, and having the body on the transaction object makes it much more accessible in the UI.
I'll open a issue for these. Done.