@webtypen/webframez-telemetry
v0.0.3
Published
Optional telemetry addon for @webtypen/webframez-core with route, job and command instrumentation
Readme
@webtypen/webframez-telemetry
Optional telemetry addon for @webtypen/webframez-core.
It tracks and groups runtime data by:
- routes
- queue jobs
- console commands
- runtime/process metrics (CPU + memory)
The package is OpenTelemetry-compatible:
- spans are created via
@opentelemetry/api - metrics are recorded via OpenTelemetry meters
- semantic attributes like
service.name,http.request.method,url.templateandwebframez.*are attached - you can plug in any OpenTelemetry SDK/exporter (OTLP, Prometheus bridge, SigNoz, Grafana, Datadog, ...)
Install
npm i @webtypen/webframez-telemetryFor export to OTel backends you also need an OpenTelemetry SDK setup (application-side):
npm i @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-trace-otlp-httpOpenTelemetry Export Setup
@webtypen/webframez-telemetry itself does not ship a collector/exporter.
You connect your app to any backend by configuring NodeSDK + OTLP exporter.
Create a bootstrap file (load it before app startup):
// telemetry-otel.ts
import { NodeSDK } from "@opentelemetry/sdk-node";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
const exporter = new OTLPTraceExporter({
// Example: http://localhost:4318/v1/traces
// Prefer env vars in production.
});
export const otelSdk = new NodeSDK({
traceExporter: exporter,
instrumentations: [getNodeAutoInstrumentations()],
});
export async function startOtel() {
await otelSdk.start();
}
export async function stopOtel() {
await otelSdk.shutdown();
}Typical env vars:
OTEL_SERVICE_NAME=my-webframez-app
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces
# optional:
# OTEL_EXPORTER_OTLP_HEADERS=key=value,key2=value2Quick Start
Hook-based telemetry is the preferred integration for webframez-core versions that export WebframezHooks.
import { initWebframezTelemetry } from "@webtypen/webframez-telemetry";
import { Route, WebApplication } from "@webtypen/webframez-core";
const telemetry = initWebframezTelemetry({
serviceName: "my-webframez-app",
traces: true,
metrics: true,
runtime: { enabled: true }
});
Route.get("/health", async () => {
return { ok: true };
});
new WebApplication().boot({
routesFunction: () => {},
});initWebframezTelemetry() subscribes to core lifecycle hooks and emits OpenTelemetry spans and metrics. The package does not initialize an SDK or exporter for you; configure the OpenTelemetry SDK in your application bootstrap.
Metrics
The hook subscriber records:
http.server.request.durationhistogram in secondshttp.server.active_requestsup/down counterwebframez.command.durationhistogram in secondswebframez.queue.job.durationhistogram in secondswebframez.route.handler.durationhistogram in secondswebframez.operation.errorscounter
Runtime metrics are exposed as observable gauges:
process.cpu.percentprocess.memory.rssprocess.memory.heap_usedsystem.memory.used_percent
Legacy wrappers
The older wrapper APIs are still exported for compatibility:
initWebframezTelemetryRouteinstrumentConsoleCommandClassinstrumentQueueJobClasswrapRouteHandlerwrapCommandHandlerwrapJobHandler
Prefer the hook-based API for new integrations.
Instrument Commands
import { instrumentConsoleCommandClass } from "@webtypen/webframez-telemetry";
import { MyCommand } from "./commands/MyCommand";
const TelemetryMyCommand = instrumentConsoleCommandClass(MyCommand, telemetry);Instrument Queue Jobs
import { instrumentQueueJobClass } from "@webtypen/webframez-telemetry";
import { SendMailJob } from "./jobs/SendMailJob";
const TelemetrySendMailJob = instrumentQueueJobClass(SendMailJob, telemetry);Read Metrics Snapshot
const snapshot = telemetry.snapshot();
console.log(snapshot.routes);
console.log(snapshot.jobs);
console.log(snapshot.commands);Snapshot fields include:
callserrorserror_rateactivemax_activeavg_duration_msmin_duration_msmax_duration_ms
Runtime snapshot fields include:
runtime.last_sample.cpu.process_percentruntime.last_sample.memory.process_rss_bytesruntime.last_sample.memory.process_heap_used_bytesruntime.last_sample.memory.system_used_percentruntime.cpu.process_percent_avgruntime.memory.process_heap_used_avg_bytes
Runtime Sampling Configuration
Defaults are tuned for low overhead:
enabled: truesampleIntervalMs: 5000historyLimit: 120(about 10 minutes at 5s interval)emitToTracer: false
You can reconfigure at runtime:
telemetry.configureRuntimeSampling({
sampleIntervalMs: 2000,
historyLimit: 300
});
const runtimeNow = telemetry.sampleRuntimeNow();
console.log(runtimeNow.last_sample);Backend Examples
The package does not need backend-specific changes for these systems.
Use the same NodeSDK pattern and switch exporter config per target.
SigNoz
- Recommended: OTLP to SigNoz Collector
- Traces endpoint (default self-host):
http://<signoz-host>:4318/v1/traces - Usually no custom headers needed in trusted network.
// telemetry-otel.ts (SigNoz)
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
const exporter = new OTLPTraceExporter({
url: "http://<signoz-host>:4318/v1/traces",
});
export const otelSdk = new NodeSDK({ traceExporter: exporter });Grafana Tempo
- Send OTLP directly to Tempo (if OTLP receiver is enabled) or via Grafana Alloy/Otel Collector.
- Typical endpoint:
http://<tempo-or-collector-host>:4318/v1/traces
// telemetry-otel.ts (Grafana Tempo)
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
const exporter = new OTLPTraceExporter({
url: "http://<tempo-or-collector-host>:4318/v1/traces",
});
export const otelSdk = new NodeSDK({ traceExporter: exporter });Jaeger
- Modern Jaeger supports OTLP ingest.
- Typical endpoint:
http://<jaeger-host>:4318/v1/traces - Alternative: route via OpenTelemetry Collector and forward to Jaeger.
// telemetry-otel.ts (Jaeger OTLP)
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
const exporter = new OTLPTraceExporter({
url: "http://<jaeger-host>:4318/v1/traces",
});
export const otelSdk = new NodeSDK({ traceExporter: exporter });Zipkin (via Collector)
- Recommended path: app -> OpenTelemetry Collector (OTLP) -> Zipkin exporter.
- App endpoint:
http://<otel-collector-host>:4318/v1/traces - Zipkin is configured inside the collector, not in this package.
// telemetry-otel.ts (Zipkin via OTel Collector)
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
const exporter = new OTLPTraceExporter({
url: "http://<otel-collector-host>:4318/v1/traces",
});
export const otelSdk = new NodeSDK({ traceExporter: exporter });Datadog
- Recommended path: app -> Datadog Agent OTLP ingest.
- Typical endpoint:
http://<datadog-agent-host>:4318/v1/traces - If your Datadog setup requires API key headers for direct ingest, provide them with
OTEL_EXPORTER_OTLP_HEADERS.
// telemetry-otel.ts (Datadog via Agent OTLP)
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
const exporter = new OTLPTraceExporter({
url: "http://<datadog-agent-host>:4318/v1/traces",
// headers: { "DD-API-KEY": "<api-key>" }, // only if required by your setup
});
export const otelSdk = new NodeSDK({ traceExporter: exporter });New Relic
- Use OTLP endpoint with API key header.
- Typical endpoint:
https://otlp.nr-data.net:4318/v1/traces - Typical header:
api-key=<NEW_RELIC_LICENSE_KEY>viaOTEL_EXPORTER_OTLP_HEADERS.
// telemetry-otel.ts (New Relic)
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
const exporter = new OTLPTraceExporter({
url: "https://otlp.nr-data.net:4318/v1/traces",
headers: {
"api-key": process.env.NEW_RELIC_LICENSE_KEY || "",
},
});
export const otelSdk = new NodeSDK({ traceExporter: exporter });Elastic APM
- Use OTLP ingest on APM Server.
- Typical endpoint:
http://<elastic-apm-host>:8200/v1/traces - If required, set auth header via
OTEL_EXPORTER_OTLP_HEADERS(for exampleAuthorization=Bearer <token>).
// telemetry-otel.ts (Elastic APM OTLP)
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
const exporter = new OTLPTraceExporter({
url: "http://<elastic-apm-host>:8200/v1/traces",
headers: process.env.ELASTIC_APM_TOKEN
? { Authorization: `Bearer ${process.env.ELASTIC_APM_TOKEN}` }
: {},
});
export const otelSdk = new NodeSDK({ traceExporter: exporter });Other OTel-compatible backends
- If it accepts OTLP traces, set:
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT- optional
OTEL_EXPORTER_OTLP_HEADERS
- No package code changes are required.
Notes
- Route auto-instrumentation wraps function-based route handlers.
- String-controller routes (
"MyController@method") are not auto-wrapped; use wrapper helpers where needed. - This package only emits telemetry; export/ingest is handled by your OpenTelemetry SDK setup.
