@justanalyticsapp/node 0.2.0 → 0.3.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 (37) hide show
  1. package/dist/client.d.ts +23 -1
  2. package/dist/client.js +140 -2
  3. package/dist/client.js.map +1 -1
  4. package/dist/integrations/axios-integration.d.ts +53 -0
  5. package/dist/integrations/axios-integration.js +221 -0
  6. package/dist/integrations/axios-integration.js.map +1 -0
  7. package/dist/integrations/drizzle.d.ts +54 -0
  8. package/dist/integrations/drizzle.js +245 -0
  9. package/dist/integrations/drizzle.js.map +1 -0
  10. package/dist/integrations/http.d.ts +3 -1
  11. package/dist/integrations/http.js +12 -1
  12. package/dist/integrations/http.js.map +1 -1
  13. package/dist/integrations/mongodb.d.ts +50 -0
  14. package/dist/integrations/mongodb.js +260 -0
  15. package/dist/integrations/mongodb.js.map +1 -0
  16. package/dist/integrations/mysql.d.ts +56 -0
  17. package/dist/integrations/mysql.js +307 -0
  18. package/dist/integrations/mysql.js.map +1 -0
  19. package/dist/integrations/next.d.ts +41 -0
  20. package/dist/integrations/next.js +204 -0
  21. package/dist/integrations/next.js.map +1 -1
  22. package/dist/integrations/pg.d.ts +31 -3
  23. package/dist/integrations/pg.js +102 -22
  24. package/dist/integrations/pg.js.map +1 -1
  25. package/dist/integrations/postgres-js.d.ts +57 -0
  26. package/dist/integrations/postgres-js.js +311 -0
  27. package/dist/integrations/postgres-js.js.map +1 -0
  28. package/dist/integrations/prisma.d.ts +54 -0
  29. package/dist/integrations/prisma.js +186 -0
  30. package/dist/integrations/prisma.js.map +1 -0
  31. package/dist/integrations/redis.d.ts +6 -0
  32. package/dist/integrations/redis.js +16 -19
  33. package/dist/integrations/redis.js.map +1 -1
  34. package/dist/integrations/upstash-redis.d.ts +43 -0
  35. package/dist/integrations/upstash-redis.js +170 -0
  36. package/dist/integrations/upstash-redis.js.map +1 -0
  37. package/package.json +1 -1
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+ /**
3
+ * @file packages/node-sdk/src/integrations/mongodb.ts
4
+ * @description MongoDB auto-instrumentation integration for the JustAnalytics Node.js SDK.
5
+ *
6
+ * Monkey-patches `mongodb` Collection.prototype methods to automatically create
7
+ * `db.query` spans for all MongoDB operations. This also covers Mongoose since
8
+ * it uses the `mongodb` driver internally.
9
+ *
10
+ * Follows the same monkey-patching pattern as pg.ts and redis.ts:
11
+ * - Integration class with `enable()`/`disable()` lifecycle methods
12
+ * - Original function preservation for clean teardown
13
+ * - Fail-open design: if instrumentation code fails, the original operation executes normally
14
+ *
15
+ * SECURITY: Query filter objects are JSON-stringified with values replaced by '?'
16
+ * to prevent leaking sensitive data into span attributes.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.MongodbIntegration = void 0;
20
+ exports.sanitizeMongoFilter = sanitizeMongoFilter;
21
+ const span_1 = require("../span");
22
+ const context_1 = require("../context");
23
+ const id_1 = require("../utils/id");
24
+ /** MongoDB Collection methods to instrument */
25
+ const COLLECTION_METHODS = [
26
+ 'find',
27
+ 'findOne',
28
+ 'insertOne',
29
+ 'insertMany',
30
+ 'updateOne',
31
+ 'updateMany',
32
+ 'deleteOne',
33
+ 'deleteMany',
34
+ 'aggregate',
35
+ 'countDocuments',
36
+ 'distinct',
37
+ 'findOneAndUpdate',
38
+ 'findOneAndDelete',
39
+ 'findOneAndReplace',
40
+ 'bulkWrite',
41
+ ];
42
+ /**
43
+ * Sanitize a MongoDB filter/query object by replacing all values with '?'.
44
+ * Only preserves top-level keys and operator keys (starting with '$').
45
+ */
46
+ function sanitizeMongoFilter(filter, maxLength = 1024) {
47
+ try {
48
+ if (!filter || typeof filter !== 'object') {
49
+ return filter === undefined ? '{}' : '?';
50
+ }
51
+ const sanitized = sanitizeObject(filter, 3);
52
+ const result = JSON.stringify(sanitized);
53
+ if (result.length > maxLength) {
54
+ return result.substring(0, maxLength - 3) + '...';
55
+ }
56
+ return result;
57
+ }
58
+ catch {
59
+ return '{}';
60
+ }
61
+ }
62
+ function sanitizeObject(obj, maxDepth) {
63
+ if (maxDepth <= 0)
64
+ return '?';
65
+ if (Array.isArray(obj)) {
66
+ return obj.length > 0 ? ['?'] : [];
67
+ }
68
+ const result = {};
69
+ for (const key of Object.keys(obj)) {
70
+ const value = obj[key];
71
+ if (key.startsWith('$') && typeof value === 'object' && value !== null) {
72
+ // Preserve MongoDB operator structure
73
+ result[key] = sanitizeObject(value, maxDepth - 1);
74
+ }
75
+ else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
76
+ result[key] = sanitizeObject(value, maxDepth - 1);
77
+ }
78
+ else {
79
+ result[key] = '?';
80
+ }
81
+ }
82
+ return result;
83
+ }
84
+ /**
85
+ * MongodbIntegration monkey-patches mongodb Collection.prototype methods
86
+ * to auto-create db.query spans for all MongoDB operations.
87
+ */
88
+ class MongodbIntegration {
89
+ constructor(serviceName, options, onSpanEnd) {
90
+ this._enabled = false;
91
+ this._instrumentedDriver = null;
92
+ // Store original Collection methods for restoration
93
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
94
+ this._collectionProto = null;
95
+ this._originals = new Map();
96
+ this._serviceName = serviceName;
97
+ this._onSpanEnd = onSpanEnd;
98
+ const opts = options || {};
99
+ this._options = {
100
+ enabled: opts.enabled !== false,
101
+ maxStatementLength: opts.maxStatementLength ?? 1024,
102
+ };
103
+ }
104
+ get instrumentedDriver() {
105
+ return this._instrumentedDriver;
106
+ }
107
+ enable() {
108
+ if (this._enabled)
109
+ return;
110
+ if (!this._options.enabled)
111
+ return;
112
+ try {
113
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
114
+ let mongodb;
115
+ try {
116
+ mongodb = require('mongodb');
117
+ }
118
+ catch {
119
+ return;
120
+ }
121
+ const Collection = mongodb.Collection;
122
+ if (!Collection || !Collection.prototype) {
123
+ return;
124
+ }
125
+ this._collectionProto = Collection.prototype;
126
+ for (const method of COLLECTION_METHODS) {
127
+ const original = Collection.prototype[method];
128
+ if (typeof original !== 'function')
129
+ continue;
130
+ this._originals.set(method, original);
131
+ Collection.prototype[method] = this._wrapMethod(original, method);
132
+ }
133
+ this._instrumentedDriver = 'mongodb';
134
+ this._enabled = true;
135
+ }
136
+ catch {
137
+ this._restoreOriginals();
138
+ }
139
+ }
140
+ disable() {
141
+ if (!this._enabled)
142
+ return;
143
+ this._restoreOriginals();
144
+ this._instrumentedDriver = null;
145
+ this._enabled = false;
146
+ }
147
+ _wrapMethod(original, method) {
148
+ const integration = this;
149
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
150
+ return function patchedMethod(...args) {
151
+ try {
152
+ const parentSpan = (0, context_1.getActiveSpan)();
153
+ const traceId = parentSpan?.traceId ?? (0, id_1.generateTraceId)();
154
+ const parentSpanId = parentSpan?.id ?? null;
155
+ // Get collection name and database name from the Collection instance
156
+ const collectionName = this.collectionName || this.s?.namespace?.collection || 'unknown';
157
+ const dbName = this.dbName || this.s?.namespace?.db || this.s?.db?.databaseName || undefined;
158
+ const operationName = `db.query ${method}`;
159
+ // Sanitize the first argument (usually the filter/document)
160
+ const filterStr = args.length > 0
161
+ ? sanitizeMongoFilter(args[0], integration._options.maxStatementLength)
162
+ : '{}';
163
+ const statement = `${method} ${collectionName} ${filterStr}`;
164
+ const truncatedStatement = statement.length > integration._options.maxStatementLength
165
+ ? statement.substring(0, integration._options.maxStatementLength - 3) + '...'
166
+ : statement;
167
+ const attributes = {
168
+ 'db.system': 'mongodb',
169
+ 'db.operation': method,
170
+ 'db.mongodb.collection': collectionName,
171
+ 'db.statement': truncatedStatement,
172
+ };
173
+ if (dbName)
174
+ attributes['db.name'] = dbName;
175
+ const span = new span_1.Span({
176
+ operationName,
177
+ serviceName: integration._serviceName,
178
+ kind: 'client',
179
+ traceId,
180
+ parentSpanId,
181
+ attributes,
182
+ });
183
+ try {
184
+ const result = original.apply(this, args);
185
+ // MongoDB methods return promises (or cursors with toArray)
186
+ if (result && typeof result.then === 'function') {
187
+ return result.then((value) => {
188
+ span.end();
189
+ integration._onSpanEnd(span);
190
+ return value;
191
+ }, (error) => {
192
+ span.setStatus('error', error instanceof Error ? error.message : String(error));
193
+ span.end();
194
+ integration._onSpanEnd(span);
195
+ throw error;
196
+ });
197
+ }
198
+ // For methods that return cursors (e.g., find, aggregate), we
199
+ // instrument the cursor's toArray/next if possible, or just end span now
200
+ if (result && typeof result === 'object' && 'toArray' in result) {
201
+ // It's a cursor -- wrap toArray to capture full duration
202
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
203
+ const cursor = result;
204
+ const originalToArray = cursor.toArray;
205
+ if (typeof originalToArray === 'function') {
206
+ cursor.toArray = function patchedToArray(...toArrayArgs) {
207
+ const toArrayResult = originalToArray.apply(cursor, toArrayArgs);
208
+ if (toArrayResult && typeof toArrayResult.then === 'function') {
209
+ return toArrayResult.then((value) => {
210
+ span.end();
211
+ integration._onSpanEnd(span);
212
+ return value;
213
+ }, (error) => {
214
+ span.setStatus('error', error instanceof Error ? error.message : String(error));
215
+ span.end();
216
+ integration._onSpanEnd(span);
217
+ throw error;
218
+ });
219
+ }
220
+ span.end();
221
+ integration._onSpanEnd(span);
222
+ return toArrayResult;
223
+ };
224
+ }
225
+ else {
226
+ // No toArray -- end span immediately
227
+ span.end();
228
+ integration._onSpanEnd(span);
229
+ }
230
+ return result;
231
+ }
232
+ // Sync result (unlikely for MongoDB)
233
+ span.end();
234
+ integration._onSpanEnd(span);
235
+ return result;
236
+ }
237
+ catch (error) {
238
+ span.setStatus('error', error instanceof Error ? error.message : String(error));
239
+ span.end();
240
+ integration._onSpanEnd(span);
241
+ throw error;
242
+ }
243
+ }
244
+ catch {
245
+ return original.apply(this, args);
246
+ }
247
+ };
248
+ }
249
+ _restoreOriginals() {
250
+ if (this._collectionProto) {
251
+ for (const [method, original] of this._originals) {
252
+ this._collectionProto[method] = original;
253
+ }
254
+ this._originals.clear();
255
+ this._collectionProto = null;
256
+ }
257
+ }
258
+ }
259
+ exports.MongodbIntegration = MongodbIntegration;
260
+ //# sourceMappingURL=mongodb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mongodb.js","sourceRoot":"","sources":["../../src/integrations/mongodb.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @file packages/node-sdk/src/integrations/mysql.ts
3
+ * @description MySQL auto-instrumentation integration for the JustAnalytics Node.js SDK.
4
+ *
5
+ * Monkey-patches `mysql2` (Connection.prototype.query and .execute) and/or
6
+ * legacy `mysql` (Connection.prototype.query) to automatically create `db.query`
7
+ * spans for all MySQL operations.
8
+ *
9
+ * Follows the same monkey-patching pattern as pg.ts:
10
+ * - Integration class with `enable()`/`disable()` lifecycle methods
11
+ * - Original function preservation for clean teardown
12
+ * - Integration with AsyncLocalStorage context for automatic parent-child span relationships
13
+ * - Fail-open design: if instrumentation code fails, the original query executes normally
14
+ *
15
+ * SQL sanitization reuses the same utilities from pg.ts.
16
+ */
17
+ import { Span } from '../span';
18
+ /**
19
+ * Configuration for the MySQL auto-instrumentation integration.
20
+ */
21
+ export interface MysqlIntegrationOptions {
22
+ /** Enable/disable the integration (default: true) */
23
+ enabled?: boolean;
24
+ /** Maximum character length for the db.statement attribute (default: 2048) */
25
+ maxQueryLength?: number;
26
+ }
27
+ /**
28
+ * MysqlIntegration monkey-patches mysql2 and/or mysql to auto-create
29
+ * db.query spans for all MySQL operations.
30
+ */
31
+ export declare class MysqlIntegration {
32
+ private _enabled;
33
+ private _options;
34
+ private _serviceName;
35
+ private _onSpanEnd;
36
+ /** Which driver was instrumented */
37
+ private _instrumentedDriver;
38
+ private _mysql2ConnectionProto;
39
+ private _originalMysql2Query;
40
+ private _originalMysql2Execute;
41
+ private _mysqlConnectionProto;
42
+ private _originalMysqlQuery;
43
+ constructor(serviceName: string, options: MysqlIntegrationOptions | undefined, onSpanEnd: (span: Span) => void);
44
+ get instrumentedDriver(): string | null;
45
+ enable(): void;
46
+ disable(): void;
47
+ private _tryPatchMysql2;
48
+ private _tryPatchMysql;
49
+ /**
50
+ * Wrap a mysql/mysql2 query or execute method to create db.query spans.
51
+ */
52
+ private _wrapQuery;
53
+ private _restoreMysql2;
54
+ private _restoreMysql;
55
+ private _restoreOriginals;
56
+ }
@@ -0,0 +1,307 @@
1
+ "use strict";
2
+ /**
3
+ * @file packages/node-sdk/src/integrations/mysql.ts
4
+ * @description MySQL auto-instrumentation integration for the JustAnalytics Node.js SDK.
5
+ *
6
+ * Monkey-patches `mysql2` (Connection.prototype.query and .execute) and/or
7
+ * legacy `mysql` (Connection.prototype.query) to automatically create `db.query`
8
+ * spans for all MySQL operations.
9
+ *
10
+ * Follows the same monkey-patching pattern as pg.ts:
11
+ * - Integration class with `enable()`/`disable()` lifecycle methods
12
+ * - Original function preservation for clean teardown
13
+ * - Integration with AsyncLocalStorage context for automatic parent-child span relationships
14
+ * - Fail-open design: if instrumentation code fails, the original query executes normally
15
+ *
16
+ * SQL sanitization reuses the same utilities from pg.ts.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.MysqlIntegration = void 0;
20
+ const span_1 = require("../span");
21
+ const context_1 = require("../context");
22
+ const id_1 = require("../utils/id");
23
+ const pg_1 = require("./pg");
24
+ /**
25
+ * Normalize mysql/mysql2 query arguments into a consistent shape.
26
+ *
27
+ * Both drivers support:
28
+ * - query(sql, callback)
29
+ * - query(sql, values, callback)
30
+ * - query(sql) -- promise (mysql2 only)
31
+ * - query(sql, values) -- promise (mysql2 only)
32
+ * - query({ sql: string, ... })
33
+ */
34
+ function normalizeMysqlArgs(args) {
35
+ let text = '';
36
+ let callback = null;
37
+ if (typeof args[0] === 'string') {
38
+ text = args[0];
39
+ }
40
+ else if (typeof args[0] === 'object' && args[0] !== null && 'sql' in args[0]) {
41
+ text = args[0].sql;
42
+ }
43
+ // Find callback (last function argument)
44
+ for (let i = args.length - 1; i >= 1; i--) {
45
+ if (typeof args[i] === 'function') {
46
+ callback = args[i];
47
+ break;
48
+ }
49
+ }
50
+ // Also check first arg callback style: query(callback) is unusual but defensive
51
+ if (!callback && args.length === 1 && typeof args[0] === 'function') {
52
+ // Not a query call we can instrument
53
+ text = '';
54
+ }
55
+ return { text, callback };
56
+ }
57
+ /**
58
+ * MysqlIntegration monkey-patches mysql2 and/or mysql to auto-create
59
+ * db.query spans for all MySQL operations.
60
+ */
61
+ class MysqlIntegration {
62
+ constructor(serviceName, options, onSpanEnd) {
63
+ this._enabled = false;
64
+ /** Which driver was instrumented */
65
+ this._instrumentedDriver = null;
66
+ // mysql2 originals
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ this._mysql2ConnectionProto = null;
69
+ this._originalMysql2Query = null;
70
+ this._originalMysql2Execute = null;
71
+ // legacy mysql originals
72
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
+ this._mysqlConnectionProto = null;
74
+ this._originalMysqlQuery = null;
75
+ this._serviceName = serviceName;
76
+ this._onSpanEnd = onSpanEnd;
77
+ const opts = options || {};
78
+ this._options = {
79
+ enabled: opts.enabled !== false,
80
+ maxQueryLength: opts.maxQueryLength ?? 2048,
81
+ };
82
+ }
83
+ get instrumentedDriver() {
84
+ return this._instrumentedDriver;
85
+ }
86
+ enable() {
87
+ if (this._enabled)
88
+ return;
89
+ if (!this._options.enabled)
90
+ return;
91
+ const drivers = [];
92
+ // Try mysql2 first (most popular)
93
+ if (this._tryPatchMysql2()) {
94
+ drivers.push('mysql2');
95
+ }
96
+ // Try legacy mysql
97
+ if (this._tryPatchMysql()) {
98
+ drivers.push('mysql');
99
+ }
100
+ if (drivers.length === 0)
101
+ return;
102
+ this._instrumentedDriver = drivers.join(', ');
103
+ this._enabled = true;
104
+ }
105
+ disable() {
106
+ if (!this._enabled)
107
+ return;
108
+ this._restoreOriginals();
109
+ this._instrumentedDriver = null;
110
+ this._enabled = false;
111
+ }
112
+ _tryPatchMysql2() {
113
+ try {
114
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
115
+ let mysql2;
116
+ try {
117
+ mysql2 = require('mysql2');
118
+ }
119
+ catch {
120
+ return false;
121
+ }
122
+ // mysql2 exposes Connection via the module
123
+ const Connection = mysql2.Connection;
124
+ if (!Connection || !Connection.prototype) {
125
+ return false;
126
+ }
127
+ this._mysql2ConnectionProto = Connection.prototype;
128
+ // Patch query
129
+ if (typeof Connection.prototype.query === 'function') {
130
+ this._originalMysql2Query = Connection.prototype.query;
131
+ Connection.prototype.query = this._wrapQuery(this._originalMysql2Query, 'mysql2');
132
+ }
133
+ // Patch execute (prepared statements)
134
+ if (typeof Connection.prototype.execute === 'function') {
135
+ this._originalMysql2Execute = Connection.prototype.execute;
136
+ Connection.prototype.execute = this._wrapQuery(this._originalMysql2Execute, 'mysql2');
137
+ }
138
+ return true;
139
+ }
140
+ catch {
141
+ this._restoreMysql2();
142
+ return false;
143
+ }
144
+ }
145
+ _tryPatchMysql() {
146
+ try {
147
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
148
+ let mysql;
149
+ try {
150
+ mysql = require('mysql');
151
+ }
152
+ catch {
153
+ return false;
154
+ }
155
+ // Legacy mysql creates connections via createConnection/createPool
156
+ // The Connection prototype is internal; try to access it
157
+ const tempConn = mysql.createConnection ? mysql.createConnection({ host: '__probe__' }) : null;
158
+ if (tempConn && tempConn.constructor && tempConn.constructor.prototype) {
159
+ const proto = tempConn.constructor.prototype;
160
+ if (typeof proto.query === 'function') {
161
+ this._mysqlConnectionProto = proto;
162
+ this._originalMysqlQuery = proto.query;
163
+ proto.query = this._wrapQuery(this._originalMysqlQuery, 'mysql');
164
+ // Destroy the probe connection (it was never connected)
165
+ try {
166
+ tempConn.destroy();
167
+ }
168
+ catch { /* ignore */ }
169
+ return true;
170
+ }
171
+ try {
172
+ tempConn.destroy();
173
+ }
174
+ catch { /* ignore */ }
175
+ }
176
+ return false;
177
+ }
178
+ catch {
179
+ this._restoreMysql();
180
+ return false;
181
+ }
182
+ }
183
+ /**
184
+ * Wrap a mysql/mysql2 query or execute method to create db.query spans.
185
+ */
186
+ _wrapQuery(original, driver) {
187
+ const integration = this;
188
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
189
+ return function patchedQuery(...args) {
190
+ try {
191
+ const { text, callback } = normalizeMysqlArgs(args);
192
+ if (!text) {
193
+ return original.apply(this, args);
194
+ }
195
+ const parentSpan = (0, context_1.getActiveSpan)();
196
+ const traceId = parentSpan?.traceId ?? (0, id_1.generateTraceId)();
197
+ const parentSpanId = parentSpan?.id ?? null;
198
+ const operation = (0, pg_1.extractSqlOperation)(text);
199
+ const table = (0, pg_1.extractTableName)(text);
200
+ const sanitizedSql = (0, pg_1.sanitizeSql)(text, integration._options.maxQueryLength);
201
+ const operationName = operation !== 'UNKNOWN' ? `db.query ${operation}` : 'db.query';
202
+ const attributes = {
203
+ 'db.system': 'mysql',
204
+ 'db.statement': sanitizedSql,
205
+ 'db.driver': driver,
206
+ };
207
+ if (operation !== 'UNKNOWN')
208
+ attributes['db.operation'] = operation;
209
+ if (table)
210
+ attributes['db.sql.table'] = table;
211
+ // Extract connection info
212
+ const config = this.config || this.connectionConfig || {};
213
+ if (config.database)
214
+ attributes['db.name'] = config.database;
215
+ if (config.user)
216
+ attributes['db.user'] = config.user;
217
+ if (config.host) {
218
+ const host = config.host || 'localhost';
219
+ const port = config.port || 3306;
220
+ attributes['db.connection_string'] = `mysql://${config.user || ''}:***@${host}:${port}/${config.database || ''}`;
221
+ }
222
+ const span = new span_1.Span({
223
+ operationName,
224
+ serviceName: integration._serviceName,
225
+ kind: 'client',
226
+ traceId,
227
+ parentSpanId,
228
+ attributes,
229
+ });
230
+ if (callback) {
231
+ // Callback-style: wrap callback to end span
232
+ const wrappedArgs = [...args];
233
+ const cbIndex = wrappedArgs.findIndex((a) => typeof a === 'function');
234
+ if (cbIndex !== -1) {
235
+ const originalCb = wrappedArgs[cbIndex];
236
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
237
+ wrappedArgs[cbIndex] = function wrappedCallback(err, ...rest) {
238
+ if (err) {
239
+ span.setStatus('error', err instanceof Error ? err.message : String(err));
240
+ }
241
+ span.end();
242
+ integration._onSpanEnd(span);
243
+ return originalCb.call(this, err, ...rest);
244
+ };
245
+ }
246
+ return original.apply(this, wrappedArgs);
247
+ }
248
+ else {
249
+ // Promise-style (mysql2 supports this)
250
+ try {
251
+ const result = original.apply(this, args);
252
+ if (result && typeof result.then === 'function') {
253
+ return result.then((value) => {
254
+ span.end();
255
+ integration._onSpanEnd(span);
256
+ return value;
257
+ }, (error) => {
258
+ span.setStatus('error', error instanceof Error ? error.message : String(error));
259
+ span.end();
260
+ integration._onSpanEnd(span);
261
+ throw error;
262
+ });
263
+ }
264
+ span.end();
265
+ integration._onSpanEnd(span);
266
+ return result;
267
+ }
268
+ catch (error) {
269
+ span.setStatus('error', error instanceof Error ? error.message : String(error));
270
+ span.end();
271
+ integration._onSpanEnd(span);
272
+ throw error;
273
+ }
274
+ }
275
+ }
276
+ catch {
277
+ return original.apply(this, args);
278
+ }
279
+ };
280
+ }
281
+ _restoreMysql2() {
282
+ if (this._mysql2ConnectionProto) {
283
+ if (this._originalMysql2Query) {
284
+ this._mysql2ConnectionProto.query = this._originalMysql2Query;
285
+ this._originalMysql2Query = null;
286
+ }
287
+ if (this._originalMysql2Execute) {
288
+ this._mysql2ConnectionProto.execute = this._originalMysql2Execute;
289
+ this._originalMysql2Execute = null;
290
+ }
291
+ this._mysql2ConnectionProto = null;
292
+ }
293
+ }
294
+ _restoreMysql() {
295
+ if (this._mysqlConnectionProto && this._originalMysqlQuery) {
296
+ this._mysqlConnectionProto.query = this._originalMysqlQuery;
297
+ this._originalMysqlQuery = null;
298
+ this._mysqlConnectionProto = null;
299
+ }
300
+ }
301
+ _restoreOriginals() {
302
+ this._restoreMysql2();
303
+ this._restoreMysql();
304
+ }
305
+ }
306
+ exports.MysqlIntegration = MysqlIntegration;
307
+ //# sourceMappingURL=mysql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql.js","sourceRoot":"","sources":["../../src/integrations/mysql.ts"],"names":[],"mappings":"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"}