I think I understand what is happening.
If I use setTag()/setCustomContext()/setUserContext() in my server.js before all my code, they all return false, probably because the transaction hasn't started I guess ?
If I set them in my routes handlers it works.
But what If I want to set them for all future transactions ? Am I misunderstanding something on the transactions behaviors ?
EDIT :
For now im using the hapi function "server.ext()" a middleware that is loaded before all my routes handlers to set contexts to the APM transaction and it works fine. I noticed that the captureBody still doesn't work.
Here is my server.js file :
const apm = require('elastic-apm-node').start({
// active: process.env.NODE_ENV === 'production'
serviceName: 'api-test',
logLevel: 'debug',
filterHttpHeaders: false,
captureBody: 'all',
serverUrl: 'http://logs.mydomain.net:8200',
});
const Hapi = require('hapi');
const Inert = require('inert');
const Vision = require('vision');
const hapiswaggerd = require('hapi-swaggered');
const hapiswaggeredui = require('hapi-swaggered-ui');
const Hapijwt = require('hapi-auth-jwt2');
const hapiI18n = require('hapi-basic-i18n');
const Path = require('path');
require('dotenv').config({ silent: true, path: Path.join(__dirname, '.env') });
const good = require('good');
const routes = require('./routes');
const jwtService = require('./jwt/jwt.service');
const server = new Hapi.Server({ debug: { request: ['error'] } });
server.connection({ port: process.env.PORT || 8080, host: '0.0.0.0', routes: { cors: true } });
server.register([
Inert,
Vision,
{
register: hapiI18n,
options: {
locale_path: Path.join(__dirname, './assets/i18n/'),
default_language: 'FR',
available_languages: ['FR'],
},
},
{
register: hapiswaggerd,
options: {
endpoint: '/swagger-doc',
},
},
{
register: Hapijwt,
},
{
register: hapiswaggeredui,
options: {
title: 'Title API',
path: '/documentation',
authorization: { // see above
field: 'Authorization',
scope: 'header',
placeholder: 'Enter your jwt token here',
},
swaggerOptions: {},
},
},
{
register: good,
options: {
ops: {
interval: 1000,
},
reporters: {
console: [{
module: 'good-squeeze',
name: 'Squeeze',
args: [{
response: '*',
error: '*',
}],
},
{
module: 'good-console',
}, 'stdout'],
},
},
},
], (err) => {
server.auth.strategy('jwt', 'jwt', {
key: jwtService.getAppSecrets,
validateFunc: (decoded, request, callback) => {
if (!decoded) {
return callback(null, false);
}
const scope = [];
if (decoded) {
if (decoded.role) {
scope.push(decoded.role);
}
if (decoded.currentOrganisation && decoded.currentOrganisation.role) {
scope.push(decoded.currentOrganisation.role);
}
}
// Scope is an array that contains AppRole and OrganisationRole
return callback(null, true, Object.assign(decoded, { scope }));
},
verifyOptions: { algorithms: ['HS256'] },
});
if (err) throw err;
routes(server, apm);
server.start((error) => {
if (error) {
throw error;
}
server.ext('onPreHandler', (request, reply) => {
apm.setCustomContext({ jwtContent: request.auth.credentials });
apm.setUserContext({
id: request.auth.credentials.id,
email: request.auth.credentials.email,
username: `${request.auth.credentials.firstname} ${request.auth.credentials.lastname}`,
});
return reply.continue();
});
});
});
module.exports = server;