@deeptracer/node 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,494 @@
1
+ # @deeptracer/node
2
+
3
+ DeepTracer SDK for **Node.js and Bun** applications. Provides automatic global error capture, console interception, and HTTP middleware for Hono and Express -- on top of the full core logging, tracing, and error tracking API.
4
+
5
+ This is the **recommended entry point** for any Node.js or Bun server. It re-exports everything from [`@deeptracer/core`](https://github.com/getdeeptracer/deeptracer-js/tree/main/packages/core), so you only need to import from `@deeptracer/node`.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Installation](#installation)
10
+ - [Quick Start](#quick-start)
11
+ - [API Reference](#api-reference)
12
+ - [init(config)](#initconfig)
13
+ - [captureGlobalErrors(logger)](#captureglobalerrors)
14
+ - [captureConsole(logger)](#captureconsole)
15
+ - [honoMiddleware(logger, options?)](#honomiddleware)
16
+ - [expressMiddleware(logger, options?)](#expressmiddleware)
17
+ - [MiddlewareOptions](#middlewareoptions)
18
+ - [Re-exported from @deeptracer/core](#re-exported-from-deeptracercore)
19
+ - [Full Examples](#full-examples)
20
+ - [Hono + Bun Server](#hono--bun-server)
21
+ - [Express Server](#express-server)
22
+ - [Background Worker](#background-worker)
23
+ - [Monorepo](#monorepo)
24
+ - [License](#license)
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ npm install @deeptracer/node
30
+ ```
31
+
32
+ `@deeptracer/core` is included as a dependency and does not need to be installed separately.
33
+
34
+ The package ships as both ESM and CJS with full TypeScript declarations.
35
+
36
+ ## Quick Start
37
+
38
+ ```ts
39
+ import { init, honoMiddleware, captureConsole } from "@deeptracer/node"
40
+ import { Hono } from "hono"
41
+
42
+ // 1. Initialize -- creates a logger and captures uncaught errors automatically
43
+ const logger = init({
44
+ product: "my-app",
45
+ service: "api",
46
+ environment: "production",
47
+ endpoint: "https://your-deeptracer.example.com",
48
+ apiKey: "dt_live_xxx",
49
+ })
50
+
51
+ // 2. (Optional) Forward all console.* calls to DeepTracer
52
+ captureConsole(logger)
53
+
54
+ // 3. Add middleware for automatic request tracing
55
+ const app = new Hono()
56
+ app.use(honoMiddleware(logger))
57
+
58
+ app.get("/", (c) => c.text("Hello!"))
59
+
60
+ export default app
61
+ ```
62
+
63
+ ## API Reference
64
+
65
+ ### init(config)
66
+
67
+ Initialize DeepTracer for Node.js/Bun with sensible defaults. Creates a `Logger` instance and automatically sets up global error capture via `captureGlobalErrors()`.
68
+
69
+ **This is the recommended way to set up DeepTracer.** It is equivalent to calling `createLogger(config)` followed by `captureGlobalErrors(logger)`.
70
+
71
+ ```ts
72
+ import { init } from "@deeptracer/node"
73
+
74
+ const logger = init({
75
+ product: "my-app",
76
+ service: "api",
77
+ environment: "production",
78
+ endpoint: "https://your-deeptracer.example.com",
79
+ apiKey: "dt_live_xxx",
80
+ })
81
+ ```
82
+
83
+ **Parameters:**
84
+ - `config: LoggerConfig` -- Logger configuration. See [`@deeptracer/core` Configuration](https://github.com/getdeeptracer/deeptracer-js/tree/main/packages/core#configuration) for the full reference.
85
+
86
+ **Returns:** `Logger` -- A fully configured logger instance with global error capture active.
87
+
88
+ **Config quick reference:**
89
+
90
+ | Field | Type | Required | Default | Description |
91
+ |-------|------|----------|---------|-------------|
92
+ | `product` | `string` | Yes | -- | Product name (e.g., `"spotbeam"`) |
93
+ | `service` | `string` | Yes | -- | Service name (e.g., `"api"`) |
94
+ | `environment` | `"production" \| "staging"` | Yes | -- | Deployment environment |
95
+ | `endpoint` | `string` | Yes | -- | DeepTracer ingestion endpoint URL |
96
+ | `apiKey` | `string` | Yes | -- | DeepTracer API key |
97
+ | `batchSize` | `number` | No | `50` | Log entries to buffer before flushing |
98
+ | `flushIntervalMs` | `number` | No | `5000` | Milliseconds between automatic flushes |
99
+ | `debug` | `boolean` | No | `false` | Mirror all logs to local console |
100
+
101
+ ---
102
+
103
+ ### captureGlobalErrors(logger)
104
+
105
+ Automatically capture all uncaught exceptions and unhandled promise rejections via Node.js/Bun `process` events. Call once at application startup.
106
+
107
+ ```ts
108
+ import { createLogger, captureGlobalErrors } from "@deeptracer/node"
109
+
110
+ const logger = createLogger({ /* ... */ })
111
+ captureGlobalErrors(logger)
112
+ ```
113
+
114
+ **Parameters:**
115
+ - `logger: Logger` -- A DeepTracer logger instance.
116
+
117
+ **Returns:** `void`
118
+
119
+ **Behavior:**
120
+ - `process.on("uncaughtException")` -- Reports the error with severity `"critical"` and immediately flushes.
121
+ - `process.on("unhandledRejection")` -- Reports the error with severity `"high"` and immediately flushes.
122
+
123
+ Errors are sent immediately via `captureError()` (not batched) and `flush()` is called after each to ensure delivery before a potential process exit.
124
+
125
+ > **Note:** `init()` calls this automatically. You only need to call `captureGlobalErrors()` directly if you are using `createLogger()` instead of `init()`.
126
+
127
+ ---
128
+
129
+ ### captureConsole(logger)
130
+
131
+ Intercept all `console.log`, `console.info`, `console.warn`, `console.error`, and `console.debug` calls and forward them to DeepTracer as log entries. **Original console output is preserved** -- messages still appear in stdout/stderr as normal.
132
+
133
+ ```ts
134
+ import { init, captureConsole } from "@deeptracer/node"
135
+
136
+ const logger = init({ /* ... */ })
137
+ captureConsole(logger)
138
+
139
+ // All of these now go to BOTH the console AND DeepTracer:
140
+ console.log("Server started on port 3000")
141
+ console.error("Something went wrong")
142
+ ```
143
+
144
+ **Parameters:**
145
+ - `logger: Logger` -- A DeepTracer logger instance.
146
+
147
+ **Returns:** `void`
148
+
149
+ **Console method to log level mapping:**
150
+
151
+ | Console Method | DeepTracer Level |
152
+ |----------------|------------------|
153
+ | `console.log()` | `info` |
154
+ | `console.info()` | `info` |
155
+ | `console.warn()` | `warn` |
156
+ | `console.error()` | `error` |
157
+ | `console.debug()` | `debug` |
158
+
159
+ Multiple arguments are joined with spaces (e.g., `console.log("a", "b")` becomes `"a b"`).
160
+
161
+ > **Implementation note:** The original console methods are preserved internally before interception. When the logger's `debug: true` option is active, it uses the preserved originals to avoid infinite recursion.
162
+
163
+ ---
164
+
165
+ ### honoMiddleware(logger, options?)
166
+
167
+ Create Hono-compatible middleware that automatically instruments every HTTP request with:
168
+
169
+ - **Distributed tracing** -- creates a span per request, propagates `x-trace-id` and `x-span-id` response headers.
170
+ - **Duration tracking** -- span records total request time.
171
+ - **Trace context extraction** -- reads `x-trace-id`, `x-span-id`, `x-request-id`, and `x-vercel-id` from incoming request headers.
172
+ - **Automatic error capture** -- if the handler throws, the span ends with `status: "error"`.
173
+
174
+ ```ts
175
+ import { Hono } from "hono"
176
+ import { init, honoMiddleware } from "@deeptracer/node"
177
+
178
+ const logger = init({ /* ... */ })
179
+ const app = new Hono()
180
+
181
+ // Basic usage -- traces all requests
182
+ app.use(honoMiddleware(logger))
183
+
184
+ // With options
185
+ app.use(honoMiddleware(logger, {
186
+ ignorePaths: ["/health", "/ready", "/metrics"],
187
+ operationName: (method, path) => `HTTP ${method} ${path}`,
188
+ }))
189
+
190
+ app.get("/api/users", async (c) => {
191
+ // The request is already being traced by the middleware
192
+ return c.json({ users: [] })
193
+ })
194
+ ```
195
+
196
+ **Parameters:**
197
+ - `logger: Logger` -- A DeepTracer logger instance.
198
+ - `options?: MiddlewareOptions` -- Optional configuration (see [MiddlewareOptions](#middlewareoptions)).
199
+
200
+ **Returns:** A Hono middleware function `(c, next) => Promise<void>`. Pass directly to `app.use()`.
201
+
202
+ **Default span operation name:** `"{METHOD} {path}"` (e.g., `"GET /api/users"`).
203
+
204
+ ---
205
+
206
+ ### expressMiddleware(logger, options?)
207
+
208
+ Create Express-compatible middleware that automatically instruments every HTTP request. Same capabilities as `honoMiddleware` but for Express.
209
+
210
+ ```ts
211
+ import express from "express"
212
+ import { init, expressMiddleware } from "@deeptracer/node"
213
+
214
+ const logger = init({ /* ... */ })
215
+ const app = express()
216
+
217
+ // Basic usage
218
+ app.use(expressMiddleware(logger))
219
+
220
+ // With options
221
+ app.use(expressMiddleware(logger, {
222
+ ignorePaths: ["/health"],
223
+ }))
224
+
225
+ app.get("/api/users", (req, res) => {
226
+ res.json({ users: [] })
227
+ })
228
+
229
+ app.listen(3000)
230
+ ```
231
+
232
+ **Parameters:**
233
+ - `logger: Logger` -- A DeepTracer logger instance.
234
+ - `options?: MiddlewareOptions` -- Optional configuration (see [MiddlewareOptions](#middlewareoptions)).
235
+
236
+ **Returns:** An Express middleware function `(req, res, next) => void`. Pass directly to `app.use()`.
237
+
238
+ **Behavior details:**
239
+ - Reads trace context from incoming headers (`x-trace-id`, `x-span-id`, `x-request-id`, `x-vercel-id`).
240
+ - Sets `x-trace-id` and `x-span-id` response headers.
241
+ - Listens on the `res.on("finish")` event to end the span with the final HTTP status code.
242
+ - Status codes >= 400 result in `status: "error"` on the span.
243
+ - Span metadata includes `status_code`, `method`, and `path`.
244
+
245
+ ---
246
+
247
+ ### MiddlewareOptions
248
+
249
+ Configuration options shared by both `honoMiddleware` and `expressMiddleware`.
250
+
251
+ ```ts
252
+ interface MiddlewareOptions {
253
+ /** Custom function to generate the span operation name. Default: "{METHOD} {path}" */
254
+ operationName?: (method: string, path: string) => string
255
+ /** Paths to exclude from tracing (e.g., ["/health", "/ready"]) */
256
+ ignorePaths?: string[]
257
+ }
258
+ ```
259
+
260
+ | Field | Type | Default | Description |
261
+ |-------|------|---------|-------------|
262
+ | `operationName` | `(method: string, path: string) => string` | `` `${method} ${path}` `` | Custom operation name for the request span |
263
+ | `ignorePaths` | `string[]` | `[]` | Paths to skip tracing. Uses `startsWith` matching. |
264
+
265
+ **Examples:**
266
+
267
+ ```ts
268
+ // Skip health checks and static assets
269
+ honoMiddleware(logger, {
270
+ ignorePaths: ["/health", "/ready", "/_next/static"],
271
+ })
272
+
273
+ // Custom operation naming
274
+ honoMiddleware(logger, {
275
+ operationName: (method, path) => {
276
+ // Group dynamic routes: /api/users/123 -> "GET /api/users/:id"
277
+ const normalized = path.replace(/\/[a-f0-9-]{36}/g, "/:id")
278
+ return `${method} ${normalized}`
279
+ },
280
+ })
281
+ ```
282
+
283
+ ## Re-exported from @deeptracer/core
284
+
285
+ `@deeptracer/node` re-exports the entire public API from `@deeptracer/core`. You do **not** need to install or import from `@deeptracer/core` separately.
286
+
287
+ **Functions:**
288
+ - `createLogger(config)` -- Create a logger instance (use `init()` instead for automatic global error capture)
289
+
290
+ **Logger methods** (available on the `Logger` instance returned by `init()` or `createLogger()`):
291
+ - `logger.debug(message, metadata?, error?)` -- Log a debug message
292
+ - `logger.info(message, metadata?, error?)` -- Log an info message
293
+ - `logger.warn(message, metadata?, error?)` -- Log a warning
294
+ - `logger.error(message, metadata?, error?)` -- Log an error
295
+ - `logger.captureError(error, options?)` -- Report an error immediately
296
+ - `logger.startSpan(operation, fn)` -- Callback-based tracing (auto-ends)
297
+ - `logger.startInactiveSpan(operation)` -- Manual tracing (call `.end()`)
298
+ - `logger.wrap(operation, fn)` -- Wrap a function with automatic tracing
299
+ - `logger.llmUsage(report)` -- Report LLM usage
300
+ - `logger.forRequest(request)` -- Create a request-scoped logger
301
+ - `logger.withContext(name)` -- Create a context-scoped logger
302
+ - `logger.flush()` -- Immediately flush buffered logs
303
+ - `logger.destroy()` -- Stop the batch timer and flush
304
+
305
+ **Types:**
306
+ - `LoggerConfig`, `Logger`, `LogLevel`, `LogEntry`, `ErrorReport`, `LLMUsageReport`, `Span`, `InactiveSpan`, `SpanData`, `MiddlewareOptions`
307
+
308
+ See the [`@deeptracer/core` README](https://github.com/getdeeptracer/deeptracer-js/tree/main/packages/core) for full documentation of these APIs.
309
+
310
+ ## Full Examples
311
+
312
+ ### Hono + Bun Server
313
+
314
+ A complete Hono server running on Bun with full DeepTracer instrumentation:
315
+
316
+ ```ts
317
+ import { Hono } from "hono"
318
+ import { init, honoMiddleware, captureConsole } from "@deeptracer/node"
319
+ import { wrapVercelAI } from "@deeptracer/ai"
320
+ import { generateText } from "ai"
321
+ import { openai } from "@ai-sdk/openai"
322
+
323
+ // Initialize DeepTracer
324
+ const logger = init({
325
+ product: "my-saas",
326
+ service: "api",
327
+ environment: "production",
328
+ endpoint: process.env.DEEPTRACER_ENDPOINT!,
329
+ apiKey: process.env.DEEPTRACER_API_KEY!,
330
+ debug: process.env.NODE_ENV !== "production",
331
+ })
332
+
333
+ // Capture all console output
334
+ captureConsole(logger)
335
+
336
+ // Wrap AI SDK
337
+ const ai = wrapVercelAI(logger, { generateText })
338
+
339
+ // Create Hono app with middleware
340
+ const app = new Hono()
341
+ app.use(honoMiddleware(logger, {
342
+ ignorePaths: ["/health"],
343
+ }))
344
+
345
+ // Health check (excluded from tracing)
346
+ app.get("/health", (c) => c.text("ok"))
347
+
348
+ // API routes
349
+ app.get("/api/summarize", async (c) => {
350
+ const reqLogger = logger.forRequest(c.req.raw)
351
+ const url = c.req.query("url")
352
+
353
+ reqLogger.info("Summarization requested", { url })
354
+
355
+ try {
356
+ const { text } = await ai.generateText({
357
+ model: openai("gpt-4o"),
358
+ prompt: `Summarize: ${url}`,
359
+ })
360
+ return c.json({ summary: text })
361
+ } catch (err) {
362
+ reqLogger.captureError(err, { severity: "high", context: { url } })
363
+ return c.json({ error: "Failed to summarize" }, 500)
364
+ }
365
+ })
366
+
367
+ // Graceful shutdown
368
+ process.on("SIGTERM", () => {
369
+ logger.destroy()
370
+ process.exit(0)
371
+ })
372
+
373
+ export default {
374
+ port: 3001,
375
+ fetch: app.fetch,
376
+ }
377
+ ```
378
+
379
+ ### Express Server
380
+
381
+ A complete Express server with DeepTracer:
382
+
383
+ ```ts
384
+ import express from "express"
385
+ import { init, expressMiddleware, captureConsole } from "@deeptracer/node"
386
+
387
+ const logger = init({
388
+ product: "my-saas",
389
+ service: "web-api",
390
+ environment: "production",
391
+ endpoint: process.env.DEEPTRACER_ENDPOINT!,
392
+ apiKey: process.env.DEEPTRACER_API_KEY!,
393
+ })
394
+
395
+ captureConsole(logger)
396
+
397
+ const app = express()
398
+ app.use(express.json())
399
+ app.use(expressMiddleware(logger, {
400
+ ignorePaths: ["/health", "/ready"],
401
+ }))
402
+
403
+ app.get("/health", (req, res) => res.send("ok"))
404
+
405
+ app.post("/api/orders", async (req, res) => {
406
+ const orderLogger = logger.withContext("orders")
407
+
408
+ try {
409
+ const order = await logger.startSpan("create-order", async () => {
410
+ orderLogger.info("Creating order", { items: req.body.items?.length })
411
+ return createOrder(req.body)
412
+ })
413
+
414
+ res.json(order)
415
+ } catch (err) {
416
+ orderLogger.captureError(err, { severity: "high" })
417
+ res.status(500).json({ error: "Order creation failed" })
418
+ }
419
+ })
420
+
421
+ const server = app.listen(3000, () => {
422
+ logger.info("Server started", { port: 3000 })
423
+ })
424
+
425
+ process.on("SIGTERM", () => {
426
+ logger.destroy()
427
+ server.close()
428
+ })
429
+ ```
430
+
431
+ ### Background Worker
432
+
433
+ A background job processor with tracing:
434
+
435
+ ```ts
436
+ import { init } from "@deeptracer/node"
437
+
438
+ const logger = init({
439
+ product: "my-saas",
440
+ service: "worker",
441
+ environment: "production",
442
+ endpoint: process.env.DEEPTRACER_ENDPOINT!,
443
+ apiKey: process.env.DEEPTRACER_API_KEY!,
444
+ })
445
+
446
+ const workerLogger = logger.withContext("job-processor")
447
+
448
+ async function processJob(job: Job) {
449
+ await workerLogger.startSpan(`job:${job.type}`, async (span) => {
450
+ workerLogger.info("Processing job", { jobId: job.id, type: job.type })
451
+
452
+ // Nested span for a specific step
453
+ await workerLogger.startSpan("send-email", async (childSpan) => {
454
+ await sendEmail(job.payload)
455
+ })
456
+
457
+ workerLogger.info("Job completed", { jobId: job.id })
458
+ })
459
+ }
460
+
461
+ // Process jobs in a loop
462
+ async function main() {
463
+ workerLogger.info("Worker started")
464
+
465
+ while (true) {
466
+ try {
467
+ const job = await getNextJob()
468
+ if (job) await processJob(job)
469
+ else await sleep(1000)
470
+ } catch (err) {
471
+ workerLogger.captureError(err, { severity: "high" })
472
+ }
473
+ }
474
+ }
475
+
476
+ main()
477
+ ```
478
+
479
+ ## Monorepo
480
+
481
+ This package is part of the [DeepTracer JavaScript SDK](https://github.com/getdeeptracer/deeptracer-js) monorepo:
482
+
483
+ | Package | Description |
484
+ |---------|-------------|
485
+ | [`@deeptracer/core`](https://github.com/getdeeptracer/deeptracer-js/tree/main/packages/core) | Zero-dependency shared core |
486
+ | **`@deeptracer/node`** | Node.js/Bun SDK (this package) |
487
+ | [`@deeptracer/ai`](https://github.com/getdeeptracer/deeptracer-js/tree/main/packages/ai) | AI SDK wrappers -- Vercel AI, OpenAI, Anthropic |
488
+ | [`@deeptracer/browser`](https://github.com/getdeeptracer/deeptracer-js/tree/main/packages/browser) | Browser SDK (preview) |
489
+ | [`@deeptracer/react`](https://github.com/getdeeptracer/deeptracer-js/tree/main/packages/react) | React integration (coming soon) |
490
+ | [`@deeptracer/nextjs`](https://github.com/getdeeptracer/deeptracer-js/tree/main/packages/nextjs) | Next.js integration (coming soon) |
491
+
492
+ ## License
493
+
494
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.ts
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ captureConsole: () => captureConsole,
25
+ captureGlobalErrors: () => captureGlobalErrors,
26
+ expressMiddleware: () => expressMiddleware,
27
+ honoMiddleware: () => honoMiddleware,
28
+ init: () => init
29
+ });
30
+ module.exports = __toCommonJS(index_exports);
31
+ __reExport(index_exports, require("@deeptracer/core"), module.exports);
32
+
33
+ // src/global-errors.ts
34
+ function captureGlobalErrors(logger) {
35
+ process.on("uncaughtException", (error) => {
36
+ logger.captureError(error, { severity: "critical" });
37
+ logger.flush();
38
+ });
39
+ process.on("unhandledRejection", (reason) => {
40
+ logger.captureError(
41
+ reason instanceof Error ? reason : new Error(String(reason)),
42
+ { severity: "high" }
43
+ );
44
+ logger.flush();
45
+ });
46
+ }
47
+
48
+ // src/console.ts
49
+ var import_internal = require("@deeptracer/core/internal");
50
+ function captureConsole(logger) {
51
+ console.log = (...args) => {
52
+ logger.info(args.map(String).join(" "));
53
+ import_internal._originalConsole.log(...args);
54
+ };
55
+ console.info = (...args) => {
56
+ logger.info(args.map(String).join(" "));
57
+ import_internal._originalConsole.info(...args);
58
+ };
59
+ console.warn = (...args) => {
60
+ logger.warn(args.map(String).join(" "));
61
+ import_internal._originalConsole.warn(...args);
62
+ };
63
+ console.error = (...args) => {
64
+ logger.error(args.map(String).join(" "));
65
+ import_internal._originalConsole.error(...args);
66
+ };
67
+ console.debug = (...args) => {
68
+ logger.debug(args.map(String).join(" "));
69
+ import_internal._originalConsole.debug(...args);
70
+ };
71
+ }
72
+
73
+ // src/middleware.ts
74
+ function honoMiddleware(logger, options) {
75
+ return async (c, next) => {
76
+ const method = c.req.method;
77
+ const path = c.req.path;
78
+ if (options?.ignorePaths?.some((p) => path.startsWith(p))) {
79
+ return next();
80
+ }
81
+ const opName = options?.operationName ? options.operationName(method, path) : `${method} ${path}`;
82
+ const reqLogger = logger.forRequest(c.req.raw);
83
+ return reqLogger.startSpan(opName, async (span) => {
84
+ c.header("x-trace-id", span.traceId);
85
+ c.header("x-span-id", span.spanId);
86
+ await next();
87
+ });
88
+ };
89
+ }
90
+ function expressMiddleware(logger, options) {
91
+ return (req, res, next) => {
92
+ const method = req.method;
93
+ const path = req.path || req.url;
94
+ if (options?.ignorePaths?.some((p) => path.startsWith(p))) {
95
+ return next();
96
+ }
97
+ const opName = options?.operationName ? options.operationName(method, path) : `${method} ${path}`;
98
+ const traceId = req.headers["x-trace-id"] || void 0;
99
+ const spanId = req.headers["x-span-id"] || void 0;
100
+ const requestId = req.headers["x-request-id"] || void 0;
101
+ const vercelId = req.headers["x-vercel-id"] || void 0;
102
+ const reqLogger = new logger.constructor(
103
+ logger.config,
104
+ logger.contextName,
105
+ {
106
+ trace_id: traceId,
107
+ span_id: spanId,
108
+ request_id: requestId || (vercelId ? vercelId.split("::").pop() : void 0),
109
+ vercel_id: vercelId
110
+ }
111
+ );
112
+ const span = reqLogger.startInactiveSpan(opName);
113
+ res.setHeader("x-trace-id", span.traceId);
114
+ res.setHeader("x-span-id", span.spanId);
115
+ res.on("finish", () => {
116
+ const status = res.statusCode >= 400 ? "error" : "ok";
117
+ span.end({
118
+ status,
119
+ metadata: { status_code: res.statusCode, method, path }
120
+ });
121
+ });
122
+ next();
123
+ };
124
+ }
125
+
126
+ // src/init.ts
127
+ var import_core = require("@deeptracer/core");
128
+ function init(config) {
129
+ const logger = (0, import_core.createLogger)(config);
130
+ captureGlobalErrors(logger);
131
+ return logger;
132
+ }
133
+ // Annotate the CommonJS export names for ESM import in node:
134
+ 0 && (module.exports = {
135
+ captureConsole,
136
+ captureGlobalErrors,
137
+ expressMiddleware,
138
+ honoMiddleware,
139
+ init,
140
+ ...require("@deeptracer/core")
141
+ });
@@ -0,0 +1,108 @@
1
+ import { Logger, MiddlewareOptions, LoggerConfig } from '@deeptracer/core';
2
+ export * from '@deeptracer/core';
3
+
4
+ /**
5
+ * Automatically capture all uncaught exceptions and unhandled promise rejections
6
+ * via Node.js/Bun process events. Call once at application startup.
7
+ *
8
+ * Uncaught exceptions are reported with severity "critical".
9
+ * Unhandled rejections are reported with severity "high".
10
+ * Errors are flushed immediately to ensure delivery before process exit.
11
+ *
12
+ * @param logger - DeepTracer logger instance
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { createLogger, captureGlobalErrors } from "@deeptracer/node"
17
+ *
18
+ * const logger = createLogger({ ... })
19
+ * captureGlobalErrors(logger)
20
+ * // All uncaught errors now automatically sent to DeepTracer
21
+ * ```
22
+ */
23
+ declare function captureGlobalErrors(logger: Logger): void;
24
+
25
+ /**
26
+ * Intercept all console.log/info/warn/error/debug calls and forward them
27
+ * to DeepTracer as log entries. Original console output is preserved.
28
+ *
29
+ * @param logger - DeepTracer logger instance
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * import { createLogger, captureConsole } from "@deeptracer/node"
34
+ *
35
+ * const logger = createLogger({ ... })
36
+ * captureConsole(logger)
37
+ * // console.log("hello") now goes to BOTH console AND DeepTracer
38
+ * ```
39
+ */
40
+ declare function captureConsole(logger: Logger): void;
41
+
42
+ /**
43
+ * Create Hono-compatible middleware that auto-instruments every request with:
44
+ * - Distributed tracing (creates a span per request)
45
+ * - Duration tracking
46
+ * - HTTP status code capture
47
+ * - Automatic error capture
48
+ *
49
+ * @param logger - DeepTracer logger instance
50
+ * @param options - Optional middleware configuration
51
+ * @returns A Hono middleware function — pass directly to `app.use()`
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * import { Hono } from "hono"
56
+ * import { createLogger, honoMiddleware } from "@deeptracer/node"
57
+ *
58
+ * const logger = createLogger({ ... })
59
+ * const app = new Hono()
60
+ * app.use(honoMiddleware(logger))
61
+ * ```
62
+ */
63
+ declare function honoMiddleware(logger: Logger, options?: MiddlewareOptions): (c: any, next: () => Promise<void>) => Promise<void>;
64
+ /**
65
+ * Create Express-compatible middleware that auto-instruments every request.
66
+ *
67
+ * @param logger - DeepTracer logger instance
68
+ * @param options - Optional middleware configuration
69
+ * @returns An Express middleware function — pass directly to `app.use()`
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * import express from "express"
74
+ * import { createLogger, expressMiddleware } from "@deeptracer/node"
75
+ *
76
+ * const logger = createLogger({ ... })
77
+ * const app = express()
78
+ * app.use(expressMiddleware(logger))
79
+ * ```
80
+ */
81
+ declare function expressMiddleware(logger: Logger, options?: MiddlewareOptions): (req: any, res: any, next: () => void) => void;
82
+
83
+ /**
84
+ * Initialize DeepTracer for Node.js/Bun with sensible defaults.
85
+ * Creates a logger and automatically sets up global error capture.
86
+ *
87
+ * This is the recommended way to set up DeepTracer in a Node.js/Bun application.
88
+ *
89
+ * @param config - Logger configuration
90
+ * @returns A Logger instance with global error capture enabled
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * import { init } from "@deeptracer/node"
95
+ *
96
+ * const logger = init({
97
+ * product: "my-app",
98
+ * service: "api",
99
+ * environment: "production",
100
+ * endpoint: "https://deeptracer.example.com",
101
+ * apiKey: "dt_live_xxx",
102
+ * })
103
+ * // Global error capture is already active!
104
+ * ```
105
+ */
106
+ declare function init(config: LoggerConfig): Logger;
107
+
108
+ export { captureConsole, captureGlobalErrors, expressMiddleware, honoMiddleware, init };
@@ -0,0 +1,108 @@
1
+ import { Logger, MiddlewareOptions, LoggerConfig } from '@deeptracer/core';
2
+ export * from '@deeptracer/core';
3
+
4
+ /**
5
+ * Automatically capture all uncaught exceptions and unhandled promise rejections
6
+ * via Node.js/Bun process events. Call once at application startup.
7
+ *
8
+ * Uncaught exceptions are reported with severity "critical".
9
+ * Unhandled rejections are reported with severity "high".
10
+ * Errors are flushed immediately to ensure delivery before process exit.
11
+ *
12
+ * @param logger - DeepTracer logger instance
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { createLogger, captureGlobalErrors } from "@deeptracer/node"
17
+ *
18
+ * const logger = createLogger({ ... })
19
+ * captureGlobalErrors(logger)
20
+ * // All uncaught errors now automatically sent to DeepTracer
21
+ * ```
22
+ */
23
+ declare function captureGlobalErrors(logger: Logger): void;
24
+
25
+ /**
26
+ * Intercept all console.log/info/warn/error/debug calls and forward them
27
+ * to DeepTracer as log entries. Original console output is preserved.
28
+ *
29
+ * @param logger - DeepTracer logger instance
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * import { createLogger, captureConsole } from "@deeptracer/node"
34
+ *
35
+ * const logger = createLogger({ ... })
36
+ * captureConsole(logger)
37
+ * // console.log("hello") now goes to BOTH console AND DeepTracer
38
+ * ```
39
+ */
40
+ declare function captureConsole(logger: Logger): void;
41
+
42
+ /**
43
+ * Create Hono-compatible middleware that auto-instruments every request with:
44
+ * - Distributed tracing (creates a span per request)
45
+ * - Duration tracking
46
+ * - HTTP status code capture
47
+ * - Automatic error capture
48
+ *
49
+ * @param logger - DeepTracer logger instance
50
+ * @param options - Optional middleware configuration
51
+ * @returns A Hono middleware function — pass directly to `app.use()`
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * import { Hono } from "hono"
56
+ * import { createLogger, honoMiddleware } from "@deeptracer/node"
57
+ *
58
+ * const logger = createLogger({ ... })
59
+ * const app = new Hono()
60
+ * app.use(honoMiddleware(logger))
61
+ * ```
62
+ */
63
+ declare function honoMiddleware(logger: Logger, options?: MiddlewareOptions): (c: any, next: () => Promise<void>) => Promise<void>;
64
+ /**
65
+ * Create Express-compatible middleware that auto-instruments every request.
66
+ *
67
+ * @param logger - DeepTracer logger instance
68
+ * @param options - Optional middleware configuration
69
+ * @returns An Express middleware function — pass directly to `app.use()`
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * import express from "express"
74
+ * import { createLogger, expressMiddleware } from "@deeptracer/node"
75
+ *
76
+ * const logger = createLogger({ ... })
77
+ * const app = express()
78
+ * app.use(expressMiddleware(logger))
79
+ * ```
80
+ */
81
+ declare function expressMiddleware(logger: Logger, options?: MiddlewareOptions): (req: any, res: any, next: () => void) => void;
82
+
83
+ /**
84
+ * Initialize DeepTracer for Node.js/Bun with sensible defaults.
85
+ * Creates a logger and automatically sets up global error capture.
86
+ *
87
+ * This is the recommended way to set up DeepTracer in a Node.js/Bun application.
88
+ *
89
+ * @param config - Logger configuration
90
+ * @returns A Logger instance with global error capture enabled
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * import { init } from "@deeptracer/node"
95
+ *
96
+ * const logger = init({
97
+ * product: "my-app",
98
+ * service: "api",
99
+ * environment: "production",
100
+ * endpoint: "https://deeptracer.example.com",
101
+ * apiKey: "dt_live_xxx",
102
+ * })
103
+ * // Global error capture is already active!
104
+ * ```
105
+ */
106
+ declare function init(config: LoggerConfig): Logger;
107
+
108
+ export { captureConsole, captureGlobalErrors, expressMiddleware, honoMiddleware, init };
package/dist/index.js ADDED
@@ -0,0 +1,110 @@
1
+ // src/index.ts
2
+ export * from "@deeptracer/core";
3
+
4
+ // src/global-errors.ts
5
+ function captureGlobalErrors(logger) {
6
+ process.on("uncaughtException", (error) => {
7
+ logger.captureError(error, { severity: "critical" });
8
+ logger.flush();
9
+ });
10
+ process.on("unhandledRejection", (reason) => {
11
+ logger.captureError(
12
+ reason instanceof Error ? reason : new Error(String(reason)),
13
+ { severity: "high" }
14
+ );
15
+ logger.flush();
16
+ });
17
+ }
18
+
19
+ // src/console.ts
20
+ import { _originalConsole } from "@deeptracer/core/internal";
21
+ function captureConsole(logger) {
22
+ console.log = (...args) => {
23
+ logger.info(args.map(String).join(" "));
24
+ _originalConsole.log(...args);
25
+ };
26
+ console.info = (...args) => {
27
+ logger.info(args.map(String).join(" "));
28
+ _originalConsole.info(...args);
29
+ };
30
+ console.warn = (...args) => {
31
+ logger.warn(args.map(String).join(" "));
32
+ _originalConsole.warn(...args);
33
+ };
34
+ console.error = (...args) => {
35
+ logger.error(args.map(String).join(" "));
36
+ _originalConsole.error(...args);
37
+ };
38
+ console.debug = (...args) => {
39
+ logger.debug(args.map(String).join(" "));
40
+ _originalConsole.debug(...args);
41
+ };
42
+ }
43
+
44
+ // src/middleware.ts
45
+ function honoMiddleware(logger, options) {
46
+ return async (c, next) => {
47
+ const method = c.req.method;
48
+ const path = c.req.path;
49
+ if (options?.ignorePaths?.some((p) => path.startsWith(p))) {
50
+ return next();
51
+ }
52
+ const opName = options?.operationName ? options.operationName(method, path) : `${method} ${path}`;
53
+ const reqLogger = logger.forRequest(c.req.raw);
54
+ return reqLogger.startSpan(opName, async (span) => {
55
+ c.header("x-trace-id", span.traceId);
56
+ c.header("x-span-id", span.spanId);
57
+ await next();
58
+ });
59
+ };
60
+ }
61
+ function expressMiddleware(logger, options) {
62
+ return (req, res, next) => {
63
+ const method = req.method;
64
+ const path = req.path || req.url;
65
+ if (options?.ignorePaths?.some((p) => path.startsWith(p))) {
66
+ return next();
67
+ }
68
+ const opName = options?.operationName ? options.operationName(method, path) : `${method} ${path}`;
69
+ const traceId = req.headers["x-trace-id"] || void 0;
70
+ const spanId = req.headers["x-span-id"] || void 0;
71
+ const requestId = req.headers["x-request-id"] || void 0;
72
+ const vercelId = req.headers["x-vercel-id"] || void 0;
73
+ const reqLogger = new logger.constructor(
74
+ logger.config,
75
+ logger.contextName,
76
+ {
77
+ trace_id: traceId,
78
+ span_id: spanId,
79
+ request_id: requestId || (vercelId ? vercelId.split("::").pop() : void 0),
80
+ vercel_id: vercelId
81
+ }
82
+ );
83
+ const span = reqLogger.startInactiveSpan(opName);
84
+ res.setHeader("x-trace-id", span.traceId);
85
+ res.setHeader("x-span-id", span.spanId);
86
+ res.on("finish", () => {
87
+ const status = res.statusCode >= 400 ? "error" : "ok";
88
+ span.end({
89
+ status,
90
+ metadata: { status_code: res.statusCode, method, path }
91
+ });
92
+ });
93
+ next();
94
+ };
95
+ }
96
+
97
+ // src/init.ts
98
+ import { createLogger } from "@deeptracer/core";
99
+ function init(config) {
100
+ const logger = createLogger(config);
101
+ captureGlobalErrors(logger);
102
+ return logger;
103
+ }
104
+ export {
105
+ captureConsole,
106
+ captureGlobalErrors,
107
+ expressMiddleware,
108
+ honoMiddleware,
109
+ init
110
+ };
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@deeptracer/node",
3
+ "version": "0.2.0",
4
+ "description": "DeepTracer SDK for Node.js and Bun — global error capture, console capture, Express & Hono middleware",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": ["dist", "README.md"],
17
+ "sideEffects": false,
18
+ "keywords": ["logging", "observability", "tracing", "deeptracer", "nodejs", "bun", "hono", "express"],
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/getdeeptracer/deeptracer-js.git",
22
+ "directory": "packages/node"
23
+ },
24
+ "license": "MIT",
25
+ "dependencies": {
26
+ "@deeptracer/core": "0.2.0"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": ">=18"
30
+ },
31
+ "scripts": {
32
+ "build": "tsup",
33
+ "dev": "tsup --watch"
34
+ }
35
+ }