No APM event when sending from a node child process

Kibana version: Latest

Elasticsearch version: Latest

APM Server version: Latest

APM Agent language and version: Node latest

Original install method (e.g. download page, yum, deb, from source, etc.) and version: pnpm

Fresh install or upgraded from other version? upgraded

Is there anything special in your setup? No

Description of the problem including expected versus actual behavior. Please include screenshots (if relevant):

I hope this code is clear enough. Basically my issue is that I got nothing when using apm client in a node child process. I must be missing something but no idea what at this point.

This is the code I init with a simple node cmd:

const { elasticApm } = require('@outmind/apm');
const cp = require('child_process');

const apmconf = {
  environment: 'staging',
  secretToken: 'xxx
  serverUrl: 'https://xxx:443',
  serviceName: 'deepsyncengine',
  serviceVersion: '1.0.0',
  active: true,
  logLevel: 'trace',
};

elasticApm.start(apmconf);

const getHours = () => {
  const a = new Date();
  return `${a.getHours()}:${a.getMinutes()}:${a.getSeconds()}`;
};

console.log('elasticApm is started => ', elasticApm.isStarted());

const service = async () => {
  const h = getHours();
  console.log('service is started', h);
  const transaction = elasticApm.startTransaction(`TEST-${h} Transaction started in my test`);
  console.log('elasticApm current transaction ==>', elasticApm.currentTraceparent);

  const span = elasticApm.startSpan('THIS IS A SPAN START');
  await new Promise((res, rej) => setTimeout(() => res(), 1500));
  span.end();

  const childProcess = cp.fork('./src/file-parser/pamworker.js', {});

  childProcess.send({
    parentTransaction: elasticApm.currentTraceparent,
    // apmClient: elasticApm,
  });

  childProcess.on('error', (e) => {
    console.log('error in childprocess ==>', e);
  });

  childProcess.on('exit', (code, signal) => {
    console.log('childprocess exit ==>', code, signal);

    transaction.end('success');
    console.log('transaction is ended', transaction.ended);

    console.log('service is endend');
  });
};

service();

This is the code of the worker in child process :

const { elasticApm, makeApmConfig } = require('@outmind/apm');
const apmconf = {
  environment: 'staging',
  secretToken: 'xxx',
  serverUrl: 'https://xxx:443',
  serviceName: 'deepsyncengine',
  serviceVersion: '1.0.0',
  active: true,
  logLevel: 'trace',
};

const getHours = () => {
  const a = new Date();
  return `${a.getHours()}:${a.getMinutes()}:${a.getSeconds()}`;
};

process.on('message', async (data) => {
  elasticApm.start(apmconf);

  const d = getHours();
  console.log('message in worker data ==>', data, d);
  console.log('apm started in worker ==>', elasticApm.isStarted());

  const orphanTrans = elasticApm.startTransaction(`Worker orphanTrans ${d}`);

  // console.log('have a look at span worker ==>', orphanTrans);
  await new Promise((res, rej) => setTimeout(() => res(), 2000));
  orphanTrans.end('success');
  console.log('orphan trans ended');

  const transaction = elasticApm.startTransaction('Worker transaction', {
    childOf: data.parentTransaction,
  });

  console.log('have a look at transaction worker ==>', transaction.ended);
  await new Promise((res, rej) => setTimeout(() => res(), 2000));
  transaction.end('success');

  console.log('transaction worker ended', transaction.ended);

  process.exit(0);
});

Just dummy code but it proves what I want to do.

I got all the log.
I can see my transaction in the first file, including the span I attach to it.

I can NOT see any event sent from the worker. Neither the orphan transaction nor the childOf.
No error. The strack trace looks fine to me (very long but I can attach it to this post).

I'd appreciate any help on this !

Thanks all.

P.S: I did read this: APM not collecting data for NodeJS applications which trigger services inside child processes. But correctly monitor in NodeJS express apps

This is what I got.

Transaction from main process OK.
Span from main process ok.
Delay from child process computing does show. Nothing in it.

I can not find it as an independent transaction either.

Hey there @pierre-aurele-martin -- thanks for giving the agent a try. We're going to try to reproduce the behavior you're seeing but have two quick questions first

  1. Is there anything we should know about that's going on in the @outmind/apm package that's not standard in the agent

  2. Is there a process.exit in your actual code or is that just there for the repro.

Re: #2 -- with the information provided so far my guess is that you're exiting the child process before its agent instance has a chance to send data off to elastic.

Hi @alanstorm

Thanks for having a look.

@outmind/apm is just:

// make-apm-config is just to wrap some default config - nothing interesting
export * from './make-apm-config';
export { default as elasticApm } from 'elastic-apm-node';

There is a process.exit in my actual code. you make an interesting point, I'll timeout the process.exit for a few seconds and see if that's better :slight_smile:

nod -- also, better than the timeout, the agent API has a flush method

You can tell the agent to send all its data and then call the callback you pass to flush. Naively, that seems like a good place to kill the child process.

That's the solution ! Thanks a lot for your help.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.