Skip to content

APM for Node, Bun and Deno

@falak/apm-node is a thin preset over the official OpenTelemetry JS SDK. It exports traces, logs and metrics as OTLP/HTTP JSON to the local agent (http://127.0.0.1:4318) and normalizes spans to Falak’s event types (request, outgoing_request, query, cache) so they show up in Insights.

Terminal window
npm i @falak/apm-node # or: bun add @falak/apm-node / pnpm add @falak/apm-node

Load it before your app so auto-instrumentation can patch modules:

package.json
{ "scripts": { "start": "node --import @falak/apm-node/register dist/server.js" } }

Or put import '@falak/apm-node/register'; on the first line of your entry file (covers CommonJS and built-ins; use --import when you load pg/express through ESM).

Auto-instrumented: http/https (incoming and outgoing), undici/global fetch, pg, mysql2, ioredis, express, fastify.

import { recordException } from '@falak/apm-node';
try { await charge(); } catch (e) { recordException(e); } // handled=true
recordException(err, { handled: false }); // span → ERROR

Uncaught exceptions and unhandled rejections are captured as handled=false; the process still crashes as it would by default. Opt out with captureProcessErrors: false.

Pass options to start({ … }) or use environment variables:

Option Env Default
enabled FALAK_APM_ENABLED true
endpoint FALAK_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_ENDPOINT http://127.0.0.1:4318
serviceName FALAK_SERVICE_NAME, OTEL_SERVICE_NAME npm_package_name (the agent overrides it with the site slug)
sampleRate FALAK_SAMPLE_RATE 1 (root, parent-based)
autoInstrument FALAK_APM_AUTO_INSTRUMENT true (Node only)
logs FALAK_APM_LOGS true
metrics FALAK_APM_METRICS true (Node only, 60 s interval)
redactKeys password, token, secret, authorization, cookie, api_key
redactQueryLiterals true
redact(attributes, eventType) none
captureRequestHeaders ['user-agent']
captureProcessErrors true

Resource attributes come from FALAK_SITE_ID, FALAK_SERVER_ID, FALAK_DEPLOYMENT_ID, FALAK_RELEASE_ID, FALAK_ORG_ID and FALAK_ENVIRONMENT (falling back to NODE_ENV).

Before export:

  • attribute keys containing a denylisted word (including captured headers) become [redacted];
  • denylisted query parameters in URLs and passwords in URL userinfo are redacted;
  • quoted SQL literals become ?;
  • cache keys containing a denylisted word are redacted;
  • your redact callback runs last (a throwing callback is ignored).
import { start, shutdown } from '@falak/apm-node';
start({ serviceName: 'shop', sampleRate: 0.5 });
process.on('SIGTERM', () => shutdown().finally(() => process.exit(0)));