@logcaffe/node
v0.4.0
Published
Datadog replacement Node.js SDK for SME/MSME teams. Self-hosted logs, traces, metrics, and error tracking with full data ownership.
Maintainers
Readme
@logcaffe/node
Self-hosted Datadog/Sentry replacement Node.js SDK. Logs, distributed traces, metrics, errors, profiling, and full-stack instrumentation with data ownership.
npm install @logcaffe/nodeQuick start
import { LogCaffe } from '@logcaffe/node';
LogCaffe.init({
serverUrl: 'https://collector.your-logcaffe-host',
apiKey: 'lc_<tenant>_<your-api-key>',
service: 'my-api',
environment: 'production',
enableTracing: true,
captureConsole: true,
captureUnhandledErrors: true,
captureSystemMetrics: true,
captureProcessMetrics: true,
});
// Express?
import express from 'express';
const app = express();
app.use(LogCaffe.expressMiddleware());
// … your routes …
app.use(LogCaffe.errorMiddleware());That's it. Out of the box you now get:
- Every HTTP request as an
ApiCallrow with method, path, status, latency. - Every HTTP request also as a
http.server.durationhistogram metric tagged withservice,http.method,http.route,http.status_code,http.status_class— the dashboard's Web service and API gateway templates render p50/p95/p99 latency from this with no extra code. - Every Postgres query as a
db.client.operation.durationhistogram (auto-instrumented when youimport 'pg'). - Every Redis command as a
cache.client.operation.durationhistogram. - Every RabbitMQ publish/consume as a
messaging.client.operation.durationhistogram (settraceAutoInstrument.amqp: true). - Distributed
traceparentpropagated acrosshttp,fetch,pg,redis, and (opt-in)amqplib. - System + process metrics: CPU, memory, event loop lag, GC pauses, heap, active handles.
- Console interception (
captureConsole: true) so existingconsole.errorcalls become structured logs. - Unhandled exceptions and promise rejections.
What's new in 0.4.0
Auto-emitted OTLP-style histograms
Every instrument now emits an OTLP-shaped duration histogram alongside the trace span. No app code changes — just init() and the dashboard's templates light up.
| Metric name | Source | Tags |
|---|---|---|
| http.server.duration | expressMiddleware() | service, http.method, http.route, http.status_code, http.status_class |
| db.client.operation.duration | pg patch (auto, requires pg) | service, db.system=postgresql, db.operation, error |
| cache.client.operation.duration | redis patch (auto, requires ioredis) | service, db.system=redis, db.operation, error |
| messaging.client.operation.duration | amqp patch (opt-in via traceAutoInstrument.amqp: true) | service, messaging.system=rabbitmq, messaging.operation (publish/consume), messaging.destination, error |
New public APIs
// Free-form histogram / gauge / counter sample.
LogCaffe.metric(
'queue.depth', // metric name (OTLP-style identifier)
142, // value
'count', // unit
{ 'queue.name': 'orders' }, // tags (low cardinality)
{ exemplar: 'msg-abc' }, // meta (richer)
);
// Convenience for durations — same as metric() with unit='ms'.
LogCaffe.recordHistogram('settlement.duration', 1234, { region: 'eu' });
// Emit a structured INFO log with `meta.event` set. Templates filter on
// these via the @event match in the LogCaffe DSL.
LogCaffe.event('checkout.complete', { 'order.id': '123', amount: 4900 });
LogCaffe.event('user.signup', { 'user.id': 'u-42', plan: 'pro' });
LogCaffe.event('payment.failed', { 'order.id': '123', reason: 'insufficient_funds' });metric() writes to the Metric table with name populated. The dashboard's metric widgets query by name:http.server.duration and aggregate p50/p95/p99/avg/sum/count over time.
RabbitMQ trace continuation
LogCaffe.init({
// ...
enableTracing: true,
traceAutoInstrument: { http: true, fetch: true, pg: true, redis: true, amqp: true },
});Publisher's traceparent flows through properties.headers.traceparent to the consumer. One trace, two spans, joined automatically — works with amqplib 0.10+.
Continuous CPU profiler
LogCaffe.init({
// ...
enableContinuousProfiler: true,
profilerIntervalMs: 60_000, // start a new profile every minute
profilerSampleMs: 10_000, // sample for 10s out of each minute
profilerSampleRate: 1.0, // 0..1 fraction of cycles
});V8 .cpuprofile blobs are uploaded to /api/profiles/upload. Render flame graphs in the dashboard's CPU Profiles page.
Heap snapshots (manual trigger)
import { captureHeapSnapshot } from '@logcaffe/node';
await captureHeapSnapshot({
service: 'my-api',
serverUrl: 'https://collector.your-logcaffe-host',
apiKey: process.env.LOGCAFFE_API_KEY!,
});Full configuration reference
LogCaffe.init({
serverUrl: string, // required
apiKey: string, // required (tenant-scoped)
secretKey?: string, // for HMAC-signed ingest
service: string, // required — used as default tag everywhere
environment?: string, // default 'production'
release?: string, // app version / build SHA
// Capture toggles
captureConsole?: boolean, // intercept console.* (default false)
captureSystemMetrics?: boolean, // CPU/mem/load every systemMetricsInterval
captureProcessMetrics?: boolean, // heap/event-loop-lag/GC-pause
captureUnhandledErrors?: boolean, // window.onerror equivalent (default true)
captureRequestBody?: boolean, // body of failed (>=400) requests
captureResponseBody?: boolean,
// Tracing
enableTracing?: boolean, // default false
traceSampleRate?: number, // 0..1
traceAutoInstrument?: {
http?: boolean, // default true when enableTracing
fetch?: boolean,
pg?: boolean,
redis?: boolean,
amqp?: boolean, // default false (opt-in)
},
traceIgnorePaths?: string[],
ignorePaths?: string[], // also for log/api-call recording
// Profiling (E3.A4)
enableContinuousProfiler?: boolean, // default false
profilerIntervalMs?: number, // default 60_000
profilerSampleMs?: number, // default 10_000
profilerSampleRate?: number, // default 1.0
// Batching / buffering
flushInterval?: number, // ms, default 3000
systemMetricsInterval?: number, // ms, default 15000
maxBatchSize?: number, // default 100
maxBufferSize?: number, // default 1000
logLevel?: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'FATAL', // gate on emission
});Manual logging
LogCaffe.debug('cache miss', { key: 'user:42' });
LogCaffe.info('order received', { orderId: 'abc' });
LogCaffe.warn('retry exceeded', { attempt: 5 });
LogCaffe.error('db connection lost', { hostname: 'pg-1' });
LogCaffe.fatal('unrecoverable: schema mismatch');Compatibility
- Node.js ≥ 18
- Optional peer deps:
express,pg,ioredis,amqplib,prisma— auto-instrumented when present, silently skipped when not. - Compatible LogCaffe collector:
>= 0.4.0. Older collectors silently ignore the newname/tagsfields on metrics.
Documentation
https://logcaffe.inhouse.electioncaffe.ai/docs/node-sdk
License
MIT — see LICENSE.
