whatap 0.5.9 → 0.5.11
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/lib/conf/config-default.js +4 -1
- package/lib/observers/prisma-observer.js +210 -186
- package/package.json +2 -2
|
@@ -271,7 +271,10 @@ var ConfigDefault = {
|
|
|
271
271
|
|
|
272
272
|
"profile_graphql_enabled": bool("profile_graphql_enabled", true),
|
|
273
273
|
"profile_graphql_variable_enabled": bool("profile_graphql_variable_enabled", false),
|
|
274
|
-
"ignore_graphql_operation": str("ignore_graphql_operation", '')
|
|
274
|
+
"ignore_graphql_operation": str("ignore_graphql_operation", ''),
|
|
275
|
+
|
|
276
|
+
"prisma_read_func_name": str("prisma_read_func_name", "read"),
|
|
277
|
+
"prisma_database_url_name": str("prisma_database_url_name", "DATABASE_URL"),
|
|
275
278
|
};
|
|
276
279
|
|
|
277
280
|
ConfigDefault._hook_method_ignore_prefix = ConfigDefault.hook_method_ignore_prefixes.split(',');
|
|
@@ -25,6 +25,12 @@ const DateUtil = require("../util/dateutil");
|
|
|
25
25
|
const TraceSQL = require("../trace/trace-sql");
|
|
26
26
|
const shimmer = require("../core/shimmer");
|
|
27
27
|
|
|
28
|
+
var prisma_read_func_name = conf.getProperty('prisma_read_func_name', 'read');
|
|
29
|
+
var prisma_database_url_name = conf.getProperty('prisma_database_url_name', 'DATABASE_URL')
|
|
30
|
+
conf.on('prisma_database_url_name', function (newProps) {
|
|
31
|
+
prisma_database_url_name = newProps;
|
|
32
|
+
})
|
|
33
|
+
|
|
28
34
|
var PrismaObserver = function(agent) {
|
|
29
35
|
this.agent = agent;
|
|
30
36
|
this.packages = ["@prisma/client"];
|
|
@@ -51,13 +57,31 @@ PrismaObserver.prototype.inject = function(mod, moduleName) {
|
|
|
51
57
|
if (mod.PrismaClient) {
|
|
52
58
|
// 직접 PrismaClient 생성자 후킹
|
|
53
59
|
shimmer.wrap(mod, 'PrismaClient', function(originalConstructor) {
|
|
54
|
-
return function() {
|
|
55
|
-
|
|
56
|
-
const instance =
|
|
60
|
+
return function(...args) {
|
|
61
|
+
const originalInstance = new originalConstructor(...args);
|
|
62
|
+
const instance = Object.create(originalInstance);
|
|
63
|
+
|
|
64
|
+
const prismaServicePrototype = Object.getPrototypeOf(this);
|
|
65
|
+
Object.getOwnPropertyNames(prismaServicePrototype).forEach((method) => {
|
|
66
|
+
if (typeof prismaServicePrototype[method] === "function" && !instance[method]) {
|
|
67
|
+
instance[method] = prismaServicePrototype[method].bind(instance);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
Object.getOwnPropertyNames(originalInstance).forEach((prop) => {
|
|
72
|
+
if (!instance.hasOwnProperty(prop)) {
|
|
73
|
+
instance[prop] = originalInstance[prop];
|
|
74
|
+
}
|
|
75
|
+
});
|
|
57
76
|
|
|
58
|
-
// 이 시점에서 instance가 생성된 Prisma 클라이언트 인스턴스
|
|
59
77
|
self.patchPrismaInstance(instance);
|
|
60
78
|
|
|
79
|
+
if (!instance[prisma_read_func_name]) {
|
|
80
|
+
instance[prisma_read_func_name] = function () {
|
|
81
|
+
return this;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
61
85
|
return instance;
|
|
62
86
|
};
|
|
63
87
|
});
|
|
@@ -75,7 +99,7 @@ PrismaObserver.prototype.patchPrismaInstance = function(prismaInstance) {
|
|
|
75
99
|
this.setupConnectionInfo(prismaInstance);
|
|
76
100
|
|
|
77
101
|
// $connect 후킹
|
|
78
|
-
this.hookConnect(prismaInstance);
|
|
102
|
+
// this.hookConnect(prismaInstance);
|
|
79
103
|
|
|
80
104
|
// Raw 쿼리 메서드 후킹
|
|
81
105
|
// this.hookRawQueryMethods(prismaInstance);
|
|
@@ -91,12 +115,12 @@ PrismaObserver.prototype.patchPrismaInstance = function(prismaInstance) {
|
|
|
91
115
|
PrismaObserver.prototype.setupConnectionInfo = function(prismaInstance) {
|
|
92
116
|
try {
|
|
93
117
|
// 연결 정보 가져오기 시도
|
|
94
|
-
const url = prismaInstance._engineConfig?.
|
|
95
|
-
prismaInstance.
|
|
96
|
-
process.env
|
|
118
|
+
const url = prismaInstance._engineConfig?.overrideDatasources?.db?.url ||
|
|
119
|
+
prismaInstance.env?.DATABASE_URL ||
|
|
120
|
+
process.env[prisma_database_url_name] ||
|
|
97
121
|
'prisma:unknown';
|
|
98
122
|
|
|
99
|
-
if (url && url !== "prisma:unknown") {
|
|
123
|
+
if (url && url !== "prisma:unknown" && !dbc_hash) {
|
|
100
124
|
const dbUrl = new URL(url);
|
|
101
125
|
const protocol = dbUrl.protocol.replace(':', '');
|
|
102
126
|
|
|
@@ -125,185 +149,185 @@ PrismaObserver.prototype.setupConnectionInfo = function(prismaInstance) {
|
|
|
125
149
|
};
|
|
126
150
|
|
|
127
151
|
// Connect 메서드 후킹
|
|
128
|
-
PrismaObserver.prototype.hookConnect = function(prismaInstance) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
};
|
|
152
|
+
// PrismaObserver.prototype.hookConnect = function(prismaInstance) {
|
|
153
|
+
// const self = this;
|
|
154
|
+
//
|
|
155
|
+
// shimmer.wrap(prismaInstance, "$connect", function(original) {
|
|
156
|
+
// return async function() {
|
|
157
|
+
// const ctx = TraceContextManager.getCurrentContext();
|
|
158
|
+
// if (!ctx || ctx.db_opening) {
|
|
159
|
+
// return original.apply(this, arguments);
|
|
160
|
+
// }
|
|
161
|
+
//
|
|
162
|
+
// ctx.db_opening = true;
|
|
163
|
+
// ctx.footprint("Prisma Connecting Start");
|
|
164
|
+
//
|
|
165
|
+
// const dbc_step = new DBCStep();
|
|
166
|
+
// dbc_step.start_time = ctx.getElapsedTime();
|
|
167
|
+
//
|
|
168
|
+
// try {
|
|
169
|
+
// const result = await original.apply(this, arguments);
|
|
170
|
+
//
|
|
171
|
+
// dbc_step.hash = dbc_hash;
|
|
172
|
+
// dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
173
|
+
//
|
|
174
|
+
// ctx.db_opening = false;
|
|
175
|
+
// ctx.footprint("Prisma Connecting Done");
|
|
176
|
+
// ctx.profile.push(dbc_step);
|
|
177
|
+
//
|
|
178
|
+
// return result;
|
|
179
|
+
// } catch (err) {
|
|
180
|
+
// ctx.db_opening = false;
|
|
181
|
+
//
|
|
182
|
+
// dbc_step.hash = dbc_hash;
|
|
183
|
+
// dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
184
|
+
// dbc_step.error = StatError.addError("prisma-connection", err.message, ctx.service_hash);
|
|
185
|
+
//
|
|
186
|
+
// if (ctx.error.isZero()) {
|
|
187
|
+
// ctx.error = dbc_step.error;
|
|
188
|
+
// }
|
|
189
|
+
//
|
|
190
|
+
// ctx.profile.push(dbc_step);
|
|
191
|
+
// Logger.printError("WHATAP-302", "Connection Error", err);
|
|
192
|
+
// throw err;
|
|
193
|
+
// }
|
|
194
|
+
// };
|
|
195
|
+
// });
|
|
196
|
+
// };
|
|
173
197
|
|
|
174
198
|
// Raw 쿼리 메서드 후킹
|
|
175
|
-
PrismaObserver.prototype.hookRawQueryMethods = function(prismaInstance) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
};
|
|
199
|
+
// PrismaObserver.prototype.hookRawQueryMethods = function(prismaInstance) {
|
|
200
|
+
// const self = this;
|
|
201
|
+
// const queryMethods = ["$queryRaw", "$executeRaw", "$queryRawUnsafe", "$executeRawUnsafe"];
|
|
202
|
+
//
|
|
203
|
+
// queryMethods.forEach(method => {
|
|
204
|
+
// if (typeof prismaInstance[method] === 'function') {
|
|
205
|
+
// shimmer.wrap(prismaInstance, method, function(original) {
|
|
206
|
+
// return async function() {
|
|
207
|
+
// const ctx = TraceContextManager.getCurrentContext();
|
|
208
|
+
// if (!ctx) {
|
|
209
|
+
// return original.apply(this, arguments);
|
|
210
|
+
// }
|
|
211
|
+
//
|
|
212
|
+
// const sql_step = new SqlStepX();
|
|
213
|
+
// sql_step.start_time = ctx.getElapsedTime();
|
|
214
|
+
// ctx.profile.push(sql_step);
|
|
215
|
+
// ctx.footprint(`Prisma ${method} Start`);
|
|
216
|
+
//
|
|
217
|
+
// ctx.sql_count = (ctx.sql_count || 0) + 1;
|
|
218
|
+
//
|
|
219
|
+
// // SQL 쿼리 추출
|
|
220
|
+
// let sql = "";
|
|
221
|
+
// let psql = null;
|
|
222
|
+
//
|
|
223
|
+
// if (arguments.length > 0) {
|
|
224
|
+
// if (typeof arguments[0] === "object" && arguments[0].sql) {
|
|
225
|
+
// // Tagged template으로 전달된 경우
|
|
226
|
+
// sql = arguments[0].sql;
|
|
227
|
+
// } else if (typeof arguments[0] === "string") {
|
|
228
|
+
// // Raw string으로 전달된 경우
|
|
229
|
+
// sql = arguments[0];
|
|
230
|
+
// }
|
|
231
|
+
// }
|
|
232
|
+
//
|
|
233
|
+
// // SQL 파싱
|
|
234
|
+
// if (sql && sql.length > 0) {
|
|
235
|
+
// try {
|
|
236
|
+
// psql = escapeLiteral(sql);
|
|
237
|
+
// } catch (e) {
|
|
238
|
+
// Logger.printError("WHATAP-303", "escapeliteral error", e, false);
|
|
239
|
+
// }
|
|
240
|
+
// } else {
|
|
241
|
+
// sql = "";
|
|
242
|
+
// psql = escapeLiteral(sql);
|
|
243
|
+
// }
|
|
244
|
+
//
|
|
245
|
+
// if (psql != null) {
|
|
246
|
+
// sql_step.hash = psql.sql;
|
|
247
|
+
// }
|
|
248
|
+
// sql_step.dbc = dbc_hash;
|
|
249
|
+
//
|
|
250
|
+
// var els = new EscapeLiteralSQL(sql);
|
|
251
|
+
// els.process();
|
|
252
|
+
//
|
|
253
|
+
// ctx.active_sqlhash = sql_step.hash;
|
|
254
|
+
// ctx.active_dbc = sql_step.dbc;
|
|
255
|
+
//
|
|
256
|
+
// // 파라미터 정보 추출
|
|
257
|
+
// if (conf.profile_sql_param_enabled) {
|
|
258
|
+
// var params = Array.from(arguments).slice(1);
|
|
259
|
+
// sql_step.setTrue(1);
|
|
260
|
+
// var crc = { value: 0 };
|
|
261
|
+
// sql_step.p1 = toParamBytes(psql.param, crc);
|
|
262
|
+
//
|
|
263
|
+
// if (params.length > 0) {
|
|
264
|
+
// const result = params.map((param) => {
|
|
265
|
+
// if (typeof param === "string") {
|
|
266
|
+
// return `'${param}'`;
|
|
267
|
+
// }
|
|
268
|
+
// return param;
|
|
269
|
+
// }).toString();
|
|
270
|
+
// sql_step.p2 = toParamBytes(result, crc);
|
|
271
|
+
// }
|
|
272
|
+
//
|
|
273
|
+
// sql_step.pcrc = crc.value;
|
|
274
|
+
// }
|
|
275
|
+
//
|
|
276
|
+
// try {
|
|
277
|
+
// const result = await original.apply(this, arguments);
|
|
278
|
+
//
|
|
279
|
+
// // SELECT 쿼리의 결과셋 처리
|
|
280
|
+
// if (method === "$queryRaw" || method === "$queryRawUnsafe") {
|
|
281
|
+
// if (Array.isArray(result)) {
|
|
282
|
+
// var result_step = new ResultSetStep();
|
|
283
|
+
// result_step.start_time = ctx.getElapsedTime();
|
|
284
|
+
// result_step.elapsed = 0;
|
|
285
|
+
// result_step.fetch = result.length;
|
|
286
|
+
// result_step.sqlhash = psql.sql;
|
|
287
|
+
// result_step.dbc = dbc_hash;
|
|
288
|
+
// ctx.profile.push(result_step);
|
|
289
|
+
//
|
|
290
|
+
// ctx.rs_count = ctx.rs_count ? ctx.rs_count + result.length : result.length;
|
|
291
|
+
// ctx.rs_time = ctx.rs_time ? ctx.rs_time + sql_step.elapsed : sql_step.elapsed;
|
|
292
|
+
//
|
|
293
|
+
// MeterSql.addFetch(result_step.dbc, result_step.fetch, 0);
|
|
294
|
+
// StatSql.addFetch(result_step.dbc, result_step.sqlhash, result_step.fetch, 0);
|
|
295
|
+
//
|
|
296
|
+
// TraceSQL.isTooManyRecords(sql_step, result_step.fetch, ctx);
|
|
297
|
+
// }
|
|
298
|
+
// }
|
|
299
|
+
//
|
|
300
|
+
// // UPDATE/INSERT/DELETE 쿼리 결과 처리
|
|
301
|
+
// if ((method === "$executeRaw" || method === "$executeRawUnsafe") && typeof result === "number") {
|
|
302
|
+
// sql_step.updated = result;
|
|
303
|
+
// }
|
|
304
|
+
//
|
|
305
|
+
// self._finishQuery(ctx, sql_step);
|
|
306
|
+
// return result;
|
|
307
|
+
// } catch (err) {
|
|
308
|
+
// Logger.printError("WHATAP-304", `${method} error: ${err.message}`, err);
|
|
309
|
+
//
|
|
310
|
+
// self._handleError(ctx, sql_step, err);
|
|
311
|
+
//
|
|
312
|
+
// if (conf.trace_sql_error_stack && conf.trace_sql_error_depth) {
|
|
313
|
+
// var traceDepth = conf.trace_sql_error_depth;
|
|
314
|
+
// var errorStack = err.stack.split("\n");
|
|
315
|
+
//
|
|
316
|
+
// if (errorStack.length > traceDepth) {
|
|
317
|
+
// errorStack = errorStack.slice(0, traceDepth + 1);
|
|
318
|
+
// }
|
|
319
|
+
//
|
|
320
|
+
// ctx.error_message = errorStack.join("\n");
|
|
321
|
+
// sql_step.error = ctx.error = StatError.addError("prisma-" + (err.code || "unknown"), err.message, ctx.service_hash, TextTypes.SQL, null);
|
|
322
|
+
// }
|
|
323
|
+
//
|
|
324
|
+
// throw err;
|
|
325
|
+
// }
|
|
326
|
+
// };
|
|
327
|
+
// });
|
|
328
|
+
// }
|
|
329
|
+
// });
|
|
330
|
+
// };
|
|
307
331
|
|
|
308
332
|
PrismaObserver.prototype.hookUseMiddleware = function(prismaInstance) {
|
|
309
333
|
const self = this;
|
package/package.json
CHANGED