examples/test-api, which the repository uses to test the API path end to end.
1
Issue an ingest key
Issue a key on your project’s Setup page, as described in Issue an ingest key. Make it available to your service as an environment variable:The variable name is yours to choose. Lumenstat only sees the header value.
2
Install the packages
@opentelemetry/sdk-node 0.300.0, @opentelemetry/sdk-trace 3.0.0, @opentelemetry/exporter-trace-otlp-http 0.300.0, @opentelemetry/instrumentation-http 0.300.0 and @opentelemetry/instrumentation-express 0.72.0.3
Add the second exporter
Create
instrument.cjs. Replace the first processor’s exporter with the one you use today.- Express
- NestJS
instrument.cjs
4
Load it before your app
The file must run before Express or Nest is required, so the instrumentations can patch them.
5
Confirm data is arriving
Send a few requests to your service, wait about a minute, then reload Setup. See Confirm data is arriving below.
Why metrics and logs are set to none
WhenNodeSDK gets no metric readers or log processors in code, it reads OTEL_METRICS_EXPORTER and OTEL_LOGS_EXPORTER, and both default to otlp. The SDK would then export its own metrics every 60 seconds, and any OpenTelemetry logs, to OTEL_EXPORTER_OTLP_ENDPOINT, or to http://localhost:4318 when that is unset. Those exports carry no ingest key. Lumenstat does not need them: the collector builds request metrics from your spans.
The ??= operator keeps any value you already set. If your APM receives metrics or logs through these variables, keep your settings. They go to your APM’s endpoint, not to Lumenstat.
Set both lines before new NodeSDK(). The SDK reads the metrics variable in its constructor.
Keep the two exporters apart
The Node OTLP exporters mergeOTEL_EXPORTER_OTLP_HEADERS and OTEL_EXPORTER_OTLP_TRACES_HEADERS into every exporter they build, including ones you configure in code. In a dual-export setup:
- Do not set
OTEL_EXPORTER_OTLP_TRACES_HEADERSto the ingest key, as the Copy settings lines on Setup do. Your APM would receive your Lumenstat key. - Do not keep APM credentials in
OTEL_EXPORTER_OTLP_HEADERS. Lumenstat would receive them. Pass them in code on the APM exporter, as in the example.
Get the best routes with http.route
Lumenstat names routes from thehttp.route attribute on the server span when it is present, and normalizes the raw path only when it is not. A route template is the best name a request can have.
- Express. The Express instrumentation records the route that matched, and the HTTP instrumentation writes it to
http.routeon the server span. Withapp.get('/accounts/:account', ...), a request to/accounts/GA5Y…is counted asGET /accounts/:account. - NestJS. On Nest’s default Express platform, Nest registers each controller route on Express, so the Express instrumentation names it the same way. A handler with
@Get(':account')in@Controller('accounts')is counted as/accounts/:account. The Nest instrumentation adds controller spans for your APM. Lumenstat ignores them because they are not server spans. - Nest on Fastify, or a plain
node:httpserver. The Express instrumentation does not apply, and the server span carries only the raw path. Lumenstat then applies its normalization rules, which handle Stellar addresses, ids, hashes and tokens.
http.route you set in place. This needs @opentelemetry/api.
Confirm data is arriving
Open Setup in the dashboard. The Is data arriving? card has an API line:
The check runs when the page loads, so reload it. The SDK’s batch processor exports every 5 seconds by default and the collector flushes aggregates every 15 seconds, so allow up to a minute after the first request. Then open API to see each route with its requests, status codes and latency.
Setup still says connected, waiting for traffic
Setup still says connected, waiting for traffic
- Check that
LUMENSTAT_INGEST_KEYreaches the process. With an empty or wrong key the collector still answers with success and the writer drops the data, so nothing fails visibly. - Check that the service can reach
https://otlp.lumenstat.comon port 443. - Start the service with
OTEL_LOG_LEVEL=debugto print exporter errors. - Make sure the requests reach an instrumented HTTP server. Only server spans are counted.
My APM stopped receiving traces
My APM stopped receiving traces
spanProcessors replaces traceExporter and OTEL_TRACES_EXPORTER. Put your APM exporter in the spanProcessors array next to the Lumenstat one.Logs show connection errors to localhost:4318
Logs show connection errors to localhost:4318
The SDK is exporting metrics or logs with its defaults. Set
OTEL_METRICS_EXPORTER=none and OTEL_LOGS_EXPORTER=none before new NodeSDK(), or point those exporters at your APM.Routes show raw paths or {unknown}
Routes show raw paths or {unknown}
The server spans have no
http.route. Check that the Express instrumentation is registered and that the app loads Express through require. {unknown} means the span had no route or path attribute at all.Request counts are lower than my access logs
Request counts are lower than my access logs
A sampler such as
OTEL_TRACES_SAMPLER=traceidratio applies to both exporters, so Lumenstat sees only the sampled requests. Keep the SDK unsampled and sample in a Collector pipeline that feeds only your APM. See Send only what Lumenstat reads.