By default, the Node.js agent will watch for uncaught exceptions and send them to Elastic APM automatically. But in most cases, errors are not thrown but returned via a callback, caught by a promise, or simply manually created. Those errors will not automatically be sent to Elastic APM. To manually send an error to Elastic APM, simply call apm.captureError() with the error:
var err = new Error('Ups, something broke!')
apm.captureError(err)
I am wonder if I have to npm install the 'elastic-apm-node' and import it into my code so as to manually send an error to Elastic APM, like apm.captureError(err)
I found out this would show an undefined agent somhow if I dont use agent start method twice.
Below is my lambda function entry point, I've already stated : NODE_OPTIONS -r elastic-apm-node/start in my tamplate.yml, and I called the apm.isStated method, but it return undefined
import apm from 'elastic-apm-node'
import { Handler, SNSEvent } from "aws-lambda";
import Model from './Model';
import timer from './lib/timer';
import { run as runBackgroundTask } from './BackgroundTask';
export const handler: Handler<SNSEvent, string | void> = async (event) => {
console.log(apm.isStarted(), 'check start or not ') // here prints undefined
timer.reset();
console.log('enter bg lambda function');
const result = await Promise.all(event.Records
.map(record => JSON.parse(record.Sns.Message) as Model.BackgroundTask)
.map(runBackgroundTask));
console.log('All task done', result);
return "Success";
};
@JasonREC Hrm. That undefined result means that your import apm from 'elastic-apm-node' is creating a different APM Agent class instance from the one created by NODE_OPTIONS=.... They are meant to be the same singleton.
This is TypeScript code. Are you able to post the built JavaScript code that you are deploying? Perhaps it is emitting ESM code (using import ...) rather than CommonJS code (using require). If so, then you are liking hitting the APM agent's limitations with ES modules. See Supported technologies | APM Node.js Agent Reference [3.x] | Elastic for some details.
I see your point. Currently, I am using template.yml MetaData property to do the build
And, I just add one more line in template.yml to specify that I want it to help me compile Typescript to Javascript in Common JS. I think this may satisify that the elastic document points out
The Elastic APM Node.js agent does not yet support automatically instrumenting ECMAScript module imports (ESM) , i.e. modules that are loaded via import ... statements. It currently only instruments CommonJS module imports, i.e. modules loaded via require(...) .
Metadata: # Manage esbuild properties
BuildMethod: esbuild
BuildProperties:
Format: cjs <------ I add this line
Minify: true
Target: "es2020"
Sourcemap: true
EntryPoints:
- lambdaBackground.ts
But when I looked at the cloudwatch log, it still said apm agent is undfined when the request enter the lambda function.
And, if I run apm.captureError(new Error('test')), it will say agent has not started
A couple things you could try now as workarounds are points 2 and 3 on that issue:
Another workaround might be to specify that the elastic-apm-node module be in the esbuild externals -- as documented at Starting the agent | APM Node.js Agent Reference [4.x] | Elastic. Can this config be passed through via the SAM configuration? If so, we should document this example.
Another possible workaround might be to not have elastic-apm-node listed in dependencies, but still import it via CommonJS require. That might result in getting the elastic-apm-node module provided by the Elastic Lambda layer. This may require configuring a linter and/or esbuild to ignore the attempt to import a module that is not listed in "dependencies".
Hi, @trentm
Thanks for helping me.
I looked at the document you mentioned, it is very helpful to know so as to use elastic apm node with ESbuild, I have to mark the modules as external.
And, yes, I just noticed that in the AWS document (The intro of Building Node.js Lambda functions with esbuild that I mentioned earlier), it does have a field called External, which the usage is
Specifies the list of packages to omit from the build.
I think I would love to give it a try and see if this can fix the problem. I will let you how it goes as soon as I try it.
Apache, Apache Lucene, Apache Hadoop, Hadoop, HDFS and the yellow elephant
logo are trademarks of the
Apache Software Foundation
in the United States and/or other countries.