whatap 1.0.1 → 1.0.2
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/README.md +32 -78
- package/lib/conf/conf-sys-mon.js +101 -0
- package/lib/conf/config-default.js +10 -3
- package/lib/conf/configure.js +369 -349
- package/lib/conf/license.js +1 -1
- package/lib/control/cmd-config.js +24 -0
- package/lib/control/control-handler.js +367 -0
- package/lib/control/packagectr-helper.js +34 -3
- package/lib/core/agent.js +176 -882
- package/lib/core/interceptor.js +6 -6
- package/lib/core/request-agent.js +27 -0
- package/lib/core/shimmer.js +82 -36
- package/lib/counter/counter-manager.js +79 -8
- package/lib/counter/meter/meter-activex.js +67 -0
- package/lib/counter/meter/meter-httpc.js +57 -0
- package/lib/counter/meter/meter-resource.js +9 -0
- package/lib/counter/meter/meter-service.js +168 -0
- package/lib/counter/meter/meter-socket.io.js +51 -0
- package/lib/counter/meter/meter-sql.js +71 -0
- package/lib/counter/meter/meter-users.js +58 -0
- package/lib/counter/meter.js +183 -0
- package/lib/counter/task/activetransaction.js +68 -17
- package/lib/counter/task/agentinfo.js +107 -0
- package/lib/{system → counter/task}/gc-action.js +27 -74
- package/lib/counter/task/gcstat.js +34 -0
- package/lib/counter/task/heapmem.js +25 -0
- package/lib/counter/task/httpc.js +76 -0
- package/lib/counter/task/metering-info.js +125 -0
- package/lib/counter/task/proc-cpu.js +29 -0
- package/lib/counter/task/realtimeuser.js +31 -0
- package/lib/counter/task/res/systemECSTask.js +39 -0
- package/lib/counter/task/res/systemKubeTask.js +53 -0
- package/lib/counter/task/res/util/awsEcsClientThread.js +218 -0
- package/lib/counter/task/res/util/linuxProcStatUtil.js +14 -0
- package/lib/counter/task/res-sys-cpu.js +62 -0
- package/lib/counter/task/service.js +202 -0
- package/lib/counter/task/socketio.js +30 -0
- package/lib/counter/task/sql.js +105 -0
- package/lib/counter/task/systemperf.js +43 -0
- package/lib/data/datapack-sender.js +289 -0
- package/lib/data/dataprofile-agent.js +162 -0
- package/lib/data/datatext-agent.js +135 -0
- package/lib/data/event-level.js +15 -0
- package/lib/data/test.js +49 -0
- package/lib/data/zipprofile.js +197 -0
- package/lib/env/constants.js +21 -0
- package/lib/error/error-handler.js +437 -0
- package/lib/io/data-inputx.js +13 -3
- package/lib/io/data-outputx.js +268 -206
- package/lib/kube/kube-client.js +144 -0
- package/lib/lang/text-types.js +58 -0
- package/lib/logger.js +6 -6
- package/lib/logsink/line-log-util.js +87 -0
- package/lib/logsink/line-log.js +12 -0
- package/lib/logsink/log-sender.js +78 -0
- package/lib/logsink/log-tracer.js +40 -0
- package/lib/logsink/sender-util.js +56 -0
- package/lib/logsink/zip/zip-send.js +177 -0
- package/lib/net/netflag.js +55 -0
- package/lib/net/receiver.js +66 -0
- package/lib/net/security-master.js +139 -20
- package/lib/net/sender.js +141 -0
- package/lib/net/tcp-return.js +18 -0
- package/lib/net/tcp-session.js +286 -0
- package/lib/net/tcpreq-client-proxy.js +70 -0
- package/lib/net/tcprequest-mgr.js +58 -0
- package/lib/observers/apollo-server-observer.js +33 -27
- package/lib/observers/cluster-observer.js +22 -0
- package/lib/observers/express-observer.js +215 -0
- package/lib/observers/file-observer.js +184 -0
- package/lib/observers/global-observer.js +155 -80
- package/lib/observers/grpc-observer.js +336 -0
- package/lib/observers/http-observer.js +666 -236
- package/lib/observers/maria-observer.js +204 -362
- package/lib/observers/memcached-observer.js +56 -0
- package/lib/observers/mongo-observer.js +317 -0
- package/lib/observers/mongodb-observer.js +169 -226
- package/lib/observers/mongoose-observer.js +518 -323
- package/lib/observers/mssql-observer.js +177 -418
- package/lib/observers/mysql-observer.js +342 -449
- package/lib/observers/mysql2-observer.js +396 -358
- package/lib/observers/net-observer.js +77 -0
- package/lib/observers/oracle-observer.js +559 -384
- package/lib/observers/pgsql-observer.js +231 -489
- package/lib/observers/prisma-observer.js +303 -92
- package/lib/observers/process-observer.js +79 -35
- package/lib/observers/promise-observer.js +31 -0
- package/lib/observers/redis-observer.js +166 -331
- package/lib/observers/schedule-observer.js +67 -0
- package/lib/observers/socket.io-observer.js +226 -187
- package/lib/observers/stream-observer.js +19 -0
- package/lib/observers/thrift-observer.js +197 -0
- package/lib/observers/websocket-observer.js +175 -301
- package/lib/pack/activestack-pack.js +55 -0
- package/lib/pack/apenum.js +8 -0
- package/lib/pack/counter-pack.js +3 -0
- package/lib/pack/errorsnap-pack.js +69 -0
- package/lib/pack/event-pack.js +54 -0
- package/lib/pack/hitmap-pack.js +63 -0
- package/lib/pack/hitmap-pack1.js +152 -0
- package/lib/pack/log-sink-pack.js +14 -52
- package/lib/pack/netstat.js +15 -0
- package/lib/pack/otype.js +7 -0
- package/lib/pack/profile-pack.js +49 -0
- package/lib/pack/realtimeuser-pack.js +41 -0
- package/lib/pack/stat-general-pack.js +96 -0
- package/lib/pack/staterror-pack.js +120 -0
- package/lib/pack/stathttpc-pack.js +66 -0
- package/lib/pack/stathttpc-rec.js +78 -0
- package/lib/pack/statremote-pack.js +46 -0
- package/lib/pack/statservice-pack.js +63 -0
- package/lib/pack/statservice-pack1.js +88 -0
- package/lib/pack/statservice-rec.js +292 -0
- package/lib/pack/statservice-rec_dep.js +151 -0
- package/lib/pack/statsql-pack.js +69 -0
- package/lib/pack/statsql-rec.js +100 -0
- package/lib/pack/statuseragent-pack.js +44 -0
- package/lib/pack/tagcount-pack.js +4 -4
- package/lib/pack/tagctr.js +15 -0
- package/lib/pack/text-pack.js +50 -0
- package/lib/pack/time-count.js +25 -0
- package/lib/pack/websocket.js +15 -0
- package/lib/pack/zip-pack.js +70 -0
- package/lib/pii/pii-item.js +31 -0
- package/lib/pii/pii-mask.js +174 -0
- package/lib/plugin/plugin-loadermanager.js +57 -0
- package/lib/plugin/plugin.js +75 -0
- package/lib/service/tx-record.js +332 -0
- package/lib/stat/stat-error.js +116 -0
- package/lib/stat/stat-httpc.js +98 -0
- package/lib/stat/stat-remote-ip.js +46 -0
- package/lib/stat/stat-remote-ipurl.js +88 -0
- package/lib/stat/stat-sql.js +113 -0
- package/lib/stat/stat-tranx.js +58 -0
- package/lib/stat/stat-tx-caller.js +160 -0
- package/lib/stat/stat-tx-domain.js +111 -0
- package/lib/stat/stat-tx-referer.js +112 -0
- package/lib/stat/stat-useragent.js +48 -0
- package/lib/stat/timingsender.js +76 -0
- package/lib/step/activestack-step.js +38 -0
- package/lib/step/dbc-step.js +36 -0
- package/lib/step/http-stepx.js +67 -0
- package/lib/step/message-step.js +40 -0
- package/lib/step/method-stepx.js +45 -0
- package/lib/step/resultset-step.js +40 -0
- package/lib/step/securemsg-step.js +44 -0
- package/lib/step/socket-step.js +46 -0
- package/lib/step/sql-stepx.js +68 -0
- package/lib/step/sqlxtype.js +16 -0
- package/lib/step/step.js +66 -0
- package/lib/step/stepenum.js +54 -0
- package/lib/topology/link.js +63 -0
- package/lib/topology/nodeinfo.js +123 -0
- package/lib/topology/status-detector.js +111 -0
- package/lib/trace/trace-context-manager.js +113 -25
- package/lib/trace/trace-context.js +21 -7
- package/lib/trace/trace-httpc.js +17 -11
- package/lib/trace/trace-sql.js +29 -21
- package/lib/util/anylist.js +103 -0
- package/lib/util/cardinality/hyperloglog.js +106 -0
- package/lib/util/cardinality/murmurhash.js +31 -0
- package/lib/util/cardinality/registerset.js +75 -0
- package/lib/util/errordata.js +21 -0
- package/lib/util/escape-literal-sql.js +5 -5
- package/lib/util/hashutil.js +18 -18
- package/lib/util/iputil_x.js +527 -0
- package/lib/util/keygen.js +0 -3
- package/lib/util/kube-util.js +73 -0
- package/lib/util/linkedset.js +1 -2
- package/lib/util/nodeutil.js +2 -1
- package/lib/util/paramsecurity.js +80 -0
- package/lib/util/pre-process.js +13 -0
- package/lib/util/process-seq.js +166 -0
- package/lib/util/property-util.js +36 -0
- package/lib/util/request-queue.js +70 -0
- package/lib/util/requestdouble-queue.js +72 -0
- package/lib/util/resourceprofile.js +157 -0
- package/lib/util/stop-watch.js +30 -0
- package/lib/util/system-util.js +10 -0
- package/lib/util/userid-util.js +57 -0
- package/lib/value/map-value.js +3 -2
- package/package.json +9 -4
- package/whatap.conf +1 -4
- package/agent/darwin/arm64/whatap_nodejs +0 -0
- package/agent/linux/amd64/whatap_nodejs +0 -0
- package/agent/linux/arm64/whatap_nodejs +0 -0
- package/build.txt +0 -4
- package/lib/observers/ioredis-observer.js +0 -294
- package/lib/udp/async_sender.js +0 -119
- package/lib/udp/index.js +0 -17
- package/lib/udp/packet_enum.js +0 -52
- package/lib/udp/packet_queue.js +0 -69
- package/lib/udp/packet_type_enum.js +0 -33
- package/lib/udp/param_def.js +0 -72
- package/lib/udp/udp_session.js +0 -336
- package/lib/util/sql-util.js +0 -178
- package/lib/util/trace-helper.js +0 -91
- package/lib/util/transfer.js +0 -58
|
@@ -6,306 +6,350 @@
|
|
|
6
6
|
|
|
7
7
|
var TraceContextManager = require('../trace/trace-context-manager'),
|
|
8
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'),
|
|
9
15
|
conf = require('../conf/configure'),
|
|
10
16
|
IntKeyMap = require('../util/intkey-map'),
|
|
11
17
|
EscapeLiteralSQL = require('../util/escape-literal-sql'),
|
|
12
18
|
HashUtil = require('../util/hashutil'),
|
|
19
|
+
StatError = require('../stat/stat-error'),
|
|
20
|
+
TextTypes = require('../lang/text-types'),
|
|
21
|
+
ParamSecurity = require('../util/paramsecurity'),
|
|
13
22
|
Logger = require('../logger'),
|
|
14
23
|
DateUtil = require('../util/dateutil'),
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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();
|
|
20
31
|
|
|
21
32
|
var OracleObserver = function (agent) {
|
|
22
33
|
this.agent = agent;
|
|
23
34
|
this.packages = ['oracledb'];
|
|
24
35
|
};
|
|
25
36
|
|
|
26
|
-
|
|
27
|
-
var
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
var checkedSql = new IntKeyMap(2000).setMax(2000);
|
|
32
|
-
var nonLiteSql = new IntKeyMap(5000).setMax(5000);
|
|
33
|
-
var date = DateUtil.yyyymmdd();
|
|
34
|
-
|
|
35
|
-
function handleSqlError(ctx, err) {
|
|
36
|
-
if (!err) return;
|
|
37
|
-
|
|
37
|
+
// 쿼리 파라미터를 바이트 배열로 변환
|
|
38
|
+
var toParamBytes = function (p, crc) {
|
|
39
|
+
if (p == null || p.length === 0) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
38
42
|
try {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
var traceDepth = conf.trace_sql_error_depth;
|
|
45
|
-
var stackLines = err.stack.split("\n");
|
|
46
|
-
if (stackLines.length > traceDepth) {
|
|
47
|
-
stackLines = stackLines.slice(0, traceDepth + 1);
|
|
48
|
-
}
|
|
49
|
-
errorStack = stackLines.join("\n");
|
|
50
|
-
}
|
|
43
|
+
return ParamSecurity.encrypt(Buffer.from(p, 'utf8'), crc);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
} else if (conf._is_trace_ignore_err_msg_contains === true && errorMessage &&
|
|
57
|
-
errorMessage.indexOf(conf.trace_ignore_err_msg_contains) < 0) {
|
|
58
|
-
shouldAddError = true;
|
|
59
|
-
} else if (conf._is_trace_ignore_err_cls_contains === false &&
|
|
60
|
-
conf._is_trace_ignore_err_msg_contains === false) {
|
|
61
|
-
shouldAddError = true;
|
|
49
|
+
var errorDelegate = function (ctx, step) {
|
|
50
|
+
return function (obj, args) {
|
|
51
|
+
if (ctx == null) {
|
|
52
|
+
return;
|
|
62
53
|
}
|
|
63
54
|
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (errorMessage) {
|
|
69
|
-
errors.push(errorMessage);
|
|
70
|
-
}
|
|
71
|
-
if (errorStack || err.stack) {
|
|
72
|
-
errors.push(errorStack || err.stack);
|
|
55
|
+
if (step == null) {
|
|
56
|
+
var laststep = ctx.profile.getLastSteps(1);
|
|
57
|
+
if (laststep == null || laststep.length === 0) {
|
|
58
|
+
return;
|
|
73
59
|
}
|
|
74
|
-
|
|
75
|
-
AsyncSender.send_packet(PacketTypeEnum.TX_ERROR, ctx, errors);
|
|
60
|
+
step = laststep[0];
|
|
76
61
|
}
|
|
77
|
-
} catch (e) {
|
|
78
|
-
Logger.printError('WHATAP-251', 'Error handling Oracle error', e, false);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
62
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
var connectInfo = connectionInfo.connectString || connectionInfo.connectionString || '';
|
|
85
|
-
var user = connectionInfo.user || '';
|
|
86
|
-
dbc = 'oracle://' + user + '@' + connectInfo;
|
|
87
|
-
dbc_hash = HashUtil.hashFromString(dbc);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
63
|
+
MeterSql.add(step.dbc, step.elapsed, true);
|
|
64
|
+
StatSql.addSqlTime(ctx.service_hash, step.dbc, step.hash, step.elapsed, true, 0);
|
|
90
65
|
|
|
91
|
-
|
|
92
|
-
if (connection && !hookedInstances.has(connection)) {
|
|
93
|
-
hookedInstances.add(connection);
|
|
94
|
-
Logger.print('WHATAP-ORACLE-CONNECTION', 'Hooking new Oracle connection object', false);
|
|
66
|
+
ctx.error_class = args[0].name || args[0].constructor?.name || 'OracleError';
|
|
95
67
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
68
|
+
try {
|
|
69
|
+
var errorCode = args[0].errorNum || args[0].code || 'ORA-00000';
|
|
70
|
+
var errorMsg = ctx.error_message = args[0].message || 'Oracle error';
|
|
102
71
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
72
|
+
if (conf._is_trace_ignore_err_cls_contains === true && errorCode.toString().indexOf(conf.trace_ignore_err_cls_contains) < 0) {
|
|
73
|
+
step.error = StatError.addError('oracle-' + errorCode, errorMsg, ctx.service_hash, TextTypes.SQL, step.hash);
|
|
74
|
+
if (ctx.error.isZero()) {
|
|
75
|
+
ctx.error = step.error;
|
|
76
|
+
}
|
|
77
|
+
} else if (conf._is_trace_ignore_err_msg_contains === true && errorMsg.indexOf(conf.trace_ignore_err_msg_contains) < 0) {
|
|
78
|
+
step.error = StatError.addError('oracle-' + errorCode, errorMsg, ctx.service_hash, TextTypes.SQL, step.hash);
|
|
79
|
+
if (ctx.error.isZero()) {
|
|
80
|
+
ctx.error = step.error;
|
|
81
|
+
}
|
|
82
|
+
} else if (conf._is_trace_ignore_err_cls_contains === false && conf._is_trace_ignore_err_msg_contains === false) {
|
|
83
|
+
step.error = StatError.addError('oracle-' + errorCode, errorMsg, ctx.service_hash, TextTypes.SQL, step.hash);
|
|
84
|
+
if (ctx.error.isZero()) {
|
|
85
|
+
ctx.error = step.error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
113
88
|
|
|
114
|
-
|
|
115
|
-
|
|
89
|
+
if (conf.trace_sql_error_stack && conf.trace_sql_error_depth) {
|
|
90
|
+
var traceDepth = conf.trace_sql_error_depth;
|
|
91
|
+
if (args[0].stack) {
|
|
92
|
+
var errorStack = args[0].stack.split("\n");
|
|
93
|
+
if (errorStack.length > traceDepth) {
|
|
94
|
+
errorStack = errorStack.slice(0, traceDepth + 1);
|
|
95
|
+
}
|
|
96
|
+
ctx.error_message = errorStack.join("\n");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} catch (e) {
|
|
100
|
+
Logger.printError('WHATAP-110', 'OracleObserver error delegate exception', e, false);
|
|
101
|
+
ctx.error_message = 'Oracle error processing failed';
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
};
|
|
116
105
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
psql = checkedSql.get(sqlHash);
|
|
106
|
+
// 커넥션 풀 관리 함수
|
|
107
|
+
OracleObserver.prototype._wrapPoolOrConnection = function (obj, dbc) {
|
|
108
|
+
var self = this;
|
|
121
109
|
|
|
122
|
-
if (
|
|
123
|
-
return
|
|
110
|
+
if (obj.__whatap_observed) {
|
|
111
|
+
return;
|
|
124
112
|
}
|
|
113
|
+
obj.__whatap_observed = true;
|
|
125
114
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
psql = new ParsedSql(els.sqlType, hash, null);
|
|
133
|
-
nonLiteSql.put(sqlHash, psql);
|
|
134
|
-
} else {
|
|
135
|
-
psql = new ParsedSql(els.sqlType, hash, els.getParameter());
|
|
136
|
-
checkedSql.put(sqlHash, psql);
|
|
137
|
-
}
|
|
138
|
-
return psql;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
var createExecuteWrapper = function(agent, dbcUrl) {
|
|
142
|
-
return function(original) {
|
|
143
|
-
return function wrappedExecute() {
|
|
144
|
-
var args = Array.prototype.slice.call(arguments);
|
|
145
|
-
var ctx = TraceContextManager.getCurrentContext();
|
|
115
|
+
// execute 메소드 래핑
|
|
116
|
+
if (obj.execute && typeof obj.execute === 'function') {
|
|
117
|
+
shimmer.wrap(obj, 'execute', function (original) {
|
|
118
|
+
return function () {
|
|
119
|
+
var ctx = TraceContextManager.getCurrentContext();
|
|
120
|
+
var args = Array.from(arguments);
|
|
146
121
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
122
|
+
if (ctx == null || args.length === 0) {
|
|
123
|
+
return original.apply(this, args);
|
|
124
|
+
}
|
|
150
125
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
126
|
+
var sql = args[0];
|
|
127
|
+
if (sql == null) {
|
|
128
|
+
return original.apply(this, args);
|
|
129
|
+
}
|
|
154
130
|
|
|
155
|
-
|
|
156
|
-
|
|
131
|
+
// DBC 단계 생성
|
|
132
|
+
var dbc_hash = HashUtil.hashFromString(dbc);
|
|
157
133
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
134
|
+
// SQL 단계 생성
|
|
135
|
+
var sql_step = new SqlStepX();
|
|
136
|
+
sql_step.start_time = ctx.getElapsedTime();
|
|
137
|
+
ctx.profile.push(sql_step);
|
|
162
138
|
|
|
163
|
-
var sql_start_time = Date.now();
|
|
164
139
|
ctx.footprint('Oracle Query Start');
|
|
165
140
|
ctx.sql_count++;
|
|
166
141
|
|
|
167
|
-
var sql = args.length > 0 ? args[0] : undefined;
|
|
168
|
-
var params = args.length > 1 ? args[1] : null;
|
|
169
|
-
var finalSql = '';
|
|
170
|
-
|
|
171
|
-
try {
|
|
172
|
-
if (typeof sql === 'string') {
|
|
173
|
-
finalSql = sql;
|
|
174
|
-
|
|
175
|
-
// Oracle 파라미터 치환 (:name 형태)
|
|
176
|
-
if (params && typeof params === 'object') {
|
|
177
|
-
if (Array.isArray(params)) {
|
|
178
|
-
// 배열 형태 파라미터 [value1, value2, ...]
|
|
179
|
-
params.forEach((param, index) => {
|
|
180
|
-
const placeholder = ':' + (index + 1);
|
|
181
|
-
const value = param === null ? 'NULL' :
|
|
182
|
-
typeof param === 'string' ? `'${param.replace(/'/g, "''")}'` :
|
|
183
|
-
String(param);
|
|
184
|
-
finalSql = finalSql.replace(new RegExp(':' + (index + 1) + '\\b', 'g'), value);
|
|
185
|
-
});
|
|
186
|
-
} else {
|
|
187
|
-
// 객체 형태 파라미터 {name: value, id: value}
|
|
188
|
-
Object.keys(params).forEach(key => {
|
|
189
|
-
const placeholder = ':' + key;
|
|
190
|
-
const value = params[key] === null ? 'NULL' :
|
|
191
|
-
typeof params[key] === 'string' ? `'${params[key].replace(/'/g, "''")}'` :
|
|
192
|
-
String(params[key]);
|
|
193
|
-
finalSql = finalSql.replace(new RegExp(':' + key + '\\b', 'g'), value);
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
} catch (formatError) {
|
|
199
|
-
Logger.printError('WHATAP-ORACLE-FORMAT', 'Error formatting Oracle query', formatError, false);
|
|
200
|
-
if (typeof sql === 'string') {
|
|
201
|
-
finalSql = sql;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (typeof finalSql !== 'string' || finalSql.length === 0) {
|
|
206
|
-
finalSql = '';
|
|
207
|
-
}
|
|
208
|
-
|
|
209
142
|
var psql = null;
|
|
210
|
-
if (typeof
|
|
143
|
+
if (typeof sql === 'string' && sql.length > 0) {
|
|
211
144
|
try {
|
|
212
|
-
psql = escapeLiteral(
|
|
213
|
-
Logger.print('WHATAP-SQL-DEBUG', 'Processing SQL: ' + finalSql.substring(0, 200), false);
|
|
145
|
+
psql = escapeLiteral(sql);
|
|
214
146
|
} catch (e) {
|
|
215
|
-
Logger.printError('WHATAP-
|
|
147
|
+
Logger.printError('WHATAP-111', 'OracleObserver escapeliteral error', e, false);
|
|
216
148
|
}
|
|
217
149
|
} else {
|
|
218
|
-
|
|
150
|
+
sql = '';
|
|
151
|
+
psql = escapeLiteral(sql);
|
|
219
152
|
}
|
|
220
153
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (currentCtx == null) {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
154
|
+
if (psql != null) {
|
|
155
|
+
sql_step.hash = psql.sql;
|
|
156
|
+
// sql_step.crud = psql.type.charCodeAt(0);
|
|
157
|
+
}
|
|
158
|
+
sql_step.dbc = dbc_hash;
|
|
229
159
|
|
|
230
|
-
|
|
160
|
+
var els = new EscapeLiteralSQL(sql);
|
|
161
|
+
els.process();
|
|
231
162
|
|
|
232
|
-
|
|
233
|
-
|
|
163
|
+
ctx.active_sqlhash = sql_step.hash;
|
|
164
|
+
ctx.active_dbc = sql_step.dbc;
|
|
165
|
+
//ctx.active_crud = sql_step.crud;
|
|
234
166
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
167
|
+
// 파라미터 처리
|
|
168
|
+
if (conf.profile_sql_param_enabled) {
|
|
169
|
+
var params = args.length > 1 ? args[1] : undefined;
|
|
170
|
+
if (params) {
|
|
171
|
+
sql_step.setTrue(1);
|
|
172
|
+
var crc = {value: 0};
|
|
173
|
+
sql_step.p1 = toParamBytes(psql.param, crc);
|
|
238
174
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
175
|
+
if (params != undefined) {
|
|
176
|
+
try {
|
|
177
|
+
// Oracle 파라미터는 객체 형태일 수 있음
|
|
178
|
+
let paramStr = '';
|
|
179
|
+
if (typeof params === 'object' && !Array.isArray(params)) {
|
|
180
|
+
paramStr = Object.entries(params).map(([key, value]) => {
|
|
181
|
+
if (typeof value === 'string') {
|
|
182
|
+
return `${key}='${value}'`;
|
|
183
|
+
}
|
|
184
|
+
return `${key}=${value}`;
|
|
185
|
+
}).join(', ');
|
|
186
|
+
} else if (Array.isArray(params)) {
|
|
187
|
+
paramStr = params.map((param) => {
|
|
188
|
+
if (typeof param === 'string') {
|
|
189
|
+
return `'${param}'`;
|
|
190
|
+
}
|
|
191
|
+
return param;
|
|
192
|
+
}).join(', ');
|
|
193
|
+
} else {
|
|
194
|
+
paramStr = String(params);
|
|
195
|
+
}
|
|
196
|
+
sql_step.p2 = toParamBytes(paramStr, crc);
|
|
197
|
+
} catch (e) {
|
|
198
|
+
Logger.printError('WHATAP-112', 'Oracle param processing error', e, false);
|
|
199
|
+
}
|
|
244
200
|
}
|
|
201
|
+
sql_step.pcrc = crc.value;
|
|
245
202
|
}
|
|
203
|
+
}
|
|
246
204
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
205
|
+
// Check if the last argument is a callback
|
|
206
|
+
var hasCallback = false;
|
|
207
|
+
var callbackIndex = -1;
|
|
208
|
+
|
|
209
|
+
if (args.length > 0 && typeof args[args.length - 1] === 'function') {
|
|
210
|
+
hasCallback = true;
|
|
211
|
+
callbackIndex = args.length - 1;
|
|
212
|
+
|
|
213
|
+
// Wrap callback to capture result
|
|
214
|
+
var originalCallback = args[callbackIndex];
|
|
215
|
+
args[callbackIndex] = function wrappedCallback(err, result) {
|
|
216
|
+
if (ctx == null) {
|
|
217
|
+
return originalCallback.apply(this, arguments);
|
|
251
218
|
}
|
|
252
|
-
} catch (e) {
|
|
253
|
-
Logger.printError('WHATAP-TRACESQL', 'Error in TraceSQL processing', e, false);
|
|
254
|
-
}
|
|
255
219
|
|
|
256
|
-
|
|
257
|
-
currentCtx.active_sqlhash = false;
|
|
258
|
-
AsyncSender.send_packet(PacketTypeEnum.TX_SQL, currentCtx, [dbcUrl, finalSql, String(resultCount)]);
|
|
220
|
+
TraceContextManager.resume(ctx._id);
|
|
259
221
|
|
|
260
|
-
|
|
261
|
-
|
|
222
|
+
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
223
|
+
ctx.sql_time += sql_step.elapsed;
|
|
262
224
|
|
|
263
|
-
|
|
264
|
-
|
|
225
|
+
if (err) {
|
|
226
|
+
errorDelegate(ctx, sql_step)(null, [err]);
|
|
227
|
+
ctx.footprint('Oracle Query Error');
|
|
228
|
+
} else {
|
|
229
|
+
ctx.footprint('Oracle Query Done');
|
|
265
230
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
231
|
+
// Process result for SELECT queries
|
|
232
|
+
if (result && result.rows && Array.isArray(result.rows) && psql != null && psql.type === 'S') {
|
|
233
|
+
var result_step = new ResultSetStep();
|
|
234
|
+
result_step.start_time = ctx.getElapsedTime();
|
|
235
|
+
result_step.elapsed = 0;
|
|
236
|
+
result_step.fetch = result.rows.length;
|
|
237
|
+
result_step.sqlhash = psql.sql;
|
|
238
|
+
result_step.dbc = dbc_hash;
|
|
239
|
+
ctx.profile.push(result_step);
|
|
240
|
+
|
|
241
|
+
ctx.rs_count = ctx.rs_count ? ctx.rs_count + result.rows.length : result.rows.length;
|
|
242
|
+
ctx.rs_time = ctx.rs_time ? ctx.rs_time + sql_step.elapsed : sql_step.elapsed;
|
|
243
|
+
|
|
244
|
+
MeterSql.addFetch(result_step.dbc, result_step.fetch, 0);
|
|
245
|
+
StatSql.addFetch(result_step.dbc, result_step.sqlhash, result_step.fetch, 0);
|
|
246
|
+
|
|
247
|
+
TraceSQL.isTooManyRecords(sql_step, result_step.fetch, ctx);
|
|
277
248
|
}
|
|
278
|
-
|
|
279
|
-
|
|
249
|
+
|
|
250
|
+
// Process affectedRows for UPDATE/INSERT/DELETE
|
|
251
|
+
if (result != null && psql != null && (psql.type === 'U' || psql.type === 'I' || psql.type === 'D')) {
|
|
252
|
+
if (result.rowsAffected !== undefined) {
|
|
253
|
+
sql_step.updated = result.rowsAffected || 0;
|
|
254
|
+
}
|
|
280
255
|
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
MeterSql.add(dbc_hash, sql_step.elapsed, !!err);
|
|
259
|
+
StatSql.addSqlTime(ctx.service_hash, sql_step.dbc,
|
|
260
|
+
sql_step.hash, sql_step.elapsed, !!err, 0);
|
|
261
|
+
|
|
262
|
+
return originalCallback.apply(this, arguments);
|
|
263
|
+
};
|
|
285
264
|
}
|
|
286
265
|
|
|
287
266
|
try {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
267
|
+
// Handle promise-based execution
|
|
268
|
+
if (!hasCallback) {
|
|
269
|
+
return original.apply(this, args)
|
|
270
|
+
.then(function (result) {
|
|
271
|
+
// 성공 처리
|
|
272
|
+
if (ctx == null) {
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
TraceContextManager.resume(ctx._id);
|
|
277
|
+
|
|
278
|
+
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
279
|
+
ctx.sql_time += sql_step.elapsed;
|
|
280
|
+
|
|
281
|
+
TraceSQL.isSlowSQL(ctx);
|
|
282
|
+
|
|
283
|
+
ctx.footprint('Oracle Query Done');
|
|
284
|
+
|
|
285
|
+
MeterSql.add(dbc_hash, sql_step.elapsed, false);
|
|
286
|
+
StatSql.addSqlTime(ctx.service_hash, sql_step.dbc,
|
|
287
|
+
sql_step.hash, sql_step.elapsed, false, 0);
|
|
288
|
+
|
|
289
|
+
if (result && result.rows && Array.isArray(result.rows) && psql != null && psql.type === 'S') {
|
|
290
|
+
var result_step = new ResultSetStep();
|
|
291
|
+
result_step.start_time = ctx.getElapsedTime();
|
|
292
|
+
result_step.elapsed = 0;
|
|
293
|
+
result_step.fetch = result.rows.length;
|
|
294
|
+
result_step.sqlhash = psql.sql;
|
|
295
|
+
result_step.dbc = dbc_hash;
|
|
296
|
+
ctx.profile.push(result_step);
|
|
297
|
+
|
|
298
|
+
ctx.rs_count = ctx.rs_count ? ctx.rs_count + result.rows.length : result.rows.length;
|
|
299
|
+
ctx.rs_time = ctx.rs_time ? ctx.rs_time + sql_step.elapsed : sql_step.elapsed;
|
|
300
|
+
|
|
301
|
+
MeterSql.addFetch(result_step.dbc, result_step.fetch, 0);
|
|
302
|
+
StatSql.addFetch(result_step.dbc, result_step.sqlhash, result_step.fetch, 0);
|
|
303
|
+
|
|
304
|
+
TraceSQL.isTooManyRecords(sql_step, result_step.fetch, ctx);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (result != null && psql != null && (psql.type === 'U' || psql.type === 'I' || psql.type === 'D')) {
|
|
308
|
+
if (result.rowsAffected !== undefined) {
|
|
309
|
+
sql_step.updated = result.rowsAffected || 0;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
300
312
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
313
|
+
return result;
|
|
314
|
+
})
|
|
315
|
+
.catch(function (error) {
|
|
316
|
+
if (ctx == null) {
|
|
317
|
+
throw error;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
TraceContextManager.resume(ctx._id);
|
|
321
|
+
errorDelegate(ctx, sql_step)(null, [error]);
|
|
322
|
+
|
|
323
|
+
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
324
|
+
ctx.sql_time += sql_step.elapsed;
|
|
325
|
+
|
|
326
|
+
ctx.footprint('Oracle Query Error');
|
|
327
|
+
|
|
328
|
+
MeterSql.add(dbc_hash, sql_step.elapsed, true);
|
|
329
|
+
StatSql.addSqlTime(ctx.service_hash, sql_step.dbc,
|
|
330
|
+
sql_step.hash, sql_step.elapsed, true, 0);
|
|
331
|
+
|
|
332
|
+
throw error;
|
|
333
|
+
});
|
|
334
|
+
} else {
|
|
335
|
+
return original.apply(this, args);
|
|
336
|
+
}
|
|
337
|
+
} catch (err) {
|
|
338
|
+
if (ctx != null) {
|
|
339
|
+
errorDelegate(ctx, sql_step)(null, [err]);
|
|
340
|
+
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
341
|
+
ctx.sql_time += sql_step.elapsed;
|
|
342
|
+
ctx.footprint('Oracle Query Error');
|
|
343
|
+
|
|
344
|
+
MeterSql.add(dbc_hash, sql_step.elapsed, true);
|
|
345
|
+
StatSql.addSqlTime(ctx.service_hash, sql_step.dbc,
|
|
346
|
+
sql_step.hash, sql_step.elapsed, true, 0);
|
|
347
|
+
}
|
|
348
|
+
throw err;
|
|
305
349
|
}
|
|
306
|
-
}
|
|
307
|
-
};
|
|
308
|
-
}
|
|
350
|
+
};
|
|
351
|
+
});
|
|
352
|
+
}
|
|
309
353
|
};
|
|
310
354
|
|
|
311
355
|
OracleObserver.prototype.inject = function (mod, moduleName) {
|
|
@@ -315,184 +359,315 @@ OracleObserver.prototype.inject = function (mod, moduleName) {
|
|
|
315
359
|
mod.__whatap_observe__ = true;
|
|
316
360
|
Logger.initPrint("OracleObserver");
|
|
317
361
|
|
|
362
|
+
var self = this;
|
|
363
|
+
|
|
318
364
|
if (conf.sql_enabled === false) {
|
|
319
365
|
return;
|
|
320
366
|
}
|
|
321
367
|
|
|
322
|
-
|
|
368
|
+
shimmer.wrap(mod, 'getConnection', function (original) {
|
|
369
|
+
return function () {
|
|
370
|
+
var args = Array.from(arguments);
|
|
371
|
+
var connectionInfo = args[0] || {};
|
|
372
|
+
var ctx = TraceContextManager.getCurrentContext();
|
|
323
373
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
var args = Array.prototype.slice.call(arguments);
|
|
329
|
-
var connectionInfo = args[0] || {};
|
|
330
|
-
var ctx = TraceContextManager.getCurrentContext();
|
|
374
|
+
var connectInfo = connectionInfo.connectString || connectionInfo.connectionString || '';
|
|
375
|
+
var user = connectionInfo.user || '';
|
|
376
|
+
var dbc = 'oracle://' + user + '@' + connectInfo;
|
|
377
|
+
var dbc_hash = HashUtil.hashFromString(dbc);
|
|
331
378
|
|
|
332
|
-
|
|
379
|
+
DataTextAgent.DBC.add(dbc_hash, dbc);
|
|
380
|
+
DataTextAgent.METHOD.add(dbc_hash, dbc);
|
|
381
|
+
DataTextAgent.ERROR.add(dbc_hash, dbc);
|
|
333
382
|
|
|
334
|
-
|
|
335
|
-
return original.apply(this, arguments);
|
|
336
|
-
}
|
|
383
|
+
var dbc_step = null;
|
|
337
384
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
ctx.footprint('Oracle Connecting Start');
|
|
343
|
-
ctx.db_opening = true;
|
|
344
|
-
|
|
345
|
-
// 콜백 래핑
|
|
346
|
-
for (var i = args.length - 1; i >= 0; i--) {
|
|
347
|
-
if (typeof args[i] === 'function') {
|
|
348
|
-
var originalCallback = args[i];
|
|
349
|
-
args[i] = connectionResource.bind(function() {
|
|
350
|
-
var callbackArgs = Array.prototype.slice.call(arguments);
|
|
351
|
-
var err = callbackArgs[0];
|
|
352
|
-
var connection = callbackArgs[1];
|
|
353
|
-
|
|
354
|
-
if (ctx) {
|
|
355
|
-
TraceContextManager.resume(ctx.id);
|
|
356
|
-
ctx.elapsed = Date.now() - ctx.start_time;
|
|
357
|
-
ctx.db_opening = false;
|
|
358
|
-
|
|
359
|
-
if (err) {
|
|
360
|
-
handleSqlError(ctx, err);
|
|
361
|
-
ctx.footprint('Oracle Connecting Error');
|
|
362
|
-
} else {
|
|
363
|
-
ctx.footprint('Oracle Connecting Done');
|
|
364
|
-
}
|
|
365
|
-
}
|
|
385
|
+
if (ctx) {
|
|
386
|
+
dbc_step = new DBCStep();
|
|
387
|
+
dbc_step.start_time = ctx.getElapsedTime();
|
|
388
|
+
dbc_step.hash = dbc_hash;
|
|
366
389
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
390
|
+
ctx.footprint('Oracle Connecting Start');
|
|
391
|
+
ctx.db_opening = true;
|
|
392
|
+
ctx.profile.push(dbc_step);
|
|
393
|
+
}
|
|
370
394
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
395
|
+
if (arguments.length > 0 && typeof arguments[arguments.length - 1] === 'function') {
|
|
396
|
+
var callbackIndex = arguments.length - 1;
|
|
397
|
+
var originalCallback = arguments[callbackIndex];
|
|
398
|
+
|
|
399
|
+
arguments[callbackIndex] = function wrappedCallback(err, connection) {
|
|
400
|
+
if (ctx) {
|
|
401
|
+
TraceContextManager.resume(ctx._id);
|
|
402
|
+
|
|
403
|
+
if (err) {
|
|
404
|
+
ctx.footprint('Oracle Connecting Error');
|
|
405
|
+
if (dbc_step) {
|
|
406
|
+
dbc_step.error = StatError.addError('oracle-' + (err.errorNum || 'ERROR'),
|
|
407
|
+
err.message || 'Oracle connection error', ctx.service_hash);
|
|
408
|
+
}
|
|
409
|
+
} else {
|
|
410
|
+
ctx.footprint('Oracle Connecting Done');
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
ctx.db_opening = false;
|
|
414
|
+
|
|
415
|
+
if (dbc_step) {
|
|
416
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
374
417
|
}
|
|
375
418
|
}
|
|
376
419
|
|
|
377
|
-
|
|
420
|
+
if (connection) {
|
|
421
|
+
connectionAttributes.set(connection, connectionInfo);
|
|
422
|
+
self._wrapPoolOrConnection(connection, dbc);
|
|
423
|
+
}
|
|
378
424
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
return result.then(connectionResource.bind(function(connection) {
|
|
382
|
-
if (ctx) {
|
|
383
|
-
TraceContextManager.resume(ctx.id);
|
|
384
|
-
ctx.elapsed = Date.now() - ctx.start_time;
|
|
385
|
-
ctx.db_opening = false;
|
|
386
|
-
ctx.footprint('Oracle Connecting Done');
|
|
387
|
-
}
|
|
425
|
+
return originalCallback.apply(this, arguments);
|
|
426
|
+
};
|
|
388
427
|
|
|
389
|
-
|
|
390
|
-
|
|
428
|
+
return original.apply(this, arguments);
|
|
429
|
+
} else {
|
|
430
|
+
return original.apply(this, args)
|
|
431
|
+
.then(function (connection) {
|
|
432
|
+
if (ctx) {
|
|
433
|
+
TraceContextManager.resume(ctx._id);
|
|
434
|
+
ctx.footprint('Oracle Connecting Done');
|
|
435
|
+
ctx.db_opening = false;
|
|
436
|
+
|
|
437
|
+
if (dbc_step) {
|
|
438
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
391
439
|
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if (connection) {
|
|
443
|
+
connectionAttributes.set(connection, connectionInfo);
|
|
444
|
+
self._wrapPoolOrConnection(connection, dbc);
|
|
445
|
+
}
|
|
392
446
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
447
|
+
return connection;
|
|
448
|
+
})
|
|
449
|
+
.catch(function (err) {
|
|
450
|
+
if (ctx) {
|
|
451
|
+
TraceContextManager.resume(ctx._id);
|
|
452
|
+
ctx.footprint('Oracle Connecting Error');
|
|
453
|
+
ctx.db_opening = false;
|
|
454
|
+
|
|
455
|
+
if (dbc_step) {
|
|
456
|
+
dbc_step.error = StatError.addError('oracle-' + (err.errorNum || 'ERROR'),
|
|
457
|
+
err.message || 'Oracle connection error', ctx.service_hash);
|
|
458
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
401
459
|
}
|
|
402
|
-
|
|
403
|
-
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
throw err;
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
shimmer.wrap(mod, 'createPool', function (original) {
|
|
469
|
+
return function () {
|
|
470
|
+
var args = Array.from(arguments);
|
|
471
|
+
var poolAttrs = args[0] || {};
|
|
472
|
+
|
|
473
|
+
// Handle callback-style
|
|
474
|
+
if (args.length > 0 && typeof args[args.length - 1] === 'function') {
|
|
475
|
+
var callbackIndex = args.length - 1;
|
|
476
|
+
var originalCallback = args[callbackIndex];
|
|
477
|
+
|
|
478
|
+
args[callbackIndex] = function wrappedCallback(err, pool) {
|
|
479
|
+
if (pool) {
|
|
480
|
+
poolAttributes.set(pool, poolAttrs);
|
|
481
|
+
if (!pool.__whatap_getconn_wrapped) {
|
|
482
|
+
pool.__whatap_getconn_wrapped = true;
|
|
483
|
+
shimmer.wrap(pool, 'getConnection', function(originalGetConn) {
|
|
484
|
+
return self._wrapPoolGetConnection(originalGetConn, poolAttrs);
|
|
485
|
+
});
|
|
486
|
+
}
|
|
404
487
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
488
|
+
|
|
489
|
+
return originalCallback.apply(this, arguments);
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
return original.apply(this, args);
|
|
493
|
+
} else {
|
|
494
|
+
return original.apply(this, args)
|
|
495
|
+
.then(function(pool) {
|
|
496
|
+
if (pool) {
|
|
497
|
+
poolAttributes.set(pool, poolAttrs);
|
|
498
|
+
if (!pool.__whatap_getconn_wrapped) {
|
|
499
|
+
pool.__whatap_getconn_wrapped = true;
|
|
500
|
+
shimmer.wrap(pool, 'getConnection', function(originalGetConn) {
|
|
501
|
+
return self._wrapPoolGetConnection(originalGetConn, poolAttrs);
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return pool;
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
if (mod.Pool && mod.Pool.prototype && !mod.Pool.prototype.__whatap_getconn_wrapped) {
|
|
512
|
+
mod.Pool.prototype.__whatap_getconn_wrapped = true;
|
|
513
|
+
shimmer.wrap(mod.Pool.prototype, 'getConnection', function(original) {
|
|
514
|
+
return self._wrapPoolGetConnection(original);
|
|
408
515
|
});
|
|
409
|
-
mod.getConnection.__whatap_wrapped__ = true;
|
|
410
516
|
}
|
|
517
|
+
};
|
|
411
518
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
return function wrappedCreatePool() {
|
|
416
|
-
var args = Array.prototype.slice.call(arguments);
|
|
417
|
-
var poolAttrs = args[0] || {};
|
|
519
|
+
// Helper function to wrap a pool's getConnection method
|
|
520
|
+
OracleObserver.prototype._wrapPoolGetConnection = function(originalGetConn, poolAttrs) {
|
|
521
|
+
var self = this;
|
|
418
522
|
|
|
419
|
-
|
|
523
|
+
if (originalGetConn.__whatap_wrapped) {
|
|
524
|
+
return originalGetConn;
|
|
525
|
+
}
|
|
420
526
|
|
|
421
|
-
|
|
527
|
+
function wrappedGetConnection() {
|
|
528
|
+
var args = Array.from(arguments);
|
|
529
|
+
var ctx = TraceContextManager.getCurrentContext();
|
|
422
530
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
531
|
+
var poolInfo = poolAttrs || poolAttributes.get(this) || {};
|
|
532
|
+
var connectInfo = poolInfo.connectString || poolInfo.connectionString || '';
|
|
533
|
+
var user = poolInfo.user || '';
|
|
534
|
+
var dbc = 'oracle://' + user + '@' + connectInfo;
|
|
535
|
+
var dbc_hash = HashUtil.hashFromString(dbc);
|
|
427
536
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
if (pool && !hookedInstances.has(pool)) {
|
|
432
|
-
hookedInstances.add(pool);
|
|
537
|
+
DataTextAgent.DBC.add(dbc_hash, dbc);
|
|
538
|
+
DataTextAgent.METHOD.add(dbc_hash, dbc);
|
|
539
|
+
DataTextAgent.ERROR.add(dbc_hash, dbc);
|
|
433
540
|
|
|
434
|
-
|
|
435
|
-
shimmer.wrap(pool, 'getConnection', function(originalGetConn) {
|
|
436
|
-
return function wrappedPoolGetConnection() {
|
|
437
|
-
var args = Array.prototype.slice.call(arguments);
|
|
438
|
-
var ctx = TraceContextManager.getCurrentContext();
|
|
541
|
+
var dbc_step = null;
|
|
439
542
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
543
|
+
if (ctx) {
|
|
544
|
+
dbc_step = new DBCStep();
|
|
545
|
+
dbc_step.start_time = ctx.getElapsedTime();
|
|
546
|
+
dbc_step.hash = dbc_hash;
|
|
443
547
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
if (connection) {
|
|
464
|
-
hookConnectionMethods(connection, self.agent);
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
return connection;
|
|
468
|
-
})).catch(poolConnectionResource.bind(function(err) {
|
|
469
|
-
if (ctx) {
|
|
470
|
-
TraceContextManager.resume(ctx.id);
|
|
471
|
-
ctx.elapsed = Date.now() - ctx.start_time;
|
|
472
|
-
ctx.db_opening = false;
|
|
473
|
-
ctx.footprint('Oracle Pool Connection Error');
|
|
474
|
-
handleSqlError(ctx, err);
|
|
475
|
-
}
|
|
476
|
-
throw err;
|
|
477
|
-
}));
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
return result;
|
|
481
|
-
});
|
|
482
|
-
};
|
|
483
|
-
});
|
|
484
|
-
pool.getConnection.__whatap_wrapped__ = true;
|
|
485
|
-
}
|
|
548
|
+
ctx.footprint('Oracle Pool Connection Start');
|
|
549
|
+
ctx.db_opening = true;
|
|
550
|
+
ctx.profile.push(dbc_step);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
if (args.length > 0 && typeof args[args.length - 1] === 'function') {
|
|
554
|
+
var callbackIndex = args.length - 1;
|
|
555
|
+
var originalCallback = args[callbackIndex];
|
|
556
|
+
|
|
557
|
+
args[callbackIndex] = function(err, connection) {
|
|
558
|
+
if (ctx) {
|
|
559
|
+
TraceContextManager.resume(ctx._id);
|
|
560
|
+
|
|
561
|
+
if (err) {
|
|
562
|
+
ctx.footprint('Oracle Pool Connection Error');
|
|
563
|
+
if (dbc_step) {
|
|
564
|
+
dbc_step.error = StatError.addError('oracle-' + (err.errorNum || 'ERROR'),
|
|
565
|
+
err.message || 'Oracle connection error', ctx.service_hash);
|
|
486
566
|
}
|
|
487
|
-
|
|
488
|
-
|
|
567
|
+
} else {
|
|
568
|
+
ctx.footprint('Oracle Pool Connection Done');
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
ctx.db_opening = false;
|
|
572
|
+
|
|
573
|
+
if (dbc_step) {
|
|
574
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
575
|
+
}
|
|
489
576
|
}
|
|
490
577
|
|
|
491
|
-
|
|
578
|
+
if (connection) {
|
|
579
|
+
connectionAttributes.set(connection, poolInfo);
|
|
580
|
+
self._wrapPoolOrConnection(connection, dbc);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
return originalCallback.apply(this, arguments);
|
|
492
584
|
};
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
585
|
+
|
|
586
|
+
return originalGetConn.apply(this, args);
|
|
587
|
+
} else {
|
|
588
|
+
return originalGetConn.apply(this, args)
|
|
589
|
+
.then(function(connection) {
|
|
590
|
+
if (ctx) {
|
|
591
|
+
TraceContextManager.resume(ctx._id);
|
|
592
|
+
ctx.footprint('Oracle Pool Connection Done');
|
|
593
|
+
ctx.db_opening = false;
|
|
594
|
+
|
|
595
|
+
if (dbc_step) {
|
|
596
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (connection) {
|
|
601
|
+
connectionAttributes.set(connection, poolInfo);
|
|
602
|
+
self._wrapPoolOrConnection(connection, dbc);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
return connection;
|
|
606
|
+
})
|
|
607
|
+
.catch(function(err) {
|
|
608
|
+
if (ctx) {
|
|
609
|
+
TraceContextManager.resume(ctx._id);
|
|
610
|
+
ctx.footprint('Oracle Pool Connection Error');
|
|
611
|
+
ctx.db_opening = false;
|
|
612
|
+
|
|
613
|
+
if (dbc_step) {
|
|
614
|
+
dbc_step.error = StatError.addError('oracle-' + (err.errorNum || 'ERROR'),
|
|
615
|
+
err.message || 'Oracle connection error', ctx.service_hash);
|
|
616
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
throw err;
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
wrappedGetConnection.__whatap_wrapped = true;
|
|
626
|
+
return wrappedGetConnection;
|
|
496
627
|
};
|
|
497
628
|
|
|
629
|
+
var checkedSql = new IntKeyMap(2000).setMax(2000);
|
|
630
|
+
var nonLiteSql = new IntKeyMap(5000).setMax(5000);
|
|
631
|
+
var date = DateUtil.yyyymmdd();
|
|
632
|
+
|
|
633
|
+
function escapeLiteral(sql) {
|
|
634
|
+
if (sql == null) {
|
|
635
|
+
sql = '';
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
if (date !== DateUtil.yyyymmdd()) {
|
|
639
|
+
checkedSql.clear();
|
|
640
|
+
nonLiteSql.clear();
|
|
641
|
+
date = DateUtil.yyyymmdd();
|
|
642
|
+
Logger.print('WHATAP-SQL-CLEAR', 'OracleObserver CLEAR SQL Cache', false);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
var sqlHash = HashUtil.hashFromString(sql);
|
|
646
|
+
var psql = nonLiteSql.get(sqlHash);
|
|
647
|
+
|
|
648
|
+
if (psql != null) {
|
|
649
|
+
return psql;
|
|
650
|
+
}
|
|
651
|
+
psql = checkedSql.get(sqlHash);
|
|
652
|
+
|
|
653
|
+
if (psql != null) {
|
|
654
|
+
return psql;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
var els = new EscapeLiteralSQL(sql);
|
|
658
|
+
els.process();
|
|
659
|
+
|
|
660
|
+
var hash = HashUtil.hashFromString(els.getParsedSql());
|
|
661
|
+
DataTextAgent.SQL.add(hash, els.getParsedSql());
|
|
662
|
+
|
|
663
|
+
if (hash === sqlHash) {
|
|
664
|
+
psql = new ParsedSql(els.sqlType, hash, null);
|
|
665
|
+
nonLiteSql.put(sqlHash, psql);
|
|
666
|
+
} else {
|
|
667
|
+
psql = new ParsedSql(els.sqlType, hash, els.getParameter());
|
|
668
|
+
checkedSql.put(sqlHash, psql);
|
|
669
|
+
}
|
|
670
|
+
return psql;
|
|
671
|
+
}
|
|
672
|
+
|
|
498
673
|
exports.OracleObserver = OracleObserver;
|