@nextdog/node 1.0.0 → 1.1.1
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/console-patch.d.ts.map +1 -1
- package/dist/console-patch.js +4 -3
- package/dist/console-patch.js.map +1 -1
- package/dist/exporter.d.ts +5 -1
- package/dist/exporter.d.ts.map +1 -1
- package/dist/exporter.js +42 -4
- package/dist/exporter.js.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/instrument-db.d.ts +17 -0
- package/dist/instrument-db.d.ts.map +1 -0
- package/dist/instrument-db.js +231 -0
- package/dist/instrument-db.js.map +1 -0
- package/dist/instrument-fetch.d.ts +7 -0
- package/dist/instrument-fetch.d.ts.map +1 -0
- package/dist/instrument-fetch.js +107 -0
- package/dist/instrument-fetch.js.map +1 -0
- package/dist/instrumentation.d.ts +21 -0
- package/dist/instrumentation.d.ts.map +1 -0
- package/dist/instrumentation.js +39 -0
- package/dist/instrumentation.js.map +1 -0
- package/dist/request-capture.d.ts +6 -0
- package/dist/request-capture.d.ts.map +1 -1
- package/dist/request-capture.js +172 -9
- package/dist/request-capture.js.map +1 -1
- package/dist/sidecar.d.ts +73 -1
- package/dist/sidecar.d.ts.map +1 -1
- package/dist/sidecar.js +180 -22
- package/dist/sidecar.js.map +1 -1
- package/package.json +6 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console-patch.d.ts","sourceRoot":"","sources":["../src/console-patch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"console-patch.d.ts","sourceRoot":"","sources":["../src/console-patch.ts"],"names":[],"mappings":"AAsEA,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,QA8F5D"}
|
package/dist/console-patch.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { context, trace } from '@opentelemetry/api';
|
|
2
2
|
import { getRequestContext } from './request-context.js';
|
|
3
3
|
const LEVELS = ['debug', 'log', 'info', 'warn', 'error'];
|
|
4
4
|
const LEVEL_MAP = {
|
|
@@ -96,8 +96,9 @@ export function patchConsole(url, serviceName) {
|
|
|
96
96
|
if (typeof firstArg === 'string' && firstArg.startsWith('[nextdog]'))
|
|
97
97
|
return;
|
|
98
98
|
// Skip Next.js internal OTel/RSC noise
|
|
99
|
-
if (typeof firstArg === 'string' &&
|
|
100
|
-
firstArg.includes('
|
|
99
|
+
if (typeof firstArg === 'string' &&
|
|
100
|
+
(firstArg.includes('Unexpected root span type') ||
|
|
101
|
+
firstArg.includes('Failed to fetch RSC payload')))
|
|
101
102
|
return;
|
|
102
103
|
// Try multiple approaches to get the active span context
|
|
103
104
|
// Next.js 14 has less reliable OTel context propagation
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console-patch.js","sourceRoot":"","sources":["../src/console-patch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"console-patch.js","sourceRoot":"","sources":["../src/console-patch.ts"],"names":[],"mappings":"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"}
|
package/dist/exporter.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-node';
|
|
2
1
|
import type { ExportResult } from '@opentelemetry/core';
|
|
2
|
+
import type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-node';
|
|
3
3
|
export declare class NextDogExporter implements SpanExporter {
|
|
4
4
|
private url;
|
|
5
|
+
/** Exact exporter target URLs. NextDog's own outbound POSTs go to these and
|
|
6
|
+
* ONLY these — so we filter exactly them and never collateral user fetches
|
|
7
|
+
* that merely share the sidecar origin or a textual-prefix-sibling port. */
|
|
8
|
+
private readonly selfTargets;
|
|
5
9
|
constructor(url: string);
|
|
6
10
|
private isNextdogSpan;
|
|
7
11
|
export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
|
package/dist/exporter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAmHhF,qBAAa,eAAgB,YAAW,YAAY;IAMtC,OAAO,CAAC,GAAG;IALvB;;iFAE6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;gBAEtB,GAAG,EAAE,MAAM;IAM/B,OAAO,CAAC,aAAa;IASrB,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAiB7E,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAChC"}
|
package/dist/exporter.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import { getRequestMetadata } from './request-capture.js';
|
|
2
2
|
const ExportResultCode = { SUCCESS: 0, FAILED: 1 };
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Headers to never capture. Request cookies ARE kept (under http.request.cookies)
|
|
5
|
+
* because they're needed for replay, but credential-bearing headers — including
|
|
6
|
+
* Set-Cookie on the response side, which mints session secrets — are stripped so
|
|
7
|
+
* they never ship to the sidecar or render in the dashboard.
|
|
8
|
+
*/
|
|
4
9
|
const SKIP_HEADERS = new Set([
|
|
5
|
-
'authorization',
|
|
10
|
+
'authorization',
|
|
11
|
+
'proxy-authorization',
|
|
12
|
+
'x-api-key',
|
|
13
|
+
'x-auth-token',
|
|
14
|
+
'set-cookie',
|
|
15
|
+
'set-cookie2',
|
|
6
16
|
]);
|
|
7
17
|
const SPAN_KIND_MAP = {
|
|
8
18
|
0: 'INTERNAL',
|
|
@@ -49,6 +59,21 @@ function convertSpan(span) {
|
|
|
49
59
|
if (metadata.body) {
|
|
50
60
|
attributes['http.request.body'] = metadata.body;
|
|
51
61
|
}
|
|
62
|
+
// Add the ORIGINAL response (status, headers, body) captured by the tee.
|
|
63
|
+
// This reflects what the request actually returned — no Replay re-issue.
|
|
64
|
+
if (metadata.responseStatus !== undefined) {
|
|
65
|
+
attributes['http.response.status'] = metadata.responseStatus;
|
|
66
|
+
}
|
|
67
|
+
if (metadata.responseHeaders) {
|
|
68
|
+
for (const [key, value] of Object.entries(metadata.responseHeaders)) {
|
|
69
|
+
if (SKIP_HEADERS.has(key.toLowerCase()))
|
|
70
|
+
continue;
|
|
71
|
+
attributes[`http.response.header.${key.toLowerCase()}`] = value;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (metadata.responseBody) {
|
|
75
|
+
attributes['http.response.body'] = metadata.responseBody;
|
|
76
|
+
}
|
|
52
77
|
}
|
|
53
78
|
}
|
|
54
79
|
return {
|
|
@@ -70,17 +95,30 @@ function convertSpan(span) {
|
|
|
70
95
|
}
|
|
71
96
|
export class NextDogExporter {
|
|
72
97
|
url;
|
|
98
|
+
/** Exact exporter target URLs. NextDog's own outbound POSTs go to these and
|
|
99
|
+
* ONLY these — so we filter exactly them and never collateral user fetches
|
|
100
|
+
* that merely share the sidecar origin or a textual-prefix-sibling port. */
|
|
101
|
+
selfTargets;
|
|
73
102
|
constructor(url) {
|
|
74
103
|
this.url = url;
|
|
104
|
+
// Normalize trailing slash so e.g. "http://localhost:6789/" matches too.
|
|
105
|
+
const base = url.replace(/\/+$/, '');
|
|
106
|
+
this.selfTargets = new Set([`${base}/v1/spans`, `${base}/v1/logs`]);
|
|
75
107
|
}
|
|
76
108
|
isNextdogSpan(span) {
|
|
77
109
|
const url = String(span.attributes['http.url'] ?? span.attributes['url.full'] ?? '');
|
|
78
|
-
|
|
110
|
+
if (!url)
|
|
111
|
+
return false;
|
|
112
|
+
// Match the exporter's own POST target exactly (ignoring any query/hash),
|
|
113
|
+
// not arbitrary URLs that merely start with the sidecar origin.
|
|
114
|
+
const withoutQuery = url.split(/[?#]/, 1)[0];
|
|
115
|
+
return this.selfTargets.has(withoutQuery);
|
|
79
116
|
}
|
|
80
117
|
export(spans, resultCallback) {
|
|
81
118
|
const filtered = spans.filter((s) => !this.isNextdogSpan(s));
|
|
82
119
|
if (filtered.length === 0) {
|
|
83
|
-
|
|
120
|
+
resultCallback({ code: ExportResultCode.SUCCESS });
|
|
121
|
+
return;
|
|
84
122
|
}
|
|
85
123
|
const converted = filtered.map(convertSpan);
|
|
86
124
|
fetch(`${this.url}/v1/spans`, {
|
package/dist/exporter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exporter.js","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,gBAAgB,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAW,CAAC;AAE5D
|
|
1
|
+
{"version":3,"file":"exporter.js","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
export { NextDogExporter } from './exporter.js';
|
|
2
|
-
export { ensureSidecar } from './sidecar.js';
|
|
3
1
|
export { patchConsole } from './console-patch.js';
|
|
4
|
-
export {
|
|
2
|
+
export { NextDogExporter } from './exporter.js';
|
|
3
|
+
export { instrumentMysql2Module, instrumentPgModule, registerDbInstrumentation, } from './instrument-db.js';
|
|
4
|
+
export { instrumentOutboundHttp } from './instrument-fetch.js';
|
|
5
|
+
export type { InstrumentationHandle } from './instrumentation.js';
|
|
6
|
+
export { registerInstrumentations } from './instrumentation.js';
|
|
5
7
|
export type { RequestMetadata } from './request-capture.js';
|
|
6
|
-
export {
|
|
8
|
+
export { getRequestMetadata, startRequestCapture } from './request-capture.js';
|
|
7
9
|
export type { RequestContext } from './request-context.js';
|
|
10
|
+
export { createRequestContext, getRequestContext, requestContextStorage, } from './request-context.js';
|
|
11
|
+
export { ensureSidecar } from './sidecar.js';
|
|
8
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC/E,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
export { patchConsole } from './console-patch.js';
|
|
1
2
|
export { NextDogExporter } from './exporter.js';
|
|
3
|
+
export { instrumentMysql2Module, instrumentPgModule, registerDbInstrumentation, } from './instrument-db.js';
|
|
4
|
+
export { instrumentOutboundHttp } from './instrument-fetch.js';
|
|
5
|
+
export { registerInstrumentations } from './instrumentation.js';
|
|
6
|
+
export { getRequestMetadata, startRequestCapture } from './request-capture.js';
|
|
7
|
+
export { createRequestContext, getRequestContext, requestContextStorage, } from './request-context.js';
|
|
2
8
|
export { ensureSidecar } from './sidecar.js';
|
|
3
|
-
export { patchConsole } from './console-patch.js';
|
|
4
|
-
export { startRequestCapture, getRequestMetadata } from './request-capture.js';
|
|
5
|
-
export { requestContextStorage, createRequestContext, getRequestContext, } from './request-context.js';
|
|
6
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE/E,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Instrument a `pg` (node-postgres) module object. Patches Client/Pool query.
|
|
3
|
+
* Returns a restore function. Idempotent per module.
|
|
4
|
+
*/
|
|
5
|
+
export declare function instrumentPgModule(pg: unknown): () => void;
|
|
6
|
+
/**
|
|
7
|
+
* Instrument a `mysql2` module object. Patches Connection/Pool query+execute.
|
|
8
|
+
* Returns a restore function. Idempotent per module.
|
|
9
|
+
*/
|
|
10
|
+
export declare function instrumentMysql2Module(mysql: unknown): () => void;
|
|
11
|
+
/**
|
|
12
|
+
* Lazily load installed DB drivers (dev only) and instrument them. Each import
|
|
13
|
+
* is wrapped in try/catch so a missing driver is simply skipped — no driver is
|
|
14
|
+
* a hard dependency. Returns a combined restore function.
|
|
15
|
+
*/
|
|
16
|
+
export declare function registerDbInstrumentation(): Promise<() => void>;
|
|
17
|
+
//# sourceMappingURL=instrument-db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrument-db.d.ts","sourceRoot":"","sources":["../src/instrument-db.ts"],"names":[],"mappings":"AAgLA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,IAAI,CAE1D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,IAAI,CAEjE;AA2CD;;;;GAIG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,CAcrE"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-dependency auto-instrumentation of DATABASE queries.
|
|
3
|
+
*
|
|
4
|
+
* We do NOT take a hard dependency on `@opentelemetry/instrumentation-pg` /
|
|
5
|
+
* `-mysql2` — those (and the `@opentelemetry/instrumentation` registration
|
|
6
|
+
* machinery they need) are heavyweight runtime deps that would land in every
|
|
7
|
+
* consumer's tree, violating nextdog's zero-runtime-dep design. Instead we
|
|
8
|
+
* monkey-patch the driver's own `query` method when the driver is actually
|
|
9
|
+
* present, the same approach used elsewhere in this package (console, fetch,
|
|
10
|
+
* http.Server). The only thing this needs is `@opentelemetry/api`, already a
|
|
11
|
+
* dependency.
|
|
12
|
+
*
|
|
13
|
+
* Each query becomes a CLIENT span carrying:
|
|
14
|
+
* - db.system ("postgresql" | "mysql")
|
|
15
|
+
* - db.statement (the SQL text)
|
|
16
|
+
* - db.rows_affected (row count, where the driver exposes it)
|
|
17
|
+
* - db.params_count (how many bound params — but NEVER the values)
|
|
18
|
+
* - duration (span start/end)
|
|
19
|
+
*
|
|
20
|
+
* REDACTION: bound parameters frequently contain PII (emails, tokens, ids), so
|
|
21
|
+
* we capture the statement text but ELIDE the param VALUES by default. We only
|
|
22
|
+
* record how many params there were. This is the privacy-preserving default.
|
|
23
|
+
*
|
|
24
|
+
* Parent linkage is automatic: the span is started inside the active OTel
|
|
25
|
+
* context, so it nests under the in-flight request span in the waterfall.
|
|
26
|
+
*/
|
|
27
|
+
import { context, SpanKind, SpanStatusCode, trace } from '@opentelemetry/api';
|
|
28
|
+
const TRACER_NAME = 'nextdog/db';
|
|
29
|
+
const WRAPPED = Symbol.for('nextdog.db.wrapped');
|
|
30
|
+
// Truncate very long statements so a giant generated query can't bloat a span.
|
|
31
|
+
const MAX_STATEMENT_LEN = 4096;
|
|
32
|
+
function statementOf(args) {
|
|
33
|
+
const first = args[0];
|
|
34
|
+
let text;
|
|
35
|
+
if (typeof first === 'string') {
|
|
36
|
+
text = first;
|
|
37
|
+
}
|
|
38
|
+
else if (first && typeof first === 'object') {
|
|
39
|
+
// pg / mysql2 also accept a config object: { text, sql, values }
|
|
40
|
+
const cfg = first;
|
|
41
|
+
text = cfg.text ?? cfg.sql;
|
|
42
|
+
}
|
|
43
|
+
if (!text)
|
|
44
|
+
return '(unknown statement)';
|
|
45
|
+
return text.length > MAX_STATEMENT_LEN ? `${text.slice(0, MAX_STATEMENT_LEN)}…` : text;
|
|
46
|
+
}
|
|
47
|
+
function paramsCountOf(args) {
|
|
48
|
+
// pg: query(text, values, cb) — values is args[1]
|
|
49
|
+
// pg config object: { values: [...] }
|
|
50
|
+
const first = args[0];
|
|
51
|
+
if (first &&
|
|
52
|
+
typeof first === 'object' &&
|
|
53
|
+
Array.isArray(first.values)) {
|
|
54
|
+
return first.values.length;
|
|
55
|
+
}
|
|
56
|
+
if (Array.isArray(args[1]))
|
|
57
|
+
return args[1].length;
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
function rowsAffectedOf(result) {
|
|
61
|
+
if (!result || typeof result !== 'object')
|
|
62
|
+
return undefined;
|
|
63
|
+
const r = result;
|
|
64
|
+
if (typeof r.rowCount === 'number')
|
|
65
|
+
return r.rowCount; // pg
|
|
66
|
+
if (typeof r.affectedRows === 'number')
|
|
67
|
+
return r.affectedRows; // pg-style top-level (defensive)
|
|
68
|
+
// mysql2 returns a tuple: reads are [rows, fields], writes are [ResultSetHeader, undefined].
|
|
69
|
+
if (Array.isArray(result)) {
|
|
70
|
+
const head = result[0];
|
|
71
|
+
if (Array.isArray(head))
|
|
72
|
+
return head.length; // read → row array
|
|
73
|
+
if (head &&
|
|
74
|
+
typeof head === 'object' &&
|
|
75
|
+
typeof head.affectedRows === 'number') {
|
|
76
|
+
return head.affectedRows; // write → ResultSetHeader
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (Array.isArray(r.rows))
|
|
80
|
+
return r.rows.length;
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Wrap a single `query`-style method on a prototype to emit a span per call.
|
|
85
|
+
* Handles both promise-returning and callback-style invocations.
|
|
86
|
+
*/
|
|
87
|
+
function wrapQueryMethod(proto, methodName, dbSystem) {
|
|
88
|
+
const original = proto[methodName];
|
|
89
|
+
if (typeof original !== 'function')
|
|
90
|
+
return;
|
|
91
|
+
const tracer = trace.getTracer(TRACER_NAME);
|
|
92
|
+
const wrapped = function (...args) {
|
|
93
|
+
const statement = statementOf(args);
|
|
94
|
+
const paramsCount = paramsCountOf(args);
|
|
95
|
+
const span = tracer.startSpan(statement, {
|
|
96
|
+
kind: SpanKind.CLIENT,
|
|
97
|
+
attributes: {
|
|
98
|
+
'db.system': dbSystem,
|
|
99
|
+
'db.statement': statement,
|
|
100
|
+
// Bound params are deliberately elided (PII). Only the count is recorded.
|
|
101
|
+
...(paramsCount !== undefined ? { 'db.params_count': paramsCount } : {}),
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
const ctx = trace.setSpan(context.active(), span);
|
|
105
|
+
const finishOk = (result) => {
|
|
106
|
+
const rows = rowsAffectedOf(result);
|
|
107
|
+
if (rows !== undefined)
|
|
108
|
+
span.setAttribute('db.rows_affected', rows);
|
|
109
|
+
span.end();
|
|
110
|
+
};
|
|
111
|
+
const finishErr = (err) => {
|
|
112
|
+
span.recordException(err);
|
|
113
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: err?.message });
|
|
114
|
+
span.end();
|
|
115
|
+
};
|
|
116
|
+
// If the caller passed a callback (last arg is a function), wrap it.
|
|
117
|
+
const lastArg = args[args.length - 1];
|
|
118
|
+
if (typeof lastArg === 'function') {
|
|
119
|
+
const cb = lastArg;
|
|
120
|
+
args[args.length - 1] = function (err, result, ...rest) {
|
|
121
|
+
if (err)
|
|
122
|
+
finishErr(err);
|
|
123
|
+
else
|
|
124
|
+
finishOk(result);
|
|
125
|
+
return cb.call(this, err, result, ...rest);
|
|
126
|
+
};
|
|
127
|
+
return context.with(ctx, () => original.apply(this, args));
|
|
128
|
+
}
|
|
129
|
+
// Otherwise treat the return value as a thenable (promise) or sync value.
|
|
130
|
+
return context.with(ctx, () => {
|
|
131
|
+
let result;
|
|
132
|
+
try {
|
|
133
|
+
result = original.apply(this, args);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
finishErr(err);
|
|
137
|
+
throw err;
|
|
138
|
+
}
|
|
139
|
+
if (result && typeof result.then === 'function') {
|
|
140
|
+
return result.then((res) => {
|
|
141
|
+
finishOk(res);
|
|
142
|
+
return res;
|
|
143
|
+
}, (err) => {
|
|
144
|
+
finishErr(err);
|
|
145
|
+
throw err;
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
finishOk(result);
|
|
149
|
+
return result;
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
proto[methodName] = wrapped;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Instrument a `pg` (node-postgres) module object. Patches Client/Pool query.
|
|
156
|
+
* Returns a restore function. Idempotent per module.
|
|
157
|
+
*/
|
|
158
|
+
export function instrumentPgModule(pg) {
|
|
159
|
+
return instrumentDriverModule(pg, 'postgresql', ['Client', 'Pool']);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Instrument a `mysql2` module object. Patches Connection/Pool query+execute.
|
|
163
|
+
* Returns a restore function. Idempotent per module.
|
|
164
|
+
*/
|
|
165
|
+
export function instrumentMysql2Module(mysql) {
|
|
166
|
+
return instrumentDriverModule(mysql, 'mysql', ['Connection', 'Pool'], ['query', 'execute']);
|
|
167
|
+
}
|
|
168
|
+
function instrumentDriverModule(mod, dbSystem, ctorNames, methods = ['query']) {
|
|
169
|
+
if (!mod || typeof mod !== 'object')
|
|
170
|
+
return () => { };
|
|
171
|
+
const patched = [];
|
|
172
|
+
for (const ctorName of ctorNames) {
|
|
173
|
+
const ctor = mod[ctorName];
|
|
174
|
+
const proto = ctor?.prototype;
|
|
175
|
+
if (!proto || proto[WRAPPED])
|
|
176
|
+
continue;
|
|
177
|
+
const originals = {};
|
|
178
|
+
for (const m of methods) {
|
|
179
|
+
if (typeof proto[m] === 'function') {
|
|
180
|
+
originals[m] = proto[m];
|
|
181
|
+
wrapQueryMethod(proto, m, dbSystem);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
proto[WRAPPED] = true;
|
|
185
|
+
patched.push({ proto, originals });
|
|
186
|
+
}
|
|
187
|
+
return () => {
|
|
188
|
+
for (const { proto, originals } of patched) {
|
|
189
|
+
for (const [m, fn] of Object.entries(originals)) {
|
|
190
|
+
proto[m] = fn;
|
|
191
|
+
}
|
|
192
|
+
delete proto[WRAPPED];
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Lazily load installed DB drivers (dev only) and instrument them. Each import
|
|
198
|
+
* is wrapped in try/catch so a missing driver is simply skipped — no driver is
|
|
199
|
+
* a hard dependency. Returns a combined restore function.
|
|
200
|
+
*/
|
|
201
|
+
export async function registerDbInstrumentation() {
|
|
202
|
+
const restores = [];
|
|
203
|
+
// node-postgres
|
|
204
|
+
const pg = await optionalImport('pg');
|
|
205
|
+
if (pg)
|
|
206
|
+
restores.push(instrumentPgModule(pg));
|
|
207
|
+
// mysql2
|
|
208
|
+
const mysql = await optionalImport('mysql2');
|
|
209
|
+
if (mysql)
|
|
210
|
+
restores.push(instrumentMysql2Module(mysql));
|
|
211
|
+
return () => {
|
|
212
|
+
for (const r of restores)
|
|
213
|
+
r();
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Import an OPTIONAL driver. The specifier is held in a variable so TypeScript
|
|
218
|
+
* does not try to resolve it at build time (it is not a dependency), and any
|
|
219
|
+
* resolution failure at runtime resolves to `undefined` — the driver is simply
|
|
220
|
+
* absent and skipped. This is what keeps the DB feature zero-dependency.
|
|
221
|
+
*/
|
|
222
|
+
async function optionalImport(specifier) {
|
|
223
|
+
try {
|
|
224
|
+
const mod = (await import(/* @vite-ignore */ specifier));
|
|
225
|
+
return mod.default ?? mod;
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=instrument-db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrument-db.js","sourceRoot":"","sources":["../src/instrument-db.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrap the global `fetch` so each call emits a CLIENT span. Returns a restore
|
|
3
|
+
* function that puts the original `fetch` back (used in tests / teardown).
|
|
4
|
+
* Idempotent: a second call is a no-op and returns a no-op restore.
|
|
5
|
+
*/
|
|
6
|
+
export declare function instrumentOutboundHttp(): () => void;
|
|
7
|
+
//# sourceMappingURL=instrument-fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrument-fetch.d.ts","sourceRoot":"","sources":["../src/instrument-fetch.ts"],"names":[],"mappings":"AAgDA;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,IAAI,CAkEnD"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-dependency auto-instrumentation of OUTBOUND HTTP made via the global
|
|
3
|
+
* `fetch` (undici under the hood in Node 18+). When a route handler calls
|
|
4
|
+
* `fetch('https://api.stripe.com/...')`, this wraps the call in an OTel CLIENT
|
|
5
|
+
* span carrying `http.url`, `http.method`, `http.status_code` and a duration.
|
|
6
|
+
*
|
|
7
|
+
* Parent linkage is automatic: `tracer.startSpan` (run inside the active
|
|
8
|
+
* context via `context.with`) parents the new span to whatever request span is
|
|
9
|
+
* active on the OTel context stack, so the call nests correctly under the
|
|
10
|
+
* incoming-request span in the waterfall — no `parentSpanId` plumbing needed.
|
|
11
|
+
*
|
|
12
|
+
* We deliberately patch `fetch` ourselves rather than depend on
|
|
13
|
+
* `@opentelemetry/instrumentation-undici`/`-http`. Those are heavyweight
|
|
14
|
+
* runtime deps that would land in every consumer's tree; we already depend on
|
|
15
|
+
* `@opentelemetry/api`, which is all this needs.
|
|
16
|
+
*/
|
|
17
|
+
import { context, SpanKind, SpanStatusCode, trace } from '@opentelemetry/api';
|
|
18
|
+
const TRACER_NAME = 'nextdog/outbound-http';
|
|
19
|
+
// Marker so we never double-wrap (e.g. registered twice across HMR reloads).
|
|
20
|
+
const WRAPPED = Symbol.for('nextdog.fetch.wrapped');
|
|
21
|
+
function urlOf(input) {
|
|
22
|
+
try {
|
|
23
|
+
if (typeof input === 'string')
|
|
24
|
+
return input;
|
|
25
|
+
if (input instanceof URL)
|
|
26
|
+
return input.toString();
|
|
27
|
+
// Request object
|
|
28
|
+
return input.url ?? String(input);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return String(input);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function methodOf(input, init) {
|
|
35
|
+
if (init?.method)
|
|
36
|
+
return init.method.toUpperCase();
|
|
37
|
+
try {
|
|
38
|
+
if (input && typeof input === 'object' && 'method' in input && input.method) {
|
|
39
|
+
return input.method.toUpperCase();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
/* ignore */
|
|
44
|
+
}
|
|
45
|
+
return 'GET';
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Wrap the global `fetch` so each call emits a CLIENT span. Returns a restore
|
|
49
|
+
* function that puts the original `fetch` back (used in tests / teardown).
|
|
50
|
+
* Idempotent: a second call is a no-op and returns a no-op restore.
|
|
51
|
+
*/
|
|
52
|
+
export function instrumentOutboundHttp() {
|
|
53
|
+
const original = globalThis.fetch;
|
|
54
|
+
if (!original)
|
|
55
|
+
return () => { };
|
|
56
|
+
if (original[WRAPPED])
|
|
57
|
+
return () => { };
|
|
58
|
+
const tracer = trace.getTracer(TRACER_NAME);
|
|
59
|
+
const wrapped = function nextdogFetch(input, init) {
|
|
60
|
+
const url = urlOf(input);
|
|
61
|
+
const method = methodOf(input, init);
|
|
62
|
+
const span = tracer.startSpan(`${method} ${url}`, {
|
|
63
|
+
kind: SpanKind.CLIENT,
|
|
64
|
+
attributes: {
|
|
65
|
+
'http.url': url,
|
|
66
|
+
'http.method': method,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
// Run the call inside the span's context so any further nested work
|
|
70
|
+
// (and the span itself) link correctly in the trace.
|
|
71
|
+
const ctx = trace.setSpan(context.active(), span);
|
|
72
|
+
return context.with(ctx, () => {
|
|
73
|
+
let result;
|
|
74
|
+
try {
|
|
75
|
+
result = original.call(this, input, init);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
// Synchronous throw (rare for fetch, but be safe).
|
|
79
|
+
span.recordException(err);
|
|
80
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: err?.message });
|
|
81
|
+
span.end();
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
return result.then((res) => {
|
|
85
|
+
span.setAttribute('http.status_code', res.status);
|
|
86
|
+
if (res.status >= 400) {
|
|
87
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: `HTTP ${res.status}` });
|
|
88
|
+
}
|
|
89
|
+
span.end();
|
|
90
|
+
return res;
|
|
91
|
+
}, (err) => {
|
|
92
|
+
span.recordException(err);
|
|
93
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: err?.message });
|
|
94
|
+
span.end();
|
|
95
|
+
throw err;
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
wrapped[WRAPPED] = true;
|
|
100
|
+
globalThis.fetch = wrapped;
|
|
101
|
+
return () => {
|
|
102
|
+
if (globalThis.fetch === wrapped) {
|
|
103
|
+
globalThis.fetch = original;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=instrument-fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrument-fetch.js","sourceRoot":"","sources":["../src/instrument-fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single entry point an adapter calls (after `provider.register()`) to turn on
|
|
3
|
+
* all of nextdog's auto-instrumentations:
|
|
4
|
+
* - outbound fetch/HTTP (#4) — zero new deps, always on
|
|
5
|
+
* - database queries (#5) — zero new deps, only patches a driver that is
|
|
6
|
+
* actually installed (pg / mysql2)
|
|
7
|
+
*
|
|
8
|
+
* Everything here uses only `@opentelemetry/api` plus optional, lazily-loaded
|
|
9
|
+
* drivers, so nothing new ships in a consumer's production bundle.
|
|
10
|
+
*/
|
|
11
|
+
export interface InstrumentationHandle {
|
|
12
|
+
/** Restore all patched globals/drivers (used in tests / teardown). */
|
|
13
|
+
restore: () => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Register outbound-HTTP and DB instrumentation. Safe to call once at startup.
|
|
17
|
+
* Returns a handle whose `restore()` undoes every patch. DB drivers load
|
|
18
|
+
* asynchronously; if a driver isn't installed it is silently skipped.
|
|
19
|
+
*/
|
|
20
|
+
export declare function registerInstrumentations(): InstrumentationHandle;
|
|
21
|
+
//# sourceMappingURL=instrumentation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../src/instrumentation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,qBAAqB,CAsBhE"}
|