@deepeloper/deeptracker 0.1.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/dist/index.js ADDED
@@ -0,0 +1,503 @@
1
+ // src/core/context.ts
2
+ import { AsyncLocalStorage } from "async_hooks";
3
+ var als = new AsyncLocalStorage();
4
+ function getStore() {
5
+ return als.getStore();
6
+ }
7
+ function runWith(store, fn) {
8
+ return als.run(store, fn);
9
+ }
10
+
11
+ // src/core/tracer.ts
12
+ import { performance } from "perf_hooks";
13
+
14
+ // src/core/ids.ts
15
+ import { randomBytes } from "crypto";
16
+ function newTraceId() {
17
+ return randomBytes(16).toString("hex");
18
+ }
19
+ function newSpanId() {
20
+ return randomBytes(8).toString("hex");
21
+ }
22
+
23
+ // src/core/tracer.ts
24
+ var state = {
25
+ appName: "unknown",
26
+ environment: "development",
27
+ sampleRate: 1,
28
+ ignore: [],
29
+ sink: null
30
+ };
31
+ function configure(patch) {
32
+ state = { ...state, ...patch };
33
+ }
34
+ function shouldTrace(req) {
35
+ if (state.sampleRate < 1 && Math.random() > state.sampleRate) return false;
36
+ const path = stripQuery(req.url ?? "");
37
+ for (const rule of state.ignore) {
38
+ if (typeof rule === "string" ? rule === path : safeRule(rule, req)) return false;
39
+ }
40
+ return true;
41
+ }
42
+ function createTrace() {
43
+ return {
44
+ traceId: newTraceId(),
45
+ appName: state.appName,
46
+ environment: state.environment,
47
+ rootSpanId: newSpanId(),
48
+ startWall: Date.now(),
49
+ startMono: performance.now(),
50
+ tags: {},
51
+ spans: [],
52
+ http: {},
53
+ ended: false
54
+ };
55
+ }
56
+ function startSpan(name, type, metadata = {}) {
57
+ const store = getStore();
58
+ if (!store) return null;
59
+ const parentId = store.parent ? store.parent.spanId : store.trace.rootSpanId;
60
+ const span2 = {
61
+ spanId: newSpanId(),
62
+ parentSpanId: parentId,
63
+ traceId: store.trace.traceId,
64
+ name,
65
+ type,
66
+ startTime: Date.now(),
67
+ endTime: 0,
68
+ duration: 0,
69
+ status: "ok",
70
+ metadata,
71
+ events: [],
72
+ _startMono: performance.now()
73
+ };
74
+ store.trace.spans.push(span2);
75
+ return span2;
76
+ }
77
+ function endSpan(span2, error) {
78
+ if (!span2 || span2.endTime !== 0) return;
79
+ span2.duration = performance.now() - span2._startMono;
80
+ span2.endTime = span2.startTime + span2.duration;
81
+ if (error !== void 0) {
82
+ span2.status = "error";
83
+ span2.error = toSpanError(error);
84
+ }
85
+ }
86
+ async function runInSpan(name, type, fn) {
87
+ const store = getStore();
88
+ if (!store) return await fn();
89
+ const span2 = startSpan(name, type);
90
+ if (!span2) return await fn();
91
+ return await runWith({ trace: store.trace, parent: span2 }, async () => {
92
+ try {
93
+ const result = await fn();
94
+ endSpan(span2);
95
+ return result;
96
+ } catch (err) {
97
+ endSpan(span2, err);
98
+ throw err;
99
+ }
100
+ });
101
+ }
102
+ function endTrace(trace, statusCode, path) {
103
+ if (trace.ended) return;
104
+ trace.ended = true;
105
+ const duration = performance.now() - trace.startMono;
106
+ const hasError = statusCode >= 500 || trace.spans.some((s) => s.status === "error");
107
+ const out = {
108
+ traceId: trace.traceId,
109
+ appName: trace.appName,
110
+ environment: trace.environment,
111
+ startTime: trace.startWall,
112
+ endTime: trace.startWall + duration,
113
+ duration,
114
+ status: hasError ? "error" : "ok",
115
+ http: {
116
+ method: trace.http.method ?? "GET",
117
+ path,
118
+ rawPath: trace.http.rawPath ?? path,
119
+ statusCode,
120
+ ...trace.http.userAgent !== void 0 ? { userAgent: trace.http.userAgent } : {}
121
+ },
122
+ tags: trace.tags,
123
+ rootSpanId: trace.rootSpanId,
124
+ spans: trace.spans.map(serializeSpan)
125
+ };
126
+ state.sink?.(out);
127
+ }
128
+ function serializeSpan(span2) {
129
+ const { _startMono: _ignored, ...rest } = span2;
130
+ void _ignored;
131
+ return rest;
132
+ }
133
+ function toSpanError(error) {
134
+ if (error instanceof Error) {
135
+ return {
136
+ message: error.message,
137
+ stack: error.stack ?? "",
138
+ type: error.name || "Error"
139
+ };
140
+ }
141
+ return { message: String(error), stack: "", type: "Error" };
142
+ }
143
+ function safeRule(rule, req) {
144
+ try {
145
+ return rule(req);
146
+ } catch {
147
+ return false;
148
+ }
149
+ }
150
+ function stripQuery(url) {
151
+ const q = url.indexOf("?");
152
+ return q === -1 ? url : url.slice(0, q);
153
+ }
154
+
155
+ // src/core/buffer.ts
156
+ var DEFAULTS = { maxSize: 100, flushIntervalMs: 5e3 };
157
+ var TraceBuffer = class {
158
+ constructor(exporter, opts = {}) {
159
+ this.exporter = exporter;
160
+ this.opts = { ...DEFAULTS, ...opts };
161
+ }
162
+ exporter;
163
+ items = [];
164
+ timer = null;
165
+ opts;
166
+ start() {
167
+ if (this.timer) return;
168
+ this.timer = setInterval(() => void this.flush(), this.opts.flushIntervalMs);
169
+ this.timer.unref?.();
170
+ }
171
+ add(trace) {
172
+ this.items.push(trace);
173
+ if (this.items.length >= this.opts.maxSize) void this.flush();
174
+ }
175
+ async flush() {
176
+ if (this.items.length === 0) return;
177
+ const batch = this.items;
178
+ this.items = [];
179
+ try {
180
+ await this.exporter.export(batch);
181
+ } catch {
182
+ }
183
+ }
184
+ async shutdown() {
185
+ if (this.timer) {
186
+ clearInterval(this.timer);
187
+ this.timer = null;
188
+ }
189
+ await this.flush();
190
+ }
191
+ };
192
+
193
+ // src/transport/console.ts
194
+ var ConsoleExporter = class {
195
+ export(traces) {
196
+ for (const trace of traces) {
197
+ this.print(trace);
198
+ }
199
+ }
200
+ print(trace) {
201
+ const flag = trace.status === "error" ? "\u2717" : "\u2713";
202
+ const head = `${flag} ${trace.http.method} ${trace.http.path} ${trace.http.statusCode} ${fmt(trace.duration)}`;
203
+ console.log(`
204
+ [tracker] ${head} (${trace.traceId})`);
205
+ const byParent = /* @__PURE__ */ new Map();
206
+ for (const span2 of trace.spans) {
207
+ const key = span2.parentSpanId ?? trace.rootSpanId;
208
+ const list = byParent.get(key) ?? [];
209
+ list.push(span2);
210
+ byParent.set(key, list);
211
+ }
212
+ const walk = (parentId, depth) => {
213
+ const children = (byParent.get(parentId) ?? []).sort((a, b) => a.startTime - b.startTime);
214
+ for (const span2 of children) {
215
+ const indent = " ".repeat(depth + 1);
216
+ const mark = span2.status === "error" ? " \u2717" : "";
217
+ console.log(`${indent}${span2.type}: ${span2.name} ${fmt(span2.duration)}${mark}`);
218
+ if (span2.error) {
219
+ console.log(`${indent} \u21B3 ${span2.error.type}: ${span2.error.message}`);
220
+ }
221
+ walk(span2.spanId, depth + 1);
222
+ }
223
+ };
224
+ walk(trace.rootSpanId, 0);
225
+ }
226
+ };
227
+ function fmt(ms) {
228
+ return ms < 1e3 ? `${Math.round(ms)}ms` : `${(ms / 1e3).toFixed(2)}s`;
229
+ }
230
+
231
+ // src/transport/http.ts
232
+ var HttpExporter = class {
233
+ constructor(endpoint, apiKey, timeoutMs = 3e3) {
234
+ this.endpoint = endpoint;
235
+ this.apiKey = apiKey;
236
+ this.timeoutMs = timeoutMs;
237
+ }
238
+ endpoint;
239
+ apiKey;
240
+ timeoutMs;
241
+ async export(traces) {
242
+ const controller = new AbortController();
243
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
244
+ try {
245
+ await fetch(this.endpoint, {
246
+ method: "POST",
247
+ headers: {
248
+ "content-type": "application/json",
249
+ authorization: `Bearer ${this.apiKey}`
250
+ },
251
+ body: JSON.stringify({ traces }),
252
+ signal: controller.signal
253
+ });
254
+ } catch {
255
+ } finally {
256
+ clearTimeout(timer);
257
+ }
258
+ }
259
+ };
260
+
261
+ // src/instruments/http.ts
262
+ import http from "http";
263
+ import https from "https";
264
+
265
+ // src/instruments/wrap.ts
266
+ var WRAPPED = /* @__PURE__ */ Symbol.for("deeptracker.wrapped");
267
+ function wrap(target, name, factory) {
268
+ const original = target[name];
269
+ if (typeof original !== "function") return;
270
+ if (original[WRAPPED]) return;
271
+ const wrapped = factory(original);
272
+ Object.defineProperty(wrapped, "name", {
273
+ value: original.name,
274
+ configurable: true
275
+ });
276
+ wrapped[WRAPPED] = true;
277
+ wrapped.__original = original;
278
+ target[name] = wrapped;
279
+ }
280
+
281
+ // src/instruments/http.ts
282
+ var HANDLED = /* @__PURE__ */ Symbol.for("deeptracker.http.handled");
283
+ function installHttpServer() {
284
+ const patchServer = (proto) => {
285
+ wrap(
286
+ proto,
287
+ "emit",
288
+ (emit) => function(event, ...args) {
289
+ if (event !== "request") return emit.call(this, event, ...args);
290
+ const req = args[0];
291
+ const res = args[1];
292
+ if (!req || !res || req[HANDLED]) return emit.call(this, event, ...args);
293
+ req[HANDLED] = true;
294
+ if (!shouldTrace(req)) return emit.call(this, event, ...args);
295
+ const trace = createTrace();
296
+ trace.http.method = req.method ?? "GET";
297
+ trace.http.rawPath = stripQuery(String(req.url ?? "/"));
298
+ const ua = req.headers?.["user-agent"];
299
+ if (typeof ua === "string") trace.http.userAgent = ua;
300
+ return runWith({ trace, parent: null }, () => {
301
+ res.on("finish", () => {
302
+ endTrace(trace, res.statusCode ?? 0, resolvePath(req, trace.http.rawPath ?? "/"));
303
+ });
304
+ return emit.call(this, event, ...args);
305
+ });
306
+ }
307
+ );
308
+ };
309
+ patchServer(http.Server.prototype);
310
+ if (https.Server && https.Server.prototype !== http.Server.prototype) {
311
+ patchServer(https.Server.prototype);
312
+ }
313
+ }
314
+ function resolvePath(req, fallback) {
315
+ const routePath = req.route?.path;
316
+ if (typeof routePath === "string") {
317
+ return (req.baseUrl ?? "") + routePath;
318
+ }
319
+ return fallback;
320
+ }
321
+ function installHttpClient() {
322
+ for (const [mod, scheme] of [
323
+ [http, "http"],
324
+ [https, "https"]
325
+ ]) {
326
+ for (const method of ["request", "get"]) {
327
+ wrap(
328
+ mod,
329
+ method,
330
+ (original) => function(...args) {
331
+ const desc = describeOutbound(args, scheme);
332
+ const span2 = startSpan(`${desc.method} ${desc.url}`, "http", {
333
+ method: desc.method,
334
+ url: desc.url
335
+ });
336
+ if (!span2) return original.apply(this, args);
337
+ const req = original.apply(this, args);
338
+ let settled = false;
339
+ const finish = (err) => {
340
+ if (settled) return;
341
+ settled = true;
342
+ endSpan(span2, err);
343
+ };
344
+ try {
345
+ req.on("response", (res) => {
346
+ span2.metadata.statusCode = res.statusCode;
347
+ });
348
+ req.on("error", (err) => finish(err));
349
+ req.on("close", () => finish());
350
+ } catch {
351
+ finish();
352
+ }
353
+ return req;
354
+ }
355
+ );
356
+ }
357
+ }
358
+ }
359
+ function describeOutbound(args, scheme) {
360
+ const first = args[0];
361
+ let method = "GET";
362
+ let url = "";
363
+ if (typeof first === "string") {
364
+ url = first;
365
+ } else if (first instanceof URL) {
366
+ url = first.toString();
367
+ } else if (first && typeof first === "object") {
368
+ const host = first.hostname ?? first.host ?? "localhost";
369
+ const path = first.path ?? "/";
370
+ method = first.method ?? "GET";
371
+ url = `${scheme}://${host}${path}`;
372
+ }
373
+ const second = args[1];
374
+ if (second && typeof second === "object" && typeof second.method === "string") {
375
+ method = second.method;
376
+ }
377
+ return { method, url };
378
+ }
379
+
380
+ // src/instruments/pg.ts
381
+ import { createRequire } from "module";
382
+ function patchPgClient(ClientClass) {
383
+ if (!ClientClass?.prototype) return;
384
+ wrap(
385
+ ClientClass.prototype,
386
+ "query",
387
+ (original) => function(...args) {
388
+ const span2 = startSpan(describeQuery(args[0]), "db", { query: extractSql(args[0]) });
389
+ if (!span2) return original.apply(this, args);
390
+ const last = args[args.length - 1];
391
+ if (typeof last === "function") {
392
+ args[args.length - 1] = function(...cbArgs) {
393
+ const [err, result] = cbArgs;
394
+ if (result?.rowCount != null) span2.metadata.rowCount = result.rowCount;
395
+ endSpan(span2, err ?? void 0);
396
+ return last.apply(this, cbArgs);
397
+ };
398
+ return original.apply(this, args);
399
+ }
400
+ const promise = original.apply(this, args);
401
+ if (promise && typeof promise.then === "function") {
402
+ return promise.then(
403
+ (result) => {
404
+ if (result?.rowCount != null) span2.metadata.rowCount = result.rowCount;
405
+ endSpan(span2);
406
+ return result;
407
+ },
408
+ (err) => {
409
+ endSpan(span2, err);
410
+ throw err;
411
+ }
412
+ );
413
+ }
414
+ endSpan(span2);
415
+ return promise;
416
+ }
417
+ );
418
+ }
419
+ function installPg() {
420
+ try {
421
+ const require2 = createRequire(import.meta.url);
422
+ const pg = require2("pg");
423
+ patchPgClient(pg.Client);
424
+ } catch {
425
+ }
426
+ }
427
+ function extractSql(arg) {
428
+ const text = typeof arg === "string" ? arg : arg?.text ?? "";
429
+ return String(text).slice(0, 2e3);
430
+ }
431
+ function describeQuery(arg) {
432
+ const sql = extractSql(arg).trim().replace(/\s+/g, " ");
433
+ const verb = sql.split(" ")[0]?.toUpperCase() ?? "QUERY";
434
+ return `db.${verb.toLowerCase()}`;
435
+ }
436
+
437
+ // src/index.ts
438
+ var activeConfig = null;
439
+ var buffer = null;
440
+ function init(config) {
441
+ if (!config.apiKey) throw new Error("[tracker] `apiKey` is required");
442
+ if (!config.appName) throw new Error("[tracker] `appName` is required");
443
+ activeConfig = config;
444
+ const environment = config.environment ?? process.env["NODE_ENV"] ?? "development";
445
+ const exporter = config.endpoint !== void 0 ? new HttpExporter(config.endpoint, config.apiKey) : new ConsoleExporter();
446
+ buffer = new TraceBuffer(exporter, {
447
+ ...config.maxBatchSize !== void 0 ? { maxSize: config.maxBatchSize } : {},
448
+ ...config.flushIntervalMs !== void 0 ? { flushIntervalMs: config.flushIntervalMs } : {}
449
+ });
450
+ buffer.start();
451
+ configure({
452
+ appName: config.appName,
453
+ environment,
454
+ sampleRate: config.sampleRate ?? 1,
455
+ ignore: config.ignore ?? [],
456
+ sink: (trace) => buffer?.add(trace)
457
+ });
458
+ installHttpServer();
459
+ installHttpClient();
460
+ installPg();
461
+ registerShutdown();
462
+ }
463
+ var shutdownRegistered = false;
464
+ function registerShutdown() {
465
+ if (shutdownRegistered) return;
466
+ shutdownRegistered = true;
467
+ const stop = () => {
468
+ void buffer?.shutdown();
469
+ };
470
+ process.once("beforeExit", stop);
471
+ process.once("SIGTERM", stop);
472
+ process.once("SIGINT", stop);
473
+ }
474
+ async function span(name, fn) {
475
+ return await runInSpan(name, "custom", fn);
476
+ }
477
+ function setTag(key, value) {
478
+ const store = getStore();
479
+ if (store) store.trace.tags[key] = String(value);
480
+ }
481
+ function log(message) {
482
+ const store = getStore();
483
+ if (store?.parent) {
484
+ store.parent.events.push({ timestamp: Date.now(), message });
485
+ }
486
+ }
487
+ async function flush() {
488
+ await buffer?.flush();
489
+ }
490
+ function getConfig() {
491
+ return activeConfig;
492
+ }
493
+ var index_default = { init, span, setTag, log, flush, getConfig };
494
+ export {
495
+ index_default as default,
496
+ flush,
497
+ getConfig,
498
+ init,
499
+ log,
500
+ setTag,
501
+ span
502
+ };
503
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/context.ts","../src/core/tracer.ts","../src/core/ids.ts","../src/core/buffer.ts","../src/transport/console.ts","../src/transport/http.ts","../src/instruments/http.ts","../src/instruments/wrap.ts","../src/instruments/pg.ts","../src/index.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Span, TraceHttpInfo } from '../types.js';\n\n/** A span while it's being built — adds a monotonic start marker we strip on serialize. */\nexport interface InternalSpan extends Span {\n _startMono: number;\n}\n\n/** A trace while it's being built, before serialization to the public {@link Trace}. */\nexport interface InternalTrace {\n traceId: string;\n appName: string;\n environment: string;\n rootSpanId: string;\n startWall: number;\n startMono: number;\n tags: Record<string, string>;\n spans: InternalSpan[];\n http: Partial<TraceHttpInfo>;\n ended: boolean;\n}\n\n/**\n * What we keep in AsyncLocalStorage. `parent` is the span that new child spans\n * attach to in the current async scope (null = attach to the trace root).\n */\nexport interface Store {\n trace: InternalTrace;\n parent: InternalSpan | null;\n}\n\nconst als = new AsyncLocalStorage<Store>();\n\nexport function getStore(): Store | undefined {\n return als.getStore();\n}\n\n/** Run `fn` with `store` as the active context for this async scope and below. */\nexport function runWith<T>(store: Store, fn: () => T): T {\n return als.run(store, fn);\n}\n","import { performance } from 'node:perf_hooks';\nimport { newSpanId, newTraceId } from './ids.js';\nimport { getStore, runWith, type InternalSpan, type InternalTrace } from './context.js';\nimport type { IgnoreRule, Span, SpanError, SpanType, Trace } from '../types.js';\n\ntype Sink = (trace: Trace) => void;\n\ninterface TracerState {\n appName: string;\n environment: string;\n sampleRate: number;\n ignore: IgnoreRule[];\n sink: Sink | null;\n}\n\nlet state: TracerState = {\n appName: 'unknown',\n environment: 'development',\n sampleRate: 1,\n ignore: [],\n sink: null,\n};\n\nexport function configure(patch: Partial<TracerState>): void {\n state = { ...state, ...patch };\n}\n\n/** True if this request should be traced (respects sampleRate + ignore rules). */\nexport function shouldTrace(req: { url?: string }): boolean {\n if (state.sampleRate < 1 && Math.random() > state.sampleRate) return false;\n const path = stripQuery(req.url ?? '');\n for (const rule of state.ignore) {\n if (typeof rule === 'string' ? rule === path : safeRule(rule, req)) return false;\n }\n return true;\n}\n\nexport function createTrace(): InternalTrace {\n return {\n traceId: newTraceId(),\n appName: state.appName,\n environment: state.environment,\n rootSpanId: newSpanId(),\n startWall: Date.now(),\n startMono: performance.now(),\n tags: {},\n spans: [],\n http: {},\n ended: false,\n };\n}\n\n/** Open a child span under the current async scope. Returns null if no active trace. */\nexport function startSpan(\n name: string,\n type: SpanType,\n metadata: Record<string, unknown> = {}\n): InternalSpan | null {\n const store = getStore();\n if (!store) return null;\n const parentId = store.parent ? store.parent.spanId : store.trace.rootSpanId;\n const span: InternalSpan = {\n spanId: newSpanId(),\n parentSpanId: parentId,\n traceId: store.trace.traceId,\n name,\n type,\n startTime: Date.now(),\n endTime: 0,\n duration: 0,\n status: 'ok',\n metadata,\n events: [],\n _startMono: performance.now(),\n };\n store.trace.spans.push(span);\n return span;\n}\n\nexport function endSpan(span: InternalSpan | null, error?: unknown): void {\n if (!span || span.endTime !== 0) return;\n span.duration = performance.now() - span._startMono;\n span.endTime = span.startTime + span.duration;\n if (error !== undefined) {\n span.status = 'error';\n span.error = toSpanError(error);\n }\n}\n\n/**\n * Run `fn` inside a new child span, establishing it as the parent for anything\n * deeper. Times the work and records thrown errors before re-throwing.\n */\nexport async function runInSpan<T>(\n name: string,\n type: SpanType,\n fn: () => Promise<T> | T\n): Promise<T> {\n const store = getStore();\n if (!store) return await fn();\n const span = startSpan(name, type);\n if (!span) return await fn();\n return await runWith({ trace: store.trace, parent: span }, async () => {\n try {\n const result = await fn();\n endSpan(span);\n return result;\n } catch (err) {\n endSpan(span, err);\n throw err;\n }\n });\n}\n\n/** Finalize a trace and hand it to the configured sink. */\nexport function endTrace(trace: InternalTrace, statusCode: number, path: string): void {\n if (trace.ended) return;\n trace.ended = true;\n\n const duration = performance.now() - trace.startMono;\n const hasError = statusCode >= 500 || trace.spans.some((s) => s.status === 'error');\n\n const out: Trace = {\n traceId: trace.traceId,\n appName: trace.appName,\n environment: trace.environment,\n startTime: trace.startWall,\n endTime: trace.startWall + duration,\n duration,\n status: hasError ? 'error' : 'ok',\n http: {\n method: trace.http.method ?? 'GET',\n path,\n rawPath: trace.http.rawPath ?? path,\n statusCode,\n ...(trace.http.userAgent !== undefined ? { userAgent: trace.http.userAgent } : {}),\n },\n tags: trace.tags,\n rootSpanId: trace.rootSpanId,\n spans: trace.spans.map(serializeSpan),\n };\n\n state.sink?.(out);\n}\n\nfunction serializeSpan(span: InternalSpan): Span {\n const { _startMono: _ignored, ...rest } = span;\n void _ignored;\n return rest;\n}\n\nfunction toSpanError(error: unknown): SpanError {\n if (error instanceof Error) {\n return {\n message: error.message,\n stack: error.stack ?? '',\n type: error.name || 'Error',\n };\n }\n return { message: String(error), stack: '', type: 'Error' };\n}\n\nfunction safeRule(rule: (req: unknown) => boolean, req: unknown): boolean {\n try {\n return rule(req);\n } catch {\n return false;\n }\n}\n\nexport function stripQuery(url: string): string {\n const q = url.indexOf('?');\n return q === -1 ? url : url.slice(0, q);\n}\n","import { randomBytes } from 'node:crypto';\n\n/** 128-bit trace id as lowercase hex (32 chars). */\nexport function newTraceId(): string {\n return randomBytes(16).toString('hex');\n}\n\n/** 64-bit span id as lowercase hex (16 chars). */\nexport function newSpanId(): string {\n return randomBytes(8).toString('hex');\n}\n","import type { Exporter } from '../transport/exporter.js';\nimport type { Trace } from '../types.js';\n\nexport interface BufferOptions {\n maxSize: number;\n flushIntervalMs: number;\n}\n\nconst DEFAULTS: BufferOptions = { maxSize: 100, flushIntervalMs: 5000 };\n\n/**\n * In-memory hold for finished traces. Flushes on an interval, when full, or on\n * shutdown. The interval timer is `unref`'d so it never keeps the process alive.\n */\nexport class TraceBuffer {\n private items: Trace[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly opts: BufferOptions;\n\n constructor(\n private readonly exporter: Exporter,\n opts: Partial<BufferOptions> = {}\n ) {\n this.opts = { ...DEFAULTS, ...opts };\n }\n\n start(): void {\n if (this.timer) return;\n this.timer = setInterval(() => void this.flush(), this.opts.flushIntervalMs);\n this.timer.unref?.();\n }\n\n add(trace: Trace): void {\n this.items.push(trace);\n if (this.items.length >= this.opts.maxSize) void this.flush();\n }\n\n async flush(): Promise<void> {\n if (this.items.length === 0) return;\n const batch = this.items;\n this.items = [];\n try {\n await this.exporter.export(batch);\n } catch {\n // Drop on failure — never block or throw into the host app.\n }\n }\n\n async shutdown(): Promise<void> {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush();\n }\n}\n","import type { Exporter } from './exporter.js';\nimport type { Span, Trace } from '../types.js';\n\n/**\n * Dev-friendly exporter: prints each trace as a compact waterfall to stdout.\n * Used by default until an ingest `endpoint` is configured.\n */\nexport class ConsoleExporter implements Exporter {\n export(traces: Trace[]): void {\n for (const trace of traces) {\n this.print(trace);\n }\n }\n\n private print(trace: Trace): void {\n const flag = trace.status === 'error' ? '✗' : '✓';\n const head = `${flag} ${trace.http.method} ${trace.http.path} ${trace.http.statusCode} ${fmt(trace.duration)}`;\n console.log(`\\n[tracker] ${head} (${trace.traceId})`);\n\n const byParent = new Map<string, Span[]>();\n for (const span of trace.spans) {\n const key = span.parentSpanId ?? trace.rootSpanId;\n const list = byParent.get(key) ?? [];\n list.push(span);\n byParent.set(key, list);\n }\n\n const walk = (parentId: string, depth: number): void => {\n const children = (byParent.get(parentId) ?? []).sort((a, b) => a.startTime - b.startTime);\n for (const span of children) {\n const indent = ' '.repeat(depth + 1);\n const mark = span.status === 'error' ? ' ✗' : '';\n console.log(`${indent}${span.type}: ${span.name} ${fmt(span.duration)}${mark}`);\n if (span.error) {\n console.log(`${indent} ↳ ${span.error.type}: ${span.error.message}`);\n }\n walk(span.spanId, depth + 1);\n }\n };\n walk(trace.rootSpanId, 0);\n }\n}\n\nfunction fmt(ms: number): string {\n return ms < 1000 ? `${Math.round(ms)}ms` : `${(ms / 1000).toFixed(2)}s`;\n}\n","import type { Exporter } from './exporter.js';\nimport type { Trace } from '../types.js';\n\n/**\n * Ships traces to the platform ingest endpoint. Fire-and-forget: failures are\n * swallowed so the host app is never affected by tracker transport issues.\n */\nexport class HttpExporter implements Exporter {\n constructor(\n private readonly endpoint: string,\n private readonly apiKey: string,\n private readonly timeoutMs = 3000\n ) {}\n\n async export(traces: Trace[]): Promise<void> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n await fetch(this.endpoint, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({ traces }),\n signal: controller.signal,\n });\n } catch {\n // Never let transport errors bubble into the host application.\n } finally {\n clearTimeout(timer);\n }\n }\n}\n","import http from 'node:http';\nimport https from 'node:https';\nimport { runWith } from '../core/context.js';\nimport {\n createTrace,\n endSpan,\n endTrace,\n shouldTrace,\n startSpan,\n stripQuery,\n} from '../core/tracer.js';\nimport { wrap, type AnyFunction } from './wrap.js';\n\nconst HANDLED = Symbol.for('deeptracker.http.handled');\n\n/**\n * Inbound: every HTTP request becomes a root trace — framework-agnostic, since\n * Express/Fastify/Koa all run on `http.Server`. We patch `Server.prototype.emit`\n * and intercept the synchronous `'request'` event so the whole handler chain\n * (and its async continuations) runs inside our AsyncLocalStorage context.\n */\nexport function installHttpServer(): void {\n const patchServer = (proto: any): void => {\n wrap(\n proto,\n 'emit',\n (emit: AnyFunction) =>\n function (this: unknown, event: string, ...args: any[]) {\n if (event !== 'request') return emit.call(this, event, ...args);\n\n const req = args[0];\n const res = args[1];\n if (!req || !res || req[HANDLED]) return emit.call(this, event, ...args);\n req[HANDLED] = true;\n\n if (!shouldTrace(req)) return emit.call(this, event, ...args);\n\n const trace = createTrace();\n trace.http.method = req.method ?? 'GET';\n trace.http.rawPath = stripQuery(String(req.url ?? '/'));\n const ua = req.headers?.['user-agent'];\n if (typeof ua === 'string') trace.http.userAgent = ua;\n\n return runWith({ trace, parent: null }, () => {\n res.on('finish', () => {\n endTrace(trace, res.statusCode ?? 0, resolvePath(req, trace.http.rawPath ?? '/'));\n });\n return emit.call(this, event, ...args);\n });\n }\n );\n };\n\n patchServer(http.Server.prototype);\n // https.Server has its own prototype; patch it too when present.\n if (https.Server && https.Server.prototype !== http.Server.prototype) {\n patchServer(https.Server.prototype);\n }\n}\n\n/** Prefer Express's parameterized route (`/users/:id`) when available. */\nfunction resolvePath(req: any, fallback: string): string {\n const routePath = req.route?.path;\n if (typeof routePath === 'string') {\n return (req.baseUrl ?? '') + routePath;\n }\n return fallback;\n}\n\n/**\n * Outbound: wrap `request`/`get` on http & https so calls made during a request\n * (axios, fetch-over-http, raw http) show up as child spans.\n */\nexport function installHttpClient(): void {\n for (const [mod, scheme] of [\n [http, 'http'],\n [https, 'https'],\n ] as const) {\n for (const method of ['request', 'get'] as const) {\n wrap(\n mod as any,\n method,\n (original: AnyFunction) =>\n function (this: unknown, ...args: any[]) {\n const desc = describeOutbound(args, scheme);\n const span = startSpan(`${desc.method} ${desc.url}`, 'http', {\n method: desc.method,\n url: desc.url,\n });\n if (!span) return original.apply(this, args);\n\n const req = original.apply(this, args);\n let settled = false;\n const finish = (err?: unknown): void => {\n if (settled) return;\n settled = true;\n endSpan(span, err);\n };\n\n try {\n req.on('response', (res: any) => {\n span.metadata.statusCode = res.statusCode;\n });\n req.on('error', (err: unknown) => finish(err));\n req.on('close', () => finish());\n } catch {\n finish();\n }\n return req;\n }\n );\n }\n }\n}\n\nfunction describeOutbound(args: any[], scheme: string): { method: string; url: string } {\n const first = args[0];\n let method = 'GET';\n let url = '';\n\n if (typeof first === 'string') {\n url = first;\n } else if (first instanceof URL) {\n url = first.toString();\n } else if (first && typeof first === 'object') {\n const host = first.hostname ?? first.host ?? 'localhost';\n const path = first.path ?? '/';\n method = first.method ?? 'GET';\n url = `${scheme}://${host}${path}`;\n }\n\n // (url, options, cb) form: method may live in the 2nd arg.\n const second = args[1];\n if (second && typeof second === 'object' && typeof second.method === 'string') {\n method = second.method;\n }\n\n return { method, url };\n}\n","/* Monkey-patching helpers. Instrumentation inherently fights the type system,\n so `any` is allowed in this folder (see eslint.config.js override). */\n\nexport type AnyFunction = (...args: any[]) => any;\n\nconst WRAPPED = Symbol.for('deeptracker.wrapped');\n\n/**\n * Replace `target[name]` with `factory(original)`, preserving the function name\n * and guarding against double-wrapping (idempotent across multiple `init()`s).\n */\nexport function wrap(\n target: Record<string, any>,\n name: string,\n factory: (original: AnyFunction) => AnyFunction\n): void {\n const original = target[name];\n if (typeof original !== 'function') return;\n if ((original as any)[WRAPPED]) return;\n\n const wrapped = factory(original);\n Object.defineProperty(wrapped, 'name', {\n value: original.name,\n configurable: true,\n });\n (wrapped as any)[WRAPPED] = true;\n (wrapped as any).__original = original;\n target[name] = wrapped;\n}\n","import { createRequire } from 'node:module';\nimport { endSpan, startSpan } from '../core/tracer.js';\nimport { wrap, type AnyFunction } from './wrap.js';\n\n/**\n * Patch a `pg`-style Client class so `.query()` becomes a `db` span. Exported\n * separately from {@link installPg} so tests can pass a fake Client.\n *\n * Supports both the promise and callback forms of `pg.Client#query`.\n */\nexport function patchPgClient(ClientClass: { prototype: Record<string, any> } | undefined): void {\n if (!ClientClass?.prototype) return;\n\n wrap(\n ClientClass.prototype,\n 'query',\n (original: AnyFunction) =>\n function (this: unknown, ...args: any[]) {\n const span = startSpan(describeQuery(args[0]), 'db', { query: extractSql(args[0]) });\n if (!span) return original.apply(this, args);\n\n const last = args[args.length - 1];\n\n // Callback form: query(text, [values], cb)\n if (typeof last === 'function') {\n args[args.length - 1] = function (this: unknown, ...cbArgs: any[]) {\n const [err, result] = cbArgs;\n if (result?.rowCount != null) span.metadata.rowCount = result.rowCount;\n endSpan(span, err ?? undefined);\n return last.apply(this, cbArgs);\n };\n return original.apply(this, args);\n }\n\n // Promise form\n const promise = original.apply(this, args);\n if (promise && typeof promise.then === 'function') {\n return promise.then(\n (result: any) => {\n if (result?.rowCount != null) span.metadata.rowCount = result.rowCount;\n endSpan(span);\n return result;\n },\n (err: unknown) => {\n endSpan(span, err);\n throw err;\n }\n );\n }\n\n endSpan(span);\n return promise;\n }\n );\n}\n\n/** Load the host app's `pg` (if installed) and patch it. No-op when absent. */\nexport function installPg(): void {\n try {\n const require = createRequire(import.meta.url);\n const pg = require('pg') as { Client?: { prototype: Record<string, any> } };\n patchPgClient(pg.Client);\n } catch {\n // pg not installed — nothing to instrument.\n }\n}\n\nfunction extractSql(arg: unknown): string {\n const text = typeof arg === 'string' ? arg : ((arg as any)?.text ?? '');\n return String(text).slice(0, 2000);\n}\n\nfunction describeQuery(arg: unknown): string {\n const sql = extractSql(arg).trim().replace(/\\s+/g, ' ');\n const verb = sql.split(' ')[0]?.toUpperCase() ?? 'QUERY';\n return `db.${verb.toLowerCase()}`;\n}\n","/**\n * @deepeloper/deeptracker — public API surface.\n *\n * Call {@link init} once at your app's entry point, before requiring the\n * frameworks/drivers you want auto-instrumented. Everything else (root traces,\n * outbound HTTP, DB queries) is captured automatically. See PLANNING.md §4.\n */\n\nimport { getStore } from './core/context.js';\nimport { configure, runInSpan } from './core/tracer.js';\nimport { TraceBuffer } from './core/buffer.js';\nimport { ConsoleExporter } from './transport/console.js';\nimport { HttpExporter } from './transport/http.js';\nimport type { Exporter } from './transport/exporter.js';\nimport { installHttpClient, installHttpServer } from './instruments/http.js';\nimport { installPg } from './instruments/pg.js';\nimport type { TrackerConfig } from './types.js';\n\nexport type * from './types.js';\n\nlet activeConfig: TrackerConfig | null = null;\nlet buffer: TraceBuffer | null = null;\n\n/**\n * Initialize the tracker: install instrumentation and start the trace buffer.\n * Idempotent-ish — calling twice re-applies config but won't double-wrap.\n */\nexport function init(config: TrackerConfig): void {\n if (!config.apiKey) throw new Error('[tracker] `apiKey` is required');\n if (!config.appName) throw new Error('[tracker] `appName` is required');\n activeConfig = config;\n\n const environment = config.environment ?? process.env['NODE_ENV'] ?? 'development';\n\n const exporter: Exporter =\n config.endpoint !== undefined\n ? new HttpExporter(config.endpoint, config.apiKey)\n : new ConsoleExporter();\n\n buffer = new TraceBuffer(exporter, {\n ...(config.maxBatchSize !== undefined ? { maxSize: config.maxBatchSize } : {}),\n ...(config.flushIntervalMs !== undefined ? { flushIntervalMs: config.flushIntervalMs } : {}),\n });\n buffer.start();\n\n configure({\n appName: config.appName,\n environment,\n sampleRate: config.sampleRate ?? 1,\n ignore: config.ignore ?? [],\n sink: (trace) => buffer?.add(trace),\n });\n\n installHttpServer();\n installHttpClient();\n installPg();\n\n registerShutdown();\n}\n\nlet shutdownRegistered = false;\nfunction registerShutdown(): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n const stop = (): void => {\n void buffer?.shutdown();\n };\n process.once('beforeExit', stop);\n process.once('SIGTERM', stop);\n process.once('SIGINT', stop);\n}\n\n/** Wrap a unit of work in a manual span so it appears in the trace tree. */\nexport async function span<T>(name: string, fn: () => Promise<T> | T): Promise<T> {\n return await runInSpan(name, 'custom', fn);\n}\n\n/** Attach a tag to the currently active trace (e.g. userId, plan). */\nexport function setTag(key: string, value: string): void {\n const store = getStore();\n if (store) store.trace.tags[key] = String(value);\n}\n\n/** Record a log event inside the current span (no-op outside an active span). */\nexport function log(message: string): void {\n const store = getStore();\n if (store?.parent) {\n store.parent.events.push({ timestamp: Date.now(), message });\n }\n}\n\n/** Force-flush buffered traces. Mainly useful in tests and before shutdown. */\nexport async function flush(): Promise<void> {\n await buffer?.flush();\n}\n\n/** Current config (used by instrumentation modules / introspection). */\nexport function getConfig(): TrackerConfig | null {\n return activeConfig;\n}\n\nexport default { init, span, setTag, log, flush, getConfig };\n"],"mappings":"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","names":["span","span","span","span","require"]}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@deepeloper/deeptracker",
3
+ "version": "0.1.0",
4
+ "description": "Auto-instrumenting deep request tracer for Node.js apps",
5
+ "license": "MIT",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "type": "module",
10
+ "main": "./dist/index.cjs",
11
+ "module": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "require": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "sideEffects": false,
24
+ "engines": {
25
+ "node": ">=20"
26
+ },
27
+ "scripts": {
28
+ "build": "tsup",
29
+ "dev": "tsup --watch",
30
+ "typecheck": "tsc --noEmit",
31
+ "test": "vitest run",
32
+ "prepack": "tsup"
33
+ },
34
+ "keywords": [
35
+ "tracing",
36
+ "observability",
37
+ "logging",
38
+ "apm",
39
+ "express",
40
+ "instrumentation"
41
+ ],
42
+ "devDependencies": {
43
+ "tsup": "^8.3.0",
44
+ "typescript": "^5.6.3",
45
+ "vitest": "^2.1.3"
46
+ }
47
+ }