@rootcat/node 0.0.0-stage → 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.
Files changed (63) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/LICENSE +202 -0
  3. package/README.md +294 -2
  4. package/dist/attach.d.ts +1 -0
  5. package/dist/attach.js +24 -0
  6. package/dist/attach.js.map +1 -0
  7. package/dist/callsite.d.ts +109 -0
  8. package/dist/callsite.js +565 -0
  9. package/dist/callsite.js.map +1 -0
  10. package/dist/coexist.d.ts +183 -0
  11. package/dist/coexist.js +587 -0
  12. package/dist/coexist.js.map +1 -0
  13. package/dist/config.d.ts +75 -0
  14. package/dist/config.js +182 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/drizzle.d.ts +21 -0
  17. package/dist/drizzle.js +127 -0
  18. package/dist/drizzle.js.map +1 -0
  19. package/dist/esm.mjs +57 -0
  20. package/dist/esmhook.d.ts +52 -0
  21. package/dist/esmhook.js +158 -0
  22. package/dist/esmhook.js.map +1 -0
  23. package/dist/iitm-hook.mjs +83 -0
  24. package/dist/index.d.ts +12 -0
  25. package/dist/index.js +52 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/intake.d.ts +40 -0
  28. package/dist/intake.js +164 -0
  29. package/dist/intake.js.map +1 -0
  30. package/dist/keys.d.ts +20 -0
  31. package/dist/keys.js +33 -0
  32. package/dist/keys.js.map +1 -0
  33. package/dist/notices.d.ts +2 -0
  34. package/dist/notices.js +21 -0
  35. package/dist/notices.js.map +1 -0
  36. package/dist/otlp.d.ts +75 -0
  37. package/dist/otlp.js +449 -0
  38. package/dist/otlp.js.map +1 -0
  39. package/dist/pg.d.ts +16 -0
  40. package/dist/pg.js +170 -0
  41. package/dist/pg.js.map +1 -0
  42. package/dist/pgpool.d.ts +20 -0
  43. package/dist/pgpool.js +99 -0
  44. package/dist/pgpool.js.map +1 -0
  45. package/dist/postgresjs.d.ts +60 -0
  46. package/dist/postgresjs.js +400 -0
  47. package/dist/postgresjs.js.map +1 -0
  48. package/dist/privacy.d.ts +38 -0
  49. package/dist/privacy.js +161 -0
  50. package/dist/privacy.js.map +1 -0
  51. package/dist/processor.d.ts +197 -0
  52. package/dist/processor.js +494 -0
  53. package/dist/processor.js.map +1 -0
  54. package/dist/register.d.ts +1 -0
  55. package/dist/register.js +12 -0
  56. package/dist/register.js.map +1 -0
  57. package/dist/sampler.d.ts +30 -0
  58. package/dist/sampler.js +101 -0
  59. package/dist/sampler.js.map +1 -0
  60. package/dist/sdk.d.ts +129 -0
  61. package/dist/sdk.js +606 -0
  62. package/dist/sdk.js.map +1 -0
  63. package/package.json +72 -4
