whatap 0.5.11 → 0.5.13
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 +2 -0
- package/lib/core/agent.js +4 -1
- package/lib/counter/counter-manager.js +4 -0
- package/lib/counter/task/metering-info.js +118 -0
- package/lib/observers/http-observer.js +1 -0
- package/lib/observers/oracle-observer.js +656 -0
- package/lib/observers/prisma-observer.js +20 -269
- package/lib/observers/socket.io-observer.js +213 -74
- package/lib/observers/websocket-observer.js +164 -67
- package/lib/pack/apenum.js +8 -0
- package/lib/pack/otype.js +7 -0
- package/lib/pack/tagcount-pack.js +51 -50
- package/lib/util/dateutil.js +33 -1
- package/lib/util/escape-literal-sql.js +5 -5
- package/package.json +2 -2
|
@@ -0,0 +1,656 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2023 the WHATAP project authors. All rights reserved.
|
|
3
|
+
* Use of this source code is governed by a license that
|
|
4
|
+
* can be found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
var TraceContextManager = require('../trace/trace-context-manager'),
|
|
8
|
+
ParsedSql = require('../trace/parsed-sql'),
|
|
9
|
+
SqlStepX = require('../step/sql-stepx'),
|
|
10
|
+
DBCStep = require('../step/dbc-step'),
|
|
11
|
+
ResultSetStep = require('../step/resultset-step'),
|
|
12
|
+
DataTextAgent = require('../data/datatext-agent'),
|
|
13
|
+
StatSql = require('../stat/stat-sql'),
|
|
14
|
+
MeterSql = require('../counter/meter/meter-sql'),
|
|
15
|
+
conf = require('../conf/configure'),
|
|
16
|
+
IntKeyMap = require('../util/intkey-map'),
|
|
17
|
+
EscapeLiteralSQL = require('../util/escape-literal-sql'),
|
|
18
|
+
HashUtil = require('../util/hashutil'),
|
|
19
|
+
StatError = require('../stat/stat-error'),
|
|
20
|
+
TextTypes = require('../lang/text-types'),
|
|
21
|
+
ParamSecurity = require('../util/paramsecurity'),
|
|
22
|
+
Logger = require('../logger'),
|
|
23
|
+
DateUtil = require('../util/dateutil'),
|
|
24
|
+
Buffer = require('buffer').Buffer,
|
|
25
|
+
TraceSQL = require('../trace/trace-sql');
|
|
26
|
+
var shimmer = require('../core/shimmer');
|
|
27
|
+
|
|
28
|
+
// Store connection info for reuse
|
|
29
|
+
var connectionAttributes = new WeakMap();
|
|
30
|
+
var poolAttributes = new WeakMap();
|
|
31
|
+
|
|
32
|
+
var OracleObserver = function (agent) {
|
|
33
|
+
this.agent = agent;
|
|
34
|
+
this.packages = ['oracledb'];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// 쿼리 파라미터를 바이트 배열로 변환
|
|
38
|
+
var toParamBytes = function (p, crc) {
|
|
39
|
+
if (p == null || p.length === 0) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
return ParamSecurity.encrypt(Buffer.from(p, 'utf8'), crc);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
var errorDelegate = function (ctx, step) {
|
|
50
|
+
return function (obj, args) {
|
|
51
|
+
if (ctx == null) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (step == null) {
|
|
56
|
+
var laststep = ctx.profile.getLastSteps(1);
|
|
57
|
+
if (laststep == null || laststep.length === 0) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
step = laststep[0];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
MeterSql.add(step.dbc, step.elapsed, true);
|
|
64
|
+
StatSql.addSqlTime(ctx.service_hash, step.dbc, step.hash, step.elapsed, true, 0);
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
var errorCode = args[0].errorNum || args[0].code || 'ORA-00000';
|
|
68
|
+
var errorMsg = args[0].message || 'Oracle error';
|
|
69
|
+
|
|
70
|
+
if (conf._is_trace_ignore_err_cls_contains === true && errorCode.toString().indexOf(conf.trace_ignore_err_cls_contains) < 0) {
|
|
71
|
+
step.error = StatError.addError('oracle-' + errorCode, errorMsg, ctx.service_hash, TextTypes.SQL, step.hash);
|
|
72
|
+
if (ctx.error.isZero()) {
|
|
73
|
+
ctx.error = step.error;
|
|
74
|
+
}
|
|
75
|
+
} else if (conf._is_trace_ignore_err_msg_contains === true && errorMsg.indexOf(conf.trace_ignore_err_msg_contains) < 0) {
|
|
76
|
+
step.error = StatError.addError('oracle-' + errorCode, errorMsg, ctx.service_hash, TextTypes.SQL, step.hash);
|
|
77
|
+
if (ctx.error.isZero()) {
|
|
78
|
+
ctx.error = step.error;
|
|
79
|
+
}
|
|
80
|
+
} else if (conf._is_trace_ignore_err_cls_contains === false && conf._is_trace_ignore_err_msg_contains === false) {
|
|
81
|
+
step.error = StatError.addError('oracle-' + errorCode, errorMsg, ctx.service_hash, TextTypes.SQL, step.hash);
|
|
82
|
+
if (ctx.error.isZero()) {
|
|
83
|
+
ctx.error = step.error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (conf.trace_sql_error_stack && conf.trace_sql_error_depth) {
|
|
88
|
+
var traceDepth = conf.trace_sql_error_depth;
|
|
89
|
+
if (args[0].stack) {
|
|
90
|
+
var errorStack = args[0].stack.split("\n");
|
|
91
|
+
if (errorStack.length > traceDepth) {
|
|
92
|
+
errorStack = errorStack.slice(0, traceDepth + 1);
|
|
93
|
+
}
|
|
94
|
+
ctx.error_message = errorStack.join("\n");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
} catch (e) {
|
|
98
|
+
Logger.printError('WHATAP-110', 'OracleObserver error delegate exception', e, false);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// 커넥션 풀 관리 함수
|
|
104
|
+
OracleObserver.prototype._wrapPoolOrConnection = function (obj, dbc) {
|
|
105
|
+
var self = this;
|
|
106
|
+
|
|
107
|
+
if (obj.__whatap_observed) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
obj.__whatap_observed = true;
|
|
111
|
+
|
|
112
|
+
// execute 메소드 래핑
|
|
113
|
+
if (obj.execute && typeof obj.execute === 'function') {
|
|
114
|
+
shimmer.wrap(obj, 'execute', function (original) {
|
|
115
|
+
return function () {
|
|
116
|
+
var ctx = TraceContextManager.getCurrentContext();
|
|
117
|
+
var args = Array.from(arguments);
|
|
118
|
+
|
|
119
|
+
if (ctx == null || args.length === 0) {
|
|
120
|
+
return original.apply(this, args);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
var sql = args[0];
|
|
124
|
+
if (sql == null) {
|
|
125
|
+
return original.apply(this, args);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// DBC 단계 생성
|
|
129
|
+
var dbc_hash = HashUtil.hashFromString(dbc);
|
|
130
|
+
|
|
131
|
+
// SQL 단계 생성
|
|
132
|
+
var sql_step = new SqlStepX();
|
|
133
|
+
sql_step.start_time = ctx.getElapsedTime();
|
|
134
|
+
ctx.profile.push(sql_step);
|
|
135
|
+
|
|
136
|
+
ctx.footprint('Oracle Query Start');
|
|
137
|
+
ctx.sql_count++;
|
|
138
|
+
|
|
139
|
+
var psql = null;
|
|
140
|
+
if (typeof sql === 'string' && sql.length > 0) {
|
|
141
|
+
try {
|
|
142
|
+
psql = escapeLiteral(sql);
|
|
143
|
+
} catch (e) {
|
|
144
|
+
Logger.printError('WHATAP-111', 'OracleObserver escapeliteral error', e, false);
|
|
145
|
+
}
|
|
146
|
+
} else {
|
|
147
|
+
sql = '';
|
|
148
|
+
psql = escapeLiteral(sql);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (psql != null) {
|
|
152
|
+
sql_step.hash = psql.sql;
|
|
153
|
+
// sql_step.crud = psql.type.charCodeAt(0);
|
|
154
|
+
}
|
|
155
|
+
sql_step.dbc = dbc_hash;
|
|
156
|
+
|
|
157
|
+
var els = new EscapeLiteralSQL(sql);
|
|
158
|
+
els.process();
|
|
159
|
+
|
|
160
|
+
ctx.active_sqlhash = sql_step.hash;
|
|
161
|
+
ctx.active_dbc = sql_step.dbc;
|
|
162
|
+
//ctx.active_crud = sql_step.crud;
|
|
163
|
+
|
|
164
|
+
// 파라미터 처리
|
|
165
|
+
if (conf.profile_sql_param_enabled) {
|
|
166
|
+
var params = args.length > 1 ? args[1] : undefined;
|
|
167
|
+
if (params) {
|
|
168
|
+
sql_step.setTrue(1);
|
|
169
|
+
var crc = {value: 0};
|
|
170
|
+
sql_step.p1 = toParamBytes(psql.param, crc);
|
|
171
|
+
|
|
172
|
+
if (params != undefined) {
|
|
173
|
+
try {
|
|
174
|
+
// Oracle 파라미터는 객체 형태일 수 있음
|
|
175
|
+
let paramStr = '';
|
|
176
|
+
if (typeof params === 'object' && !Array.isArray(params)) {
|
|
177
|
+
paramStr = Object.entries(params).map(([key, value]) => {
|
|
178
|
+
if (typeof value === 'string') {
|
|
179
|
+
return `${key}='${value}'`;
|
|
180
|
+
}
|
|
181
|
+
return `${key}=${value}`;
|
|
182
|
+
}).join(', ');
|
|
183
|
+
} else if (Array.isArray(params)) {
|
|
184
|
+
paramStr = params.map((param) => {
|
|
185
|
+
if (typeof param === 'string') {
|
|
186
|
+
return `'${param}'`;
|
|
187
|
+
}
|
|
188
|
+
return param;
|
|
189
|
+
}).join(', ');
|
|
190
|
+
} else {
|
|
191
|
+
paramStr = String(params);
|
|
192
|
+
}
|
|
193
|
+
sql_step.p2 = toParamBytes(paramStr, crc);
|
|
194
|
+
} catch (e) {
|
|
195
|
+
Logger.printError('WHATAP-112', 'Oracle param processing error', e, false);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
sql_step.pcrc = crc.value;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Check if the last argument is a callback
|
|
203
|
+
var hasCallback = false;
|
|
204
|
+
var callbackIndex = -1;
|
|
205
|
+
|
|
206
|
+
if (args.length > 0 && typeof args[args.length - 1] === 'function') {
|
|
207
|
+
hasCallback = true;
|
|
208
|
+
callbackIndex = args.length - 1;
|
|
209
|
+
|
|
210
|
+
// Wrap callback to capture result
|
|
211
|
+
var originalCallback = args[callbackIndex];
|
|
212
|
+
args[callbackIndex] = function wrappedCallback(err, result) {
|
|
213
|
+
if (ctx == null) {
|
|
214
|
+
return originalCallback.apply(this, arguments);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
TraceContextManager.resume(ctx._id);
|
|
218
|
+
|
|
219
|
+
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
220
|
+
ctx.sql_time += sql_step.elapsed;
|
|
221
|
+
|
|
222
|
+
if (err) {
|
|
223
|
+
errorDelegate(ctx, sql_step)(null, [err]);
|
|
224
|
+
ctx.footprint('Oracle Query Error');
|
|
225
|
+
} else {
|
|
226
|
+
ctx.footprint('Oracle Query Done');
|
|
227
|
+
|
|
228
|
+
// Process result for SELECT queries
|
|
229
|
+
if (result && result.rows && Array.isArray(result.rows) && psql != null && psql.type === 'S') {
|
|
230
|
+
var result_step = new ResultSetStep();
|
|
231
|
+
result_step.start_time = ctx.getElapsedTime();
|
|
232
|
+
result_step.elapsed = 0;
|
|
233
|
+
result_step.fetch = result.rows.length;
|
|
234
|
+
result_step.sqlhash = psql.sql;
|
|
235
|
+
result_step.dbc = dbc_hash;
|
|
236
|
+
ctx.profile.push(result_step);
|
|
237
|
+
|
|
238
|
+
ctx.rs_count = ctx.rs_count ? ctx.rs_count + result.rows.length : result.rows.length;
|
|
239
|
+
ctx.rs_time = ctx.rs_time ? ctx.rs_time + sql_step.elapsed : sql_step.elapsed;
|
|
240
|
+
|
|
241
|
+
MeterSql.addFetch(result_step.dbc, result_step.fetch, 0);
|
|
242
|
+
StatSql.addFetch(result_step.dbc, result_step.sqlhash, result_step.fetch, 0);
|
|
243
|
+
|
|
244
|
+
TraceSQL.isTooManyRecords(sql_step, result_step.fetch, ctx);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Process affectedRows for UPDATE/INSERT/DELETE
|
|
248
|
+
if (result != null && psql != null && (psql.type === 'U' || psql.type === 'I' || psql.type === 'D')) {
|
|
249
|
+
if (result.rowsAffected !== undefined) {
|
|
250
|
+
sql_step.updated = result.rowsAffected || 0;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
MeterSql.add(dbc_hash, sql_step.elapsed, !!err);
|
|
256
|
+
StatSql.addSqlTime(ctx.service_hash, sql_step.dbc,
|
|
257
|
+
sql_step.hash, sql_step.elapsed, !!err, 0);
|
|
258
|
+
|
|
259
|
+
return originalCallback.apply(this, arguments);
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
try {
|
|
264
|
+
// Handle promise-based execution
|
|
265
|
+
if (!hasCallback) {
|
|
266
|
+
return original.apply(this, args)
|
|
267
|
+
.then(function (result) {
|
|
268
|
+
// 성공 처리
|
|
269
|
+
if (ctx == null) {
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
TraceContextManager.resume(ctx._id);
|
|
274
|
+
|
|
275
|
+
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
276
|
+
ctx.sql_time += sql_step.elapsed;
|
|
277
|
+
|
|
278
|
+
TraceSQL.isSlowSQL(ctx);
|
|
279
|
+
|
|
280
|
+
ctx.footprint('Oracle Query Done');
|
|
281
|
+
|
|
282
|
+
MeterSql.add(dbc_hash, sql_step.elapsed, false);
|
|
283
|
+
StatSql.addSqlTime(ctx.service_hash, sql_step.dbc,
|
|
284
|
+
sql_step.hash, sql_step.elapsed, false, 0);
|
|
285
|
+
|
|
286
|
+
if (result && result.rows && Array.isArray(result.rows) && psql != null && psql.type === 'S') {
|
|
287
|
+
var result_step = new ResultSetStep();
|
|
288
|
+
result_step.start_time = ctx.getElapsedTime();
|
|
289
|
+
result_step.elapsed = 0;
|
|
290
|
+
result_step.fetch = result.rows.length;
|
|
291
|
+
result_step.sqlhash = psql.sql;
|
|
292
|
+
result_step.dbc = dbc_hash;
|
|
293
|
+
ctx.profile.push(result_step);
|
|
294
|
+
|
|
295
|
+
ctx.rs_count = ctx.rs_count ? ctx.rs_count + result.rows.length : result.rows.length;
|
|
296
|
+
ctx.rs_time = ctx.rs_time ? ctx.rs_time + sql_step.elapsed : sql_step.elapsed;
|
|
297
|
+
|
|
298
|
+
MeterSql.addFetch(result_step.dbc, result_step.fetch, 0);
|
|
299
|
+
StatSql.addFetch(result_step.dbc, result_step.sqlhash, result_step.fetch, 0);
|
|
300
|
+
|
|
301
|
+
TraceSQL.isTooManyRecords(sql_step, result_step.fetch, ctx);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (result != null && psql != null && (psql.type === 'U' || psql.type === 'I' || psql.type === 'D')) {
|
|
305
|
+
if (result.rowsAffected !== undefined) {
|
|
306
|
+
sql_step.updated = result.rowsAffected || 0;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return result;
|
|
311
|
+
})
|
|
312
|
+
.catch(function (error) {
|
|
313
|
+
if (ctx == null) {
|
|
314
|
+
throw error;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
TraceContextManager.resume(ctx._id);
|
|
318
|
+
errorDelegate(ctx, sql_step)(null, [error]);
|
|
319
|
+
|
|
320
|
+
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
321
|
+
ctx.sql_time += sql_step.elapsed;
|
|
322
|
+
|
|
323
|
+
ctx.footprint('Oracle Query Error');
|
|
324
|
+
|
|
325
|
+
MeterSql.add(dbc_hash, sql_step.elapsed, true);
|
|
326
|
+
StatSql.addSqlTime(ctx.service_hash, sql_step.dbc,
|
|
327
|
+
sql_step.hash, sql_step.elapsed, true, 0);
|
|
328
|
+
|
|
329
|
+
throw error;
|
|
330
|
+
});
|
|
331
|
+
} else {
|
|
332
|
+
return original.apply(this, args);
|
|
333
|
+
}
|
|
334
|
+
} catch (err) {
|
|
335
|
+
if (ctx != null) {
|
|
336
|
+
errorDelegate(ctx, sql_step)(null, [err]);
|
|
337
|
+
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
338
|
+
ctx.sql_time += sql_step.elapsed;
|
|
339
|
+
ctx.footprint('Oracle Query Error');
|
|
340
|
+
|
|
341
|
+
MeterSql.add(dbc_hash, sql_step.elapsed, true);
|
|
342
|
+
StatSql.addSqlTime(ctx.service_hash, sql_step.dbc,
|
|
343
|
+
sql_step.hash, sql_step.elapsed, true, 0);
|
|
344
|
+
}
|
|
345
|
+
throw err;
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
OracleObserver.prototype.inject = function (mod, moduleName) {
|
|
353
|
+
if (mod.__whatap_observe__) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
mod.__whatap_observe__ = true;
|
|
357
|
+
Logger.initPrint("OracleObserver");
|
|
358
|
+
|
|
359
|
+
var self = this;
|
|
360
|
+
|
|
361
|
+
if (conf.sql_enabled === false) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
shimmer.wrap(mod, 'getConnection', function (original) {
|
|
366
|
+
return function () {
|
|
367
|
+
var args = Array.from(arguments);
|
|
368
|
+
var connectionInfo = args[0] || {};
|
|
369
|
+
var ctx = TraceContextManager.getCurrentContext();
|
|
370
|
+
|
|
371
|
+
var connectInfo = connectionInfo.connectString || connectionInfo.connectionString || '';
|
|
372
|
+
var user = connectionInfo.user || '';
|
|
373
|
+
var dbc = 'oracle://' + user + '@' + connectInfo;
|
|
374
|
+
var dbc_hash = HashUtil.hashFromString(dbc);
|
|
375
|
+
|
|
376
|
+
DataTextAgent.DBC.add(dbc_hash, dbc);
|
|
377
|
+
DataTextAgent.METHOD.add(dbc_hash, dbc);
|
|
378
|
+
DataTextAgent.ERROR.add(dbc_hash, dbc);
|
|
379
|
+
|
|
380
|
+
var dbc_step = null;
|
|
381
|
+
|
|
382
|
+
if (ctx) {
|
|
383
|
+
dbc_step = new DBCStep();
|
|
384
|
+
dbc_step.start_time = ctx.getElapsedTime();
|
|
385
|
+
dbc_step.hash = dbc_hash;
|
|
386
|
+
|
|
387
|
+
ctx.footprint('Oracle Connecting Start');
|
|
388
|
+
ctx.db_opening = true;
|
|
389
|
+
ctx.profile.push(dbc_step);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
if (arguments.length > 0 && typeof arguments[arguments.length - 1] === 'function') {
|
|
393
|
+
var callbackIndex = arguments.length - 1;
|
|
394
|
+
var originalCallback = arguments[callbackIndex];
|
|
395
|
+
|
|
396
|
+
arguments[callbackIndex] = function wrappedCallback(err, connection) {
|
|
397
|
+
if (ctx) {
|
|
398
|
+
TraceContextManager.resume(ctx._id);
|
|
399
|
+
|
|
400
|
+
if (err) {
|
|
401
|
+
ctx.footprint('Oracle Connecting Error');
|
|
402
|
+
if (dbc_step) {
|
|
403
|
+
dbc_step.error = StatError.addError('oracle-' + (err.errorNum || 'ERROR'),
|
|
404
|
+
err.message || 'Oracle connection error', ctx.service_hash);
|
|
405
|
+
}
|
|
406
|
+
} else {
|
|
407
|
+
ctx.footprint('Oracle Connecting Done');
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
ctx.db_opening = false;
|
|
411
|
+
|
|
412
|
+
if (dbc_step) {
|
|
413
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (connection) {
|
|
418
|
+
connectionAttributes.set(connection, connectionInfo);
|
|
419
|
+
self._wrapPoolOrConnection(connection, dbc);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return originalCallback.apply(this, arguments);
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
return original.apply(this, arguments);
|
|
426
|
+
} else {
|
|
427
|
+
return original.apply(this, args)
|
|
428
|
+
.then(function (connection) {
|
|
429
|
+
if (ctx) {
|
|
430
|
+
TraceContextManager.resume(ctx._id);
|
|
431
|
+
ctx.footprint('Oracle Connecting Done');
|
|
432
|
+
ctx.db_opening = false;
|
|
433
|
+
|
|
434
|
+
if (dbc_step) {
|
|
435
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (connection) {
|
|
440
|
+
connectionAttributes.set(connection, connectionInfo);
|
|
441
|
+
self._wrapPoolOrConnection(connection, dbc);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return connection;
|
|
445
|
+
})
|
|
446
|
+
.catch(function (err) {
|
|
447
|
+
if (ctx) {
|
|
448
|
+
TraceContextManager.resume(ctx._id);
|
|
449
|
+
ctx.footprint('Oracle Connecting Error');
|
|
450
|
+
ctx.db_opening = false;
|
|
451
|
+
|
|
452
|
+
if (dbc_step) {
|
|
453
|
+
dbc_step.error = StatError.addError('oracle-' + (err.errorNum || 'ERROR'),
|
|
454
|
+
err.message || 'Oracle connection error', ctx.service_hash);
|
|
455
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
throw err;
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
shimmer.wrap(mod, 'createPool', function (original) {
|
|
466
|
+
return function () {
|
|
467
|
+
var args = Array.from(arguments);
|
|
468
|
+
var poolAttrs = args[0] || {};
|
|
469
|
+
|
|
470
|
+
// Handle callback-style
|
|
471
|
+
if (args.length > 0 && typeof args[args.length - 1] === 'function') {
|
|
472
|
+
var callbackIndex = args.length - 1;
|
|
473
|
+
var originalCallback = args[callbackIndex];
|
|
474
|
+
|
|
475
|
+
args[callbackIndex] = function wrappedCallback(err, pool) {
|
|
476
|
+
if (pool) {
|
|
477
|
+
poolAttributes.set(pool, poolAttrs);
|
|
478
|
+
// Wrap Pool's getConnection method after pool is created
|
|
479
|
+
shimmer.wrap(pool, 'getConnection', function(originalGetConn) {
|
|
480
|
+
return self._wrapPoolGetConnection(originalGetConn, poolAttrs);
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
return originalCallback.apply(this, arguments);
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
return original.apply(this, args);
|
|
488
|
+
} else {
|
|
489
|
+
return original.apply(this, args)
|
|
490
|
+
.then(function(pool) {
|
|
491
|
+
if (pool) {
|
|
492
|
+
poolAttributes.set(pool, poolAttrs);
|
|
493
|
+
shimmer.wrap(pool, 'getConnection', function(originalGetConn) {
|
|
494
|
+
return self._wrapPoolGetConnection(originalGetConn, poolAttrs);
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
return pool;
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
if (mod.Pool && mod.Pool.prototype) {
|
|
504
|
+
shimmer.wrap(mod.Pool.prototype, 'getConnection', function(original) {
|
|
505
|
+
return self._wrapPoolGetConnection(original);
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
OracleObserver.prototype._wrapPoolGetConnection = function(originalGetConn, poolAttrs) {
|
|
511
|
+
var self = this;
|
|
512
|
+
|
|
513
|
+
return function wrappedGetConnection() {
|
|
514
|
+
var args = Array.from(arguments);
|
|
515
|
+
var ctx = TraceContextManager.getCurrentContext();
|
|
516
|
+
|
|
517
|
+
var poolInfo = poolAttrs || poolAttributes.get(this) || {};
|
|
518
|
+
var connectInfo = poolInfo.connectString || poolInfo.connectionString || '';
|
|
519
|
+
var user = poolInfo.user || '';
|
|
520
|
+
var dbc = 'oracle://' + user + '@' + connectInfo;
|
|
521
|
+
var dbc_hash = HashUtil.hashFromString(dbc);
|
|
522
|
+
|
|
523
|
+
DataTextAgent.DBC.add(dbc_hash, dbc);
|
|
524
|
+
DataTextAgent.METHOD.add(dbc_hash, dbc);
|
|
525
|
+
DataTextAgent.ERROR.add(dbc_hash, dbc);
|
|
526
|
+
|
|
527
|
+
var dbc_step = null;
|
|
528
|
+
|
|
529
|
+
if (ctx) {
|
|
530
|
+
dbc_step = new DBCStep();
|
|
531
|
+
dbc_step.start_time = ctx.getElapsedTime();
|
|
532
|
+
dbc_step.hash = dbc_hash;
|
|
533
|
+
|
|
534
|
+
ctx.footprint('Oracle Pool Connection Start');
|
|
535
|
+
ctx.db_opening = true;
|
|
536
|
+
ctx.profile.push(dbc_step);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
if (args.length > 0 && typeof args[args.length - 1] === 'function') {
|
|
540
|
+
var callbackIndex = args.length - 1;
|
|
541
|
+
var originalCallback = args[callbackIndex];
|
|
542
|
+
|
|
543
|
+
args[callbackIndex] = function(err, connection) {
|
|
544
|
+
if (ctx) {
|
|
545
|
+
TraceContextManager.resume(ctx._id);
|
|
546
|
+
|
|
547
|
+
if (err) {
|
|
548
|
+
ctx.footprint('Oracle Pool Connection Error');
|
|
549
|
+
if (dbc_step) {
|
|
550
|
+
dbc_step.error = StatError.addError('oracle-' + (err.errorNum || 'ERROR'),
|
|
551
|
+
err.message || 'Oracle connection error', ctx.service_hash);
|
|
552
|
+
}
|
|
553
|
+
} else {
|
|
554
|
+
ctx.footprint('Oracle Pool Connection Done');
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
ctx.db_opening = false;
|
|
558
|
+
|
|
559
|
+
if (dbc_step) {
|
|
560
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (connection) {
|
|
565
|
+
connectionAttributes.set(connection, poolInfo);
|
|
566
|
+
self._wrapPoolOrConnection(connection, dbc);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return originalCallback.apply(this, arguments);
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
return originalGetConn.apply(this, args);
|
|
573
|
+
} else {
|
|
574
|
+
return originalGetConn.apply(this, args)
|
|
575
|
+
.then(function(connection) {
|
|
576
|
+
if (ctx) {
|
|
577
|
+
TraceContextManager.resume(ctx._id);
|
|
578
|
+
ctx.footprint('Oracle Pool Connection Done');
|
|
579
|
+
ctx.db_opening = false;
|
|
580
|
+
|
|
581
|
+
if (dbc_step) {
|
|
582
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
if (connection) {
|
|
587
|
+
connectionAttributes.set(connection, poolInfo);
|
|
588
|
+
self._wrapPoolOrConnection(connection, dbc);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
return connection;
|
|
592
|
+
})
|
|
593
|
+
.catch(function(err) {
|
|
594
|
+
if (ctx) {
|
|
595
|
+
TraceContextManager.resume(ctx._id);
|
|
596
|
+
ctx.footprint('Oracle Pool Connection Error');
|
|
597
|
+
ctx.db_opening = false;
|
|
598
|
+
|
|
599
|
+
if (dbc_step) {
|
|
600
|
+
dbc_step.error = StatError.addError('oracle-' + (err.errorNum || 'ERROR'),
|
|
601
|
+
err.message || 'Oracle connection error', ctx.service_hash);
|
|
602
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
throw err;
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
var checkedSql = new IntKeyMap(2000).setMax(2000);
|
|
613
|
+
var nonLiteSql = new IntKeyMap(5000).setMax(5000);
|
|
614
|
+
var date = DateUtil.yyyymmdd();
|
|
615
|
+
|
|
616
|
+
function escapeLiteral(sql) {
|
|
617
|
+
if (sql == null) {
|
|
618
|
+
sql = '';
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
if (date !== DateUtil.yyyymmdd()) {
|
|
622
|
+
checkedSql.clear();
|
|
623
|
+
nonLiteSql.clear();
|
|
624
|
+
date = DateUtil.yyyymmdd();
|
|
625
|
+
Logger.print('WHATAP-SQL-CLEAR', 'OracleObserver CLEAR SQL Cache', false);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
var sqlHash = HashUtil.hashFromString(sql);
|
|
629
|
+
var psql = nonLiteSql.get(sqlHash);
|
|
630
|
+
|
|
631
|
+
if (psql != null) {
|
|
632
|
+
return psql;
|
|
633
|
+
}
|
|
634
|
+
psql = checkedSql.get(sqlHash);
|
|
635
|
+
|
|
636
|
+
if (psql != null) {
|
|
637
|
+
return psql;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
var els = new EscapeLiteralSQL(sql);
|
|
641
|
+
els.process();
|
|
642
|
+
|
|
643
|
+
var hash = HashUtil.hashFromString(els.getParsedSql());
|
|
644
|
+
DataTextAgent.SQL.add(hash, els.getParsedSql());
|
|
645
|
+
|
|
646
|
+
if (hash === sqlHash) {
|
|
647
|
+
psql = new ParsedSql(els.sqlType, hash, null);
|
|
648
|
+
nonLiteSql.put(sqlHash, psql);
|
|
649
|
+
} else {
|
|
650
|
+
psql = new ParsedSql(els.sqlType, hash, els.getParameter());
|
|
651
|
+
checkedSql.put(sqlHash, psql);
|
|
652
|
+
}
|
|
653
|
+
return psql;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
exports.OracleObserver = OracleObserver;
|