Agent API
editAgent
API
editThe Elastic APM agent for Node.js is a singleton.
You get the agent instance by either requiring elastic-apm-node
or elastic-apm-node/start
.
For details on the two approaches,
see the Setup and Configuration guide.
The agent is also returned by the start()
function,
which allows you to require and start the agent on the same line:
const apm = require('elastic-apm-node').start(...)
If you need to access the Agent
in any part of your codebase,
you can simply require elastic-apm-node
to access the already started singleton.
You therefore don’t need to manage or pass around the started Agent
yourself.
apm.start([options])
editStarts the Elastic APM agent for Node.js and returns itself.
Put the call to this function at the very top of your main app file - before requiring any other modules.
If you are using Babel calling this function will not have the desired effect. See the Babel / ES Modules support documentation for details.
If you are using Typescript the import statement may be removed if it is not used.
It is recommended to use -r elastic-apm-node/start
when starting the app to avoid this.
See the Configuration documentation for available options.
apm.isStarted()
editAdded in: v1.5.0
Use isStarted()
to check if the agent has already started.
Returns true
if the agent has started,
otherwise returns false
.
apm.setFramework(options)
editAdded in: v2.8.0
-
options
<Object>
The following options are supported:-
name
<string>
Framework name. -
version
<string>
Framework version. -
overwrite
<boolean>
If set tofalse
, theframeworkName
andframeworkVersion
provided as config options will not be overwritten. Default:true
.
-
Set or change the frameworkName
or frameworkVersion
after the agent has started.
These config options can also be provided as part of the regular agent configuration.
apm.addFilter(callback)
editAdded in: v0.1.0
Use addFilter()
to supply a filter function.
Each filter function will be called just before data is being sent to the APM Server. This will allow you to manipulate the data being sent, for instance to remove sensitive information like passwords etc.
Each filter function will be called in the order they were added,
and will receive a payload
object as the only argument,
containing the data about to be sent to the APM Server.
The format of the payload depends on the event type being sent. For details about the different formats, see the APM Server intake API documentation.
The filter function is synchronous and should return the manipulated payload object. If a filter function doesn’t return any value or returns a falsy value, the remaining filter functions will not be called and the payload will not be sent to the APM Server.
Example usage:
apm.addFilter(function (payload) { if (payload.context.request && payload.context.request.headers) { // redact sensitive data payload.context.request.headers['x-secret'] = '[REDACTED]' } // remember to return the modified payload return payload })
A set of built-in filters are added by default.
See filterHttpHeaders
for details.
Though you can also use filter functions to add new contextual information to the user
and custom
properties,
it’s recommended that you use apm.setUserContext()
and apm.setCustomContext()
for that purpose.
apm.addErrorFilter(callback)
editAdded in: v2.0.0
Similar to apm.addFilter()
,
but the callback
will only be called with error payloads.
apm.addTransactionFilter(callback)
editAdded in: v2.0.0
Similar to apm.addFilter()
,
but the callback
will only be called with transaction payloads.
apm.addSpanFilter(callback)
editAdded in: v2.0.0
Similar to apm.addFilter()
,
but the callback
will only be called with span payloads.
apm.setUserContext(context)
editAdded in: v0.1.0
-
context
<Object>
Accepts the following optional properties:
Call this to enrich collected performance data and errors with information about the user/client. This function can be called at any point during the request/response life cycle (i.e. while a transaction is active).
The given context
will be added to the active transaction.
If no active transaction can be found,
false
is returned.
Otherwise true
.
It’s possible to call this function multiple times within the scope of the same active transaction.
For each call, the properties of the context
argument are shallow merged with the context previously given.
If an error is captured,
the context from the active transaction is used as context for the captured error,
and any custom context given as the 2nd argument to apm.captureError
takes precedence and is shallow merged on top.
The provided user context is stored under context.user
in Elasticsearch on both errors and transactions.
apm.setCustomContext(context)
editAdded in: v0.1.0
-
context
<Object>
Can contain any property that can be JSON encoded.
Call this to enrich collected errors and transactions with any information that you think will help you debug performance issues or errors. This function can be called at any point while a transaction is active (e.g. during the request/response life cycle of an incoming HTTP request).
The provided custom context is stored under context.custom
in APM Server pre-7.0,
or transaction.custom
and error.custom
in APM Server 7.0+.
The given context
will be added to the active transaction.
If no active transaction can be found,
false
is returned.
Otherwise true
.
It’s possible to call this function multiple times within the scope of the same active transaction.
For each call, the properties of the context
argument are shallow merged with the context previously given.
If an error is captured,
the context from the active transaction is used as context for the captured error,
and any custom context given as the 2nd argument to apm.captureError
takes precedence and is shallow merged on top.
Before using custom context, ensure you understand the different types of metadata that are available.
apm.setTag(name, value)
editDeprecated in 2.10.0.
Replaced by apm.setLabel(name, value)
Added in: v0.1.0
Set a tag on the current transaction. You can set multiple tags on the same transaction. If an error happens during the current transaction, it will also get tagged with the same tags.
Tags are key/value pairs that are indexed by Elasticsearch and therefore searchable (as opposed to data set via apm.setCustomContext()
).
apm.setLabel(name, value)
editAdded in: v0.1.0
Renamed from apm.setTag()
to apm.setLabel()
: v2.10.0
Set a label on the current transaction. You can set multiple labels on the same transaction. If an error happens during the current transaction, it will also get tagged with the same label.
Labels are key/value pairs that are indexed by Elasticsearch and therefore searchable
(as opposed to data set via apm.setCustomContext()
).
Before using custom labels, ensure you understand the different types of
metadata that are available.
Avoid defining too many user-specified labels. Defining too many unique fields in an index is a condition that can lead to a mapping explosion.
apm.addTags({ [name]: value })
editDeprecated in 2.10.0.
Replaced by apm.addLabels({ [name]: value })
Added in: v1.5.0
-
tags
<Object>
Contains key/value pairs:
Add several tags on the current transaction. You can add tags multiple times. If an error happens during the current transaction, it will also get tagged with the same tags.
Tags are key/value pairs that are indexed by Elasticsearch and therefore searchable (as opposed to data set via apm.setCustomContext()
).
apm.addLabels({ [name]: value })
editAdded in: v1.5.0
Renamed from apm.addTags()
to apm.addLabels()
: v2.10.0
-
labels
<Object>
Contains key/value pairs:
Add several labels on the current transaction. You can add labels multiple times. If an error happens during the current transaction, it will also get tagged with the same labels.
Labels are key/value pairs that are indexed by Elasticsearch and therefore searchable
(as opposed to data set via apm.setCustomContext()
).
Before using custom labels, ensure you understand the different types of
metadata that are available.
Avoid defining too many user-specified labels. Defining too many unique fields in an index is a condition that can lead to a mapping explosion.
apm.captureError(error[, options][, callback])
editAdded in: v0.1.0
-
error
- Can be either an<Error>
object, a message string, or a special parameterized message object -
options
<Object>
The following options are supported:-
timestamp
<number>
The time when the error happened. Must be a Unix Time Stamp representing the number of milliseconds since January 1, 1970, 00:00:00 UTC. Sub-millisecond precision can be achieved using decimals. If not provided, the current time will be used -
message
- If theerror
argument is an<Error>
object, it’s possible to use this option to supply an additional message string that will be stored along with the error message underlog.message
-
user
- See metadata section for details about this option -
custom
- See metadata section for details about this option -
request
<http.IncomingMessage>
You can associate an error with information about the incoming request to gain additional context such as the request url, headers, and cookies. However, in most cases, the agent will detect if an error was in response to an http request and automatically add the request details for you. See http requests section for more details. -
response
<http.ServerResponse>
You can associate an error with information about the http response to get additional details such as status code and headers. However, in most cases, the agent will detect if an error occured during an http request and automatically add response details for you. See http responses section for more details. -
handled
<boolean>
Adds additional context to the exception to show whether the error is handled or uncaught. Default:true
. -
labels
<Object>
Add additional context with labels, these labels will be added to the error along with the labels from the current transaction. See theapm.addLabels()
method for details about the format.
-
-
callback
- Will be called after the error has been sent to the APM Server. It will receive anError
instance if the agent failed to send the error, and the id of the captured error
Send an error to the APM Server:
apm.captureError(new Error('boom!'))
Message strings
editInstead of an Error
object,
you can log a plain text message:
apm.captureError('Something happened!')
This will also be sent as an error to the APM Server, but will not be associated with an exception.
Parameterized message object
editInstead of an Error
object or a string,
you can supply a special parameterized message object:
apm.captureError({ message: 'Could not find user %s with id %d in the database', params: ['Peter', 42] })
This makes it possible to better group error messages that contain variable data like ID’s or names.
Metadata
editTo ease debugging it’s possible to send some extra data with each error you send to the APM Server.
The APM Server intake API supports a lot of different metadata fields,
most of which are automatically managed by the Elastic APM Node.js Agent.
But if you wish you can supply some extra details using user
or custom
.
For more details on the properties accepted by the events intake API see the events intake API docs.
To supply any of these extra fields,
use the optional options argument when calling apm.captureError()
.
Here are some examples:
// Sending some extra details about the user apm.captureError(error, { user: { id: 'unique_id', username: 'foo', email: 'foo@example.com' } }) // Sending some arbitrary details using the `custom` field apm.captureError(error, { custom: { some_important_metric: 'foobar' } })
To supply per-request metadata to all errors captured in one central location,
use apm.setUserContext()
and apm.setCustomContext()
.
HTTP requests
editBesides the options described in the metadata section,
you can use the options
argument to associate the error with an HTTP request:
apm.captureError(err, { request: req // an instance of http.IncomingMessage })
This will log the URL that was requested, the HTTP headers, cookies and other useful details to help you debug the error.
In most cases, this isn’t needed, as the agent is pretty smart at figuring out if your Node.js app is an HTTP server and if an error occurred during an incoming request. In which case it will automate this processes for you.
HTTP responses
editBesides the options described in the metadata section,
you can use the options
argument to associate the error with an HTTP response:
apm.captureError(err, { response: res // an instance of http.ServerResponse })
This will log the response status code, headers and other useful details to help you debug the error.
In most cases, this isn’t needed, as the agent is pretty smart at figuring out if your Node.js app is an HTTP server and if an error occurred during an incoming request. In which case it will automate this processes for you.
apm.middleware.connect()
editAdded in: v0.1.0
Returns a middleware function used to collect and send errors to the APM Server.
const apm = require('elastic-apm-node').start() const connect = require('connect') const app = connect() // your regular middleware: app.use(...) app.use(...) // your main HTTP router app.use(function (req, res, next) { throw new Error('Broke!') }) // add Elastic APM in the bottom of the middleware stack app.use(apm.middleware.connect()) app.listen(3000)
apm.middleware.connect
must be added to the middleware stack before any other error handling middleware functions or there’s a chance that the error will never get to the agent.
apm.startTransaction([name][, type][, options])
editAdded in: v0.1.0
-
name
<string>
The name of the transaction. You can always set this later viatransaction.name
orapm.setTransactionName()
. Default:unnamed
-
type
<string>
The type of transaction. You can always set this later viatransaction.type
. Default:custom
-
options
<Object>
The following options are supported:-
startTime
<number>
The time when the transaction started. Must be a Unix Time Stamp representing the number of milliseconds since January 1, 1970, 00:00:00 UTC. Sub-millisecond precision can be achieved using decimals. If not provided, the current time will be used -
childOf
<string>
The traceparent header received from a remote service.
-
Start a new transaction.
Use this function to create a custom transaction. Note that the agent will do this for you automatically whenever your application receives an incoming HTTP request. You only need to use this function to create custom transactions.
There’s a special type
called request
which is used by the agent for the transactions automatically created when an incoming HTTP request is detected.
See the Transaction API docs for details on how to use custom transactions.
apm.endTransaction([result][, endTime])
editAdded in: v0.1.0
-
result
<string>
Describes the result of the transaction. This is typically the HTTP status code, or e.g. "success" or "failure" for a background task -
endTime
<number>
The time when the transaction ended. Must be a Unix Time Stamp representing the number of milliseconds since January 1, 1970, 00:00:00 UTC. Sub-millisecond precision can be achieved using decimals. If not provided, the current time will be used
Ends the active transaction. If no transaction is currently active, nothing happens.
Note that the agent will do this for you automatically for all regular HTTP transactions.
You only need to use this function to end custom transactions created by apm.startTransaction()
or if you wish the end a regular transaction prematurely.
Alternatively you can call end()
directly on an active transaction object.
apm.currentTransaction
editAdded in: v1.9.0
Get the currently active transaction, if used within the context of a transaction.
If there’s no active transaction available,
null
will be returned.
apm.currentSpan
editAdded in: v2.0.0
Get the currently active span, if used within the context of a span.
If there’s no active span available,
null
will be returned.
apm.currentTraceparent
editAdded in: v2.9.0
Get the serialized traceparent string of the current transaction or span.
If there’s no active transaction or span available,
null
will be returned.
apm.setTransactionName(name)
editAdded in: v0.1.0
-
name
<string>
Set or overwrite the name of the current transaction.
If you use a supported router/framework the agent will automatically set the transaction name for you.
If you do not use Express, hapi, koa-router, Restify, or Fastify or if the agent for some reason cannot detect the name of the HTTP route,
the transaction name will default to METHOD unknown route
(e.g. POST unknown route
).
Read more about naming routes manually in the Get started with a custom Node.js stack article.
apm.startSpan([name][, type][, options])
editAdded in: v1.1.0
-
name
<string>
The name of the span. You can alternatively set this viaspan.name
. Default:unnamed
-
type
<string>
The type of span. You can alternatively set this viaspan.type
. Default:custom.code
-
options
<Object>
The following options are supported:-
startTime
<number>
The time when the span started. Must be a Unix Time Stamp representing the number of milliseconds since January 1, 1970, 00:00:00 UTC. Sub-millisecond precision can be achieved using decimals. If not provided, the current time will be used
-
Start and return a new custom span associated with the current active transaction.
This is the same as getting the current transaction with apm.currentTransaction
and,
if a transaction was found,
calling transaction.startSpan(name, type, options)
on it.
When a span is started it will measure the time until span.end()
is called.
See Span API docs for details on how to use custom spans.
If there’s no active transaction available,
null
will be returned.
apm.handleUncaughtExceptions([callback])
editAdded in: v0.1.0
By default, the agent will terminate the Node.js process when an uncaught exception is detected. Use this function if you need to run any custom code before the process is terminated.
apm.handleUncaughtExceptions(function (err) { // Do your own stuff... and then exit: process.exit(1) })
The callback is called after the event has been sent to the APM Server with the following arguments:
-
err
<Error>
the captured exception
This function will also enable the uncaught exception handler if it was disabled using the captureExceptions
configuration option.
If you don’t specify a callback, the node process is terminated automatically when an uncaught exception has been captured and sent to the APM Server.
It is recommended that you don’t leave the process running after receiving an uncaught exception, so if you are using the optional callback, remember to terminate the node process.
apm.flush([callback])
editAdded in: v0.12.0
apm.flush(function (err) { // Flush complete })
Manually end the active outgoing HTTP request to the APM Server.
The HTTP request is otherwise ended automatically at regular intervals,
controlled by the apiRequestTime
and apiRequestSize
config options.
The callback is called after the active HTTP request has ended. The callback is called even if no HTTP request is currently active.
apm.lambda([type, ]handler)
editAdded in: v1.4.0
exports.hello = apm.lambda(function (payload, context, callback) { callback(null, `Hello, ${payload.name}!`) })
Manually instrument an AWS Lambda function to form a transaction around each execution. Optionally, a type may also be provided to group lambdas together. By default, "lambda" will be used as the type name.
Read more lambda support in the Lambda article.
apm.addPatch(modules, handler)
editAdded in: v2.7.0
-
modules
<string>
|<string[>]
Name of module(s) to apply the patch to, when required. -
handler
<Function>
|<string>
Must be a patch function or a path to a module exporting a patch function-
exports
<Object>
The original export object of the module -
agent
- The agent instance to use in the patch function -
options
<Object>
The following options are supported:-
version
<string>
|<Undefined>
The module version, if applicable. -
enabled
<boolean>
A flag indicating if the instrumentation is enabled. Any module patch can be disabled, by module name, withdisableInstrumentations
.
-
-
Register a module patch to apply on intercepted require
calls.
A module can have any number of patches and will be applied in the order they are added.
apm.addPatch('timers', (exports, agent, { version, enabled }) => { const setTimeout = exports.setTimeout exports.setTimeout = (fn, ms) => { const span = agent.createSpan('set-timeout') return setTimeout(() => { span.end() fn() }, ms) } return exports }) // or ... apm.addPatch(['hapi', '@hapi/hapi'], (exports, agent, { version, enabled }) => { const setTimeout = exports.setTimeout exports.setTimeout = (fn, ms) => { const span = agent.createSpan('set-timeout') return setTimeout(() => { span.end() fn() }, ms) } return exports }) // or ... apm.addPatch('timers', './timer-patch')
apm.removePatch(modules, handler)
editAdded in: v2.7.0
Removes a module patch.
This will generally only be needed when replacing an existing patch.
To disable instrumentation while keeping context propagation support, see disableInstrumentations
.
apm.removePatch('timers', './timers-patch') // or ... apm.removePatch(['timers'], './timers-patch') // or ... apm.removePatch('timers', timerPatchFunction)
apm.clearPatches(modules)
editAdded in: v2.7.0
Clear all patches for the given module.
This will generally only be needed when replacing an existing patch.
To disable instrumentation while keeping context propagation support, see disableInstrumentations
.
apm.clearPatches('timers') // or ... apm.clearPatches(['timers'])
apm.currentTraceIds
editAdded in: v2.17.0
apm.currentTraceIds
produces an object containing trace.id
and either transaction.id
or span.id
when a current transaction or span is available.
When no transaction or span is available it will return an empty object.
This enables log correlation to APM traces with structured loggers.
{ "trace.id": "abc123", "transaction.id": "abc123" } // or ... { "trace.id": "abc123", "span.id": "abc123" }
All current trace id objects,
including the empty form,
include a toString()
implementation.
This enables log correlation to APM traces with text-only loggers.
"trace.id=abc123 transaction.id=abc123" // or ... "trace.id=abc123 span.id=abc123"