package/dist/pg.js ADDED
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PgInstrumentation = void 0;
4
+ // pg (node-postgres): one span per query, nothing else. The upstream
5
+ // instrumentation starts a span for every pool acquire beside the query,
6
+ // another per connection, records metrics and a dozen attributes, and
7
+ // costs about three times what the query span itself does (see the
8
+ // benchmark); the agent counts operations and keeps error events, so
9
+ // one client span with the statement, the database and the server is
10
+ // what it needs. Client.prototype.query is patched (pool.query goes
11
+ // through it); a submittable (a cursor or a stream) passes through
12
+ // untraced; parameter values are never read.
13
+ const api_1 = require("@opentelemetry/api");
14
+ const instrumentation_1 = require("@opentelemetry/instrumentation");
15
+ const callsite_js_1 = require("./callsite.js");
16
+ const keys_js_1 = require("./keys.js");
17
+ const privacy_js_1 = require("./privacy.js");
18
+ const processor_js_1 = require("./processor.js");
19
+ const maxStatementBytes = 4096;
20
+ const supportedVersions = ['>=8.0.0 <9'];
21
+ class PgInstrumentation extends instrumentation_1.InstrumentationBase {
22
+ constructor(options) {
23
+ super('@rootcat/node/pg', '0.2.0', options);
24
+ }
25
+ init() {
26
+ return new instrumentation_1.InstrumentationNodeModuleDefinition('pg', supportedVersions, (moduleExports) => {
27
+ const proto = clientPrototype(moduleExports);
28
+ if (proto) {
29
+ if ((0, instrumentation_1.isWrapped)(proto.query) && (0, keys_js_1.mine)(proto.query)) {
30
+ this._unwrap(proto, 'query');
31
+ }
32
+ const before = proto.query;
33
+ this._wrap(proto, 'query', this.wrapQuery);
34
+ if (proto.query !== before) {
35
+ (0, keys_js_1.marked)(proto.query); // not when a guard kept another SDK's wrapper
36
+ }
37
+ }
38
+ return moduleExports;
39
+ }, (moduleExports) => {
40
+ const proto = clientPrototype(moduleExports);
41
+ if (proto && (0, instrumentation_1.isWrapped)(proto.query) && (0, keys_js_1.mine)(proto.query)) {
42
+ this._unwrap(proto, 'query');
43
+ }
44
+ });
45
+ }
46
+ wrapQuery = (original) => {
47
+ const instrumentation = this;
48
+ return function query(...args) {
49
+ const [config, values, callback] = args;
50
+ if (config && typeof config.submit === 'function') {
51
+ return original.apply(this, args); // a cursor or a stream: not a query with an end
52
+ }
53
+ const outer = api_1.context.active();
54
+ let span;
55
+ let parent = outer;
56
+ try {
57
+ const options = instrumentation.getConfig();
58
+ parent = options.sampling.carry(() => (0, callsite_js_1.captureCallSite)(options.depth, options.isApp, query)) ?? outer;
59
+ if ((0, processor_js_1.unsampled)(parent)) {
60
+ return original.apply(this, args); // not recorded: nothing to start or carry
61
+ }
62
+ span = instrumentation.startQuerySpan(this, config, parent);
63
+ }
64
+ catch {
65
+ span = undefined;
66
+ }
67
+ if (!span) {
68
+ return original.apply(this, args);
69
+ }
70
+ const end = instrumentation.endQuerySpan.bind(instrumentation, span);
71
+ // The callback may be the second or third argument, or on the config.
72
+ // It continues in the caller's context, not the query's.
73
+ let callArgs = args;
74
+ const userCallback = typeof values === 'function' ? values : typeof callback === 'function' ? callback : config?.callback;
75
+ if (typeof userCallback === 'function') {
76
+ const wrapped = api_1.context.bind(outer, function (error, result) {
77
+ end(error);
78
+ return userCallback.call(this, error, result);
79
+ });
80
+ if (typeof values === 'function') {
81
+ callArgs = [config, wrapped];
82
+ }
83
+ else if (typeof callback === 'function') {
84
+ callArgs = [config, values, wrapped];
85
+ }
86
+ else {
87
+ // A config may be a class instance whose text or values are
88
+ // getters on its prototype: the callback goes on an object that
89
+ // inherits from it, not on a copy of its own fields.
90
+ const withCallback = Object.create(config);
91
+ withCallback.callback = wrapped;
92
+ callArgs = [withCallback, values, callback];
93
+ }
94
+ }
95
+ const active = api_1.trace.setSpan(parent, span);
96
+ let result;
97
+ try {
98
+ result = api_1.context.with(active, () => original.apply(this, callArgs));
99
+ }
100
+ catch (error) {
101
+ end(error);
102
+ throw error;
103
+ }
104
+ if (typeof userCallback !== 'function') {
105
+ if (result && typeof result.then === 'function') {
106
+ result.then(() => end(undefined), (error) => end(error ?? new Error('query failed')));
107
+ }
108
+ else {
109
+ end(undefined);
110
+ }
111
+ }
112
+ return result;
113
+ };
114
+ };
115
+ startQuerySpan(client, config, parent) {
116
+ const text = typeof config === 'string' ? config : typeof config?.text === 'string' ? config.text : '';
117
+ const keyword = (0, privacy_js_1.statementKeyword)(text);
118
+ const attributes = { 'db.system.name': 'postgresql' };
119
+ if (keyword !== '') {
120
+ attributes['db.operation.name'] = keyword;
121
+ }
122
+ if (text !== '') {
123
+ // Literals are masked (or the text reduced to its keyword) by the
124
+ // processor's statement rule as the span starts.
125
+ attributes['db.query.text'] = text.slice(0, maxStatementBytes);
126
+ }
127
+ if (typeof client.database === 'string') {
128
+ attributes['db.namespace'] = client.database;
129
+ }
130
+ if (typeof client.host === 'string') {
131
+ attributes['server.address'] = client.host;
132
+ }
133
+ if (typeof client.port === 'number') {
134
+ attributes['server.port'] = client.port;
135
+ }
136
+ return this.tracer.startSpan(keyword === '' ? 'pg.query' : `pg.query:${keyword}`, { kind: api_1.SpanKind.CLIENT, attributes }, parent);
137
+ }
138
+ endQuerySpan(span, error) {
139
+ try {
140
+ if (error !== undefined && error !== null) {
141
+ // The server's message can quote the input that failed; only the
142
+ // error's class and SQLSTATE travel.
143
+ const e = error;
144
+ const generic = typeof e.name !== 'string' || e.name === '' || e.name === 'Error' || e.name === 'error';
145
+ const name = (generic ? e.constructor?.name : e.name) || 'Error';
146
+ const code = typeof e.code === 'string' ? e.code.slice(0, 16) : '';
147
+ const message = code === '' ? `${name} from pg` : `${name} from pg (code: ${code})`;
148
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message });
149
+ span.addEvent('exception', { 'exception.type': name.slice(0, 64), 'exception.message': message });
150
+ span.setAttribute('error.type', name.slice(0, 64));
151
+ if (code !== '') {
152
+ span.setAttribute('db.response.status_code', code);
153
+ }
154
+ }
155
+ }
156
+ catch {
157
+ // the span still ends
158
+ }
159
+ finally {
160
+ span.end();
161
+ }
162
+ }
163
+ }
164
+ exports.PgInstrumentation = PgInstrumentation;
165
+ function clientPrototype(moduleExports) {
166
+ const mod = moduleExports;
167
+ const proto = mod?.Client?.prototype;
168
+ return proto && typeof proto.query === 'function' ? proto : undefined;
169
+ }
170
+ //# sourceMappingURL=pg.js.map
package/dist/pg.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg.js","sourceRoot":"","sources":["../src/pg.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { InstrumentationBase, type InstrumentationConfig, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';
2
+ import { type CallSiteSampling } from './processor.js';
3
+ /** PgPoolEntryOptions bounds and gates the capture. */
4
+ export interface PgPoolEntryOptions extends InstrumentationConfig {
5
+ depth: number;
6
+ sampling: CallSiteSampling;
7
+ isApp?: (file: string) => boolean;
8
+ /**
9
+ * connect false leaves Pool.prototype.connect alone: inside a tracing
10
+ * Sentry, whose pg instrumentation spans the pool's connect under the
11
+ * caller's span (and drops it without one), the root context the
12
+ * package runs connect in would change Sentry's spans.
13
+ */
14
+ connect?: boolean;
15
+ }
16
+ export declare class PgPoolEntryInstrumentation extends InstrumentationBase<PgPoolEntryOptions> {
17
+ constructor(options: PgPoolEntryOptions);
18
+ protected init(): InstrumentationNodeModuleDefinition;
19
+ private readonly wrapQuery;
20
+ }
package/dist/pgpool.js ADDED
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PgPoolEntryInstrumentation = void 0;
4
+ // pg-pool entry. Pool.prototype.query hands the query to a client on a
5
+ // later tick, so the pg query span's stack never shows the caller: this
6
+ // wrapper captures the call site where the application calls pool.query
7
+ // and carries it in the active context to the span that starts later.
8
+ //
9
+ // Pool.prototype.connect queues its callback when every client is busy
10
+ // and runs it from the release of another client, in that client's
11
+ // query's context. Its callback is bound to the context of the connect
12
+ // call, so a queued query keeps its own call site and its own parent
13
+ // instead of borrowing the query that freed the client.
14
+ const api_1 = require("@opentelemetry/api");
15
+ const instrumentation_1 = require("@opentelemetry/instrumentation");
16
+ const callsite_js_1 = require("./callsite.js");
17
+ const keys_js_1 = require("./keys.js");
18
+ const processor_js_1 = require("./processor.js");
19
+ function poolPrototype(moduleExports) {
20
+ const proto = moduleExports?.prototype;
21
+ return proto && typeof proto.query === 'function' && typeof proto.connect === 'function' ? proto : undefined;
22
+ }
23
+ class PgPoolEntryInstrumentation extends instrumentation_1.InstrumentationBase {
24
+ constructor(options) {
25
+ super('@rootcat/node/pg-pool-entry', '0.2.0', options);
26
+ }
27
+ init() {
28
+ return new instrumentation_1.InstrumentationNodeModuleDefinition('pg-pool', ['>=2.0.0 <4'], (moduleExports) => {
29
+ const proto = poolPrototype(moduleExports);
30
+ if (proto) {
31
+ for (const name of ['query', 'connect']) {
32
+ if ((0, instrumentation_1.isWrapped)(proto[name]) && (0, keys_js_1.mine)(proto[name])) {
33
+ this._unwrap(proto, name);
34
+ }
35
+ }
36
+ const beforeQuery = proto.query;
37
+ this._wrap(proto, 'query', this.wrapQuery);
38
+ if (proto.query !== beforeQuery) {
39
+ (0, keys_js_1.marked)(proto.query); // not when a guard kept another SDK's wrapper
40
+ }
41
+ if (this.getConfig().connect !== false) {
42
+ const beforeConnect = proto.connect;
43
+ this._wrap(proto, 'connect', wrapConnect);
44
+ if (proto.connect !== beforeConnect) {
45
+ (0, keys_js_1.marked)(proto.connect);
46
+ }
47
+ }
48
+ }
49
+ return moduleExports;
50
+ }, (moduleExports) => {
51
+ const proto = poolPrototype(moduleExports);
52
+ if (proto) {
53
+ for (const name of ['query', 'connect']) {
54
+ if ((0, instrumentation_1.isWrapped)(proto[name]) && (0, keys_js_1.mine)(proto[name])) {
55
+ this._unwrap(proto, name);
56
+ }
57
+ }
58
+ }
59
+ });
60
+ }
61
+ wrapQuery = (original) => {
62
+ const instrumentation = this;
63
+ return function query(...args) {
64
+ let carried;
65
+ try {
66
+ // A callback continues in the caller's context, never in the
67
+ // query's: a query issued from it captures its own site.
68
+ const last = args.length - 1;
69
+ if (last >= 0 && typeof args[last] === 'function') {
70
+ args[last] = api_1.context.bind(api_1.context.active(), args[last]);
71
+ }
72
+ const config = instrumentation.getConfig();
73
+ carried = config.sampling.carry(() => (0, callsite_js_1.captureCallSite)(config.depth, config.isApp, query));
74
+ }
75
+ catch {
76
+ carried = undefined;
77
+ }
78
+ return (0, processor_js_1.runCarried)(carried, () => original.apply(this, args));
79
+ };
80
+ };
81
+ }
82
+ exports.PgPoolEntryInstrumentation = PgPoolEntryInstrumentation;
83
+ /**
84
+ * wrapConnect binds a connect callback to the context of the call, and
85
+ * runs the pool's own work (opening a client and its socket) in the root
86
+ * context: a connection outlives the query that opened it, and the events
87
+ * it emits later (a LISTEN notification, an error) must not run in that
88
+ * query's context, with its span and call site.
89
+ */
90
+ function wrapConnect(original) {
91
+ return function connect(...args) {
92
+ const callback = args[0];
93
+ if (typeof callback === 'function') {
94
+ args[0] = api_1.context.bind(api_1.context.active(), callback);
95
+ }
96
+ return api_1.context.with(api_1.ROOT_CONTEXT, () => original.apply(this, args));
97
+ };
98
+ }
99
+ //# sourceMappingURL=pgpool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pgpool.js","sourceRoot":"","sources":["../src/pgpool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { InstrumentationBase, type InstrumentationConfig, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';
2
+ import { type CallSiteLocation } from './callsite.js';
3
+ import { type CallSiteSampling } from './processor.js';
4
+ /** PostgresJsOptions configures the instrumentation. */
5
+ export interface PostgresJsOptions extends InstrumentationConfig {
6
+ /** sampling gates the origin parsing, like any capture. */
7
+ sampling: CallSiteSampling;
8
+ /**
9
+ * spans false starts no span: another SDK (Sentry, tracing on) has
10
+ * already started one for the query when handle() runs, and onSite is
11
+ * handed the query's origin to give that span its call site.
12
+ */
13
+ spans?: boolean;
14
+ /** onSite receives a query's call site when spans is false. */
15
+ onSite?: (site: CallSiteLocation) => void;
16
+ }
17
+ export declare class PostgresJsInstrumentation extends InstrumentationBase<PostgresJsOptions> {
18
+ private readonly patched;
19
+ /** origins remembers the parsed call site per template, null for none. */
20
+ private readonly origins;
21
+ /** recording maps a sql function to its site-recording proxy (spans false). */
22
+ private readonly recording;
23
+ /** templateSites remembers the captured call site per template (spans false). */
24
+ private readonly templateSites;
25
+ /** querySites holds the call site captured for a query until it is handled (spans false). */
26
+ private readonly querySites;
27
+ constructor(options: PostgresJsOptions);
28
+ protected init(): InstrumentationNodeModuleDefinition;
29
+ /**
30
+ * patchModule wraps the factory. CommonJS exports the function itself
31
+ * (the wrapper is returned in its place); an ES module namespace has it
32
+ * as default (replaced in place).
33
+ */
34
+ private patchModule;
35
+ private unpatchModule;
36
+ private wrapFactory;
37
+ /**
38
+ * siteRecording is the sql function as the application gets it when
39
+ * another SDK (Sentry) spans the queries: the driver's own origin then
40
+ * cannot name the application, as it keeps four frames and Sentry's
41
+ * wrapper of the sql function takes the last one. The call site is
42
+ * captured here instead, where the application calls: once per tagged
43
+ * template (a template is one place in the source, as the driver's own
44
+ * origin cache assumes), and per unsafe() call unless an outer layer
45
+ * (Drizzle) already carries one; queries inside sql.begin() get the
46
+ * same treatment through the transaction's sql function.
47
+ */
48
+ private siteRecording;
49
+ /** patchQueryClass finds Query.prototype through an unexecuted query. */
50
+ private patchQueryClass;
51
+ private readonly wrapHandle;
52
+ /**
53
+ * originSite is the application frame of the driver's own origin stack
54
+ * for a tagged query, parsed once per template; undefined for unsafe()
55
+ * and file() queries, which hold no origin.
56
+ */
57
+ private originSite;
58
+ private startQuerySpan;
59
+ private endQuerySpan;
60
+ }