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.
Files changed (198) hide show
  1. package/README.md +32 -78
  2. package/lib/conf/conf-sys-mon.js +101 -0
  3. package/lib/conf/config-default.js +10 -3
  4. package/lib/conf/configure.js +369 -349
  5. package/lib/conf/license.js +1 -1
  6. package/lib/control/cmd-config.js +24 -0
  7. package/lib/control/control-handler.js +367 -0
  8. package/lib/control/packagectr-helper.js +34 -3
  9. package/lib/core/agent.js +176 -882
  10. package/lib/core/interceptor.js +6 -6
  11. package/lib/core/request-agent.js +27 -0
  12. package/lib/core/shimmer.js +82 -36
  13. package/lib/counter/counter-manager.js +79 -8
  14. package/lib/counter/meter/meter-activex.js +67 -0
  15. package/lib/counter/meter/meter-httpc.js +57 -0
  16. package/lib/counter/meter/meter-resource.js +9 -0
  17. package/lib/counter/meter/meter-service.js +168 -0
  18. package/lib/counter/meter/meter-socket.io.js +51 -0
  19. package/lib/counter/meter/meter-sql.js +71 -0
  20. package/lib/counter/meter/meter-users.js +58 -0
  21. package/lib/counter/meter.js +183 -0
  22. package/lib/counter/task/activetransaction.js +68 -17
  23. package/lib/counter/task/agentinfo.js +107 -0
  24. package/lib/{system → counter/task}/gc-action.js +27 -74
  25. package/lib/counter/task/gcstat.js +34 -0
  26. package/lib/counter/task/heapmem.js +25 -0
  27. package/lib/counter/task/httpc.js +76 -0
  28. package/lib/counter/task/metering-info.js +125 -0
  29. package/lib/counter/task/proc-cpu.js +29 -0
  30. package/lib/counter/task/realtimeuser.js +31 -0
  31. package/lib/counter/task/res/systemECSTask.js +39 -0
  32. package/lib/counter/task/res/systemKubeTask.js +53 -0
  33. package/lib/counter/task/res/util/awsEcsClientThread.js +218 -0
  34. package/lib/counter/task/res/util/linuxProcStatUtil.js +14 -0
  35. package/lib/counter/task/res-sys-cpu.js +62 -0
  36. package/lib/counter/task/service.js +202 -0
  37. package/lib/counter/task/socketio.js +30 -0
  38. package/lib/counter/task/sql.js +105 -0
  39. package/lib/counter/task/systemperf.js +43 -0
  40. package/lib/data/datapack-sender.js +289 -0
  41. package/lib/data/dataprofile-agent.js +162 -0
  42. package/lib/data/datatext-agent.js +135 -0
  43. package/lib/data/event-level.js +15 -0
  44. package/lib/data/test.js +49 -0
  45. package/lib/data/zipprofile.js +197 -0
  46. package/lib/env/constants.js +21 -0
  47. package/lib/error/error-handler.js +437 -0
  48. package/lib/io/data-inputx.js +13 -3
  49. package/lib/io/data-outputx.js +268 -206
  50. package/lib/kube/kube-client.js +144 -0
  51. package/lib/lang/text-types.js +58 -0
  52. package/lib/logger.js +6 -6
  53. package/lib/logsink/line-log-util.js +87 -0
  54. package/lib/logsink/line-log.js +12 -0
  55. package/lib/logsink/log-sender.js +78 -0
  56. package/lib/logsink/log-tracer.js +40 -0
  57. package/lib/logsink/sender-util.js +56 -0
  58. package/lib/logsink/zip/zip-send.js +177 -0
  59. package/lib/net/netflag.js +55 -0
  60. package/lib/net/receiver.js +66 -0
  61. package/lib/net/security-master.js +139 -20
  62. package/lib/net/sender.js +141 -0
  63. package/lib/net/tcp-return.js +18 -0
  64. package/lib/net/tcp-session.js +286 -0
  65. package/lib/net/tcpreq-client-proxy.js +70 -0
  66. package/lib/net/tcprequest-mgr.js +58 -0
  67. package/lib/observers/apollo-server-observer.js +33 -27
  68. package/lib/observers/cluster-observer.js +22 -0
  69. package/lib/observers/express-observer.js +215 -0
  70. package/lib/observers/file-observer.js +184 -0
  71. package/lib/observers/global-observer.js +155 -80
  72. package/lib/observers/grpc-observer.js +336 -0
  73. package/lib/observers/http-observer.js +666 -236
  74. package/lib/observers/maria-observer.js +204 -362
  75. package/lib/observers/memcached-observer.js +56 -0
  76. package/lib/observers/mongo-observer.js +317 -0
  77. package/lib/observers/mongodb-observer.js +169 -226
  78. package/lib/observers/mongoose-observer.js +518 -323
  79. package/lib/observers/mssql-observer.js +177 -418
  80. package/lib/observers/mysql-observer.js +342 -449
  81. package/lib/observers/mysql2-observer.js +396 -358
  82. package/lib/observers/net-observer.js +77 -0
  83. package/lib/observers/oracle-observer.js +559 -384
  84. package/lib/observers/pgsql-observer.js +231 -489
  85. package/lib/observers/prisma-observer.js +303 -92
  86. package/lib/observers/process-observer.js +79 -35
  87. package/lib/observers/promise-observer.js +31 -0
  88. package/lib/observers/redis-observer.js +166 -331
  89. package/lib/observers/schedule-observer.js +67 -0
  90. package/lib/observers/socket.io-observer.js +226 -187
  91. package/lib/observers/stream-observer.js +19 -0
  92. package/lib/observers/thrift-observer.js +197 -0
  93. package/lib/observers/websocket-observer.js +175 -301
  94. package/lib/pack/activestack-pack.js +55 -0
  95. package/lib/pack/apenum.js +8 -0
  96. package/lib/pack/counter-pack.js +3 -0
  97. package/lib/pack/errorsnap-pack.js +69 -0
  98. package/lib/pack/event-pack.js +54 -0
  99. package/lib/pack/hitmap-pack.js +63 -0
  100. package/lib/pack/hitmap-pack1.js +152 -0
  101. package/lib/pack/log-sink-pack.js +14 -52
  102. package/lib/pack/netstat.js +15 -0
  103. package/lib/pack/otype.js +7 -0
  104. package/lib/pack/profile-pack.js +49 -0
  105. package/lib/pack/realtimeuser-pack.js +41 -0
  106. package/lib/pack/stat-general-pack.js +96 -0
  107. package/lib/pack/staterror-pack.js +120 -0
  108. package/lib/pack/stathttpc-pack.js +66 -0
  109. package/lib/pack/stathttpc-rec.js +78 -0
  110. package/lib/pack/statremote-pack.js +46 -0
  111. package/lib/pack/statservice-pack.js +63 -0
  112. package/lib/pack/statservice-pack1.js +88 -0
  113. package/lib/pack/statservice-rec.js +292 -0
  114. package/lib/pack/statservice-rec_dep.js +151 -0
  115. package/lib/pack/statsql-pack.js +69 -0
  116. package/lib/pack/statsql-rec.js +100 -0
  117. package/lib/pack/statuseragent-pack.js +44 -0
  118. package/lib/pack/tagcount-pack.js +4 -4
  119. package/lib/pack/tagctr.js +15 -0
  120. package/lib/pack/text-pack.js +50 -0
  121. package/lib/pack/time-count.js +25 -0
  122. package/lib/pack/websocket.js +15 -0
  123. package/lib/pack/zip-pack.js +70 -0
  124. package/lib/pii/pii-item.js +31 -0
  125. package/lib/pii/pii-mask.js +174 -0
  126. package/lib/plugin/plugin-loadermanager.js +57 -0
  127. package/lib/plugin/plugin.js +75 -0
  128. package/lib/service/tx-record.js +332 -0
  129. package/lib/stat/stat-error.js +116 -0
  130. package/lib/stat/stat-httpc.js +98 -0
  131. package/lib/stat/stat-remote-ip.js +46 -0
  132. package/lib/stat/stat-remote-ipurl.js +88 -0
  133. package/lib/stat/stat-sql.js +113 -0
  134. package/lib/stat/stat-tranx.js +58 -0
  135. package/lib/stat/stat-tx-caller.js +160 -0
  136. package/lib/stat/stat-tx-domain.js +111 -0
  137. package/lib/stat/stat-tx-referer.js +112 -0
  138. package/lib/stat/stat-useragent.js +48 -0
  139. package/lib/stat/timingsender.js +76 -0
  140. package/lib/step/activestack-step.js +38 -0
  141. package/lib/step/dbc-step.js +36 -0
  142. package/lib/step/http-stepx.js +67 -0
  143. package/lib/step/message-step.js +40 -0
  144. package/lib/step/method-stepx.js +45 -0
  145. package/lib/step/resultset-step.js +40 -0
  146. package/lib/step/securemsg-step.js +44 -0
  147. package/lib/step/socket-step.js +46 -0
  148. package/lib/step/sql-stepx.js +68 -0
  149. package/lib/step/sqlxtype.js +16 -0
  150. package/lib/step/step.js +66 -0
  151. package/lib/step/stepenum.js +54 -0
  152. package/lib/topology/link.js +63 -0
  153. package/lib/topology/nodeinfo.js +123 -0
  154. package/lib/topology/status-detector.js +111 -0
  155. package/lib/trace/trace-context-manager.js +113 -25
  156. package/lib/trace/trace-context.js +21 -7
  157. package/lib/trace/trace-httpc.js +17 -11
  158. package/lib/trace/trace-sql.js +29 -21
  159. package/lib/util/anylist.js +103 -0
  160. package/lib/util/cardinality/hyperloglog.js +106 -0
  161. package/lib/util/cardinality/murmurhash.js +31 -0
  162. package/lib/util/cardinality/registerset.js +75 -0
  163. package/lib/util/errordata.js +21 -0
  164. package/lib/util/escape-literal-sql.js +5 -5
  165. package/lib/util/hashutil.js +18 -18
  166. package/lib/util/iputil_x.js +527 -0
  167. package/lib/util/keygen.js +0 -3
  168. package/lib/util/kube-util.js +73 -0
  169. package/lib/util/linkedset.js +1 -2
  170. package/lib/util/nodeutil.js +2 -1
  171. package/lib/util/paramsecurity.js +80 -0
  172. package/lib/util/pre-process.js +13 -0
  173. package/lib/util/process-seq.js +166 -0
  174. package/lib/util/property-util.js +36 -0
  175. package/lib/util/request-queue.js +70 -0
  176. package/lib/util/requestdouble-queue.js +72 -0
  177. package/lib/util/resourceprofile.js +157 -0
  178. package/lib/util/stop-watch.js +30 -0
  179. package/lib/util/system-util.js +10 -0
  180. package/lib/util/userid-util.js +57 -0
  181. package/lib/value/map-value.js +3 -2
  182. package/package.json +9 -4
  183. package/whatap.conf +1 -4
  184. package/agent/darwin/arm64/whatap_nodejs +0 -0
  185. package/agent/linux/amd64/whatap_nodejs +0 -0
  186. package/agent/linux/arm64/whatap_nodejs +0 -0
  187. package/build.txt +0 -4
  188. package/lib/observers/ioredis-observer.js +0 -294
  189. package/lib/udp/async_sender.js +0 -119
  190. package/lib/udp/index.js +0 -17
  191. package/lib/udp/packet_enum.js +0 -52
  192. package/lib/udp/packet_queue.js +0 -69
  193. package/lib/udp/packet_type_enum.js +0 -33
  194. package/lib/udp/param_def.js +0 -72
  195. package/lib/udp/udp_session.js +0 -336
  196. package/lib/util/sql-util.js +0 -178
  197. package/lib/util/trace-helper.js +0 -91
  198. 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
- AsyncSender = require('../udp/async_sender'),
16
- PacketTypeEnum = require('../udp/packet_type_enum'),
17
- shimmer = require('../core/shimmer'),
18
- TraceSQL = require('../trace/trace-sql'),
19
- AsyncResource = require('async_hooks').AsyncResource;
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
- var dbc_hash = 0;
27
- var dbc = 'oracle://';
28
-
29
- var hookedInstances = new WeakSet();
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
- var errorClass = err.errorNum || err.code || err.name || err.constructor?.name || 'OracleError';
40
- var errorMessage = err.message || 'oracle error';
41
- var errorStack = '';
42
-
43
- if (conf.trace_sql_error_stack && conf.trace_sql_error_depth && err.stack) {
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
- var shouldAddError = false;
53
- if (conf._is_trace_ignore_err_cls_contains === true && errorClass &&
54
- errorClass.toString().indexOf(conf.trace_ignore_err_cls_contains) < 0) {
55
- shouldAddError = true;
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 (shouldAddError) {
65
- if (!ctx.error) ctx.error = 1;
66
- ctx.status = 500;
67
- var errors = [errorClass];
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
- function setupDbcInfo(connectionInfo) {
83
- if (dbc_hash === 0 && connectionInfo) {
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
- function hookConnectionMethods(connection, agent) {
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
- if (connection.execute && !connection.execute.__whatap_wrapped__) {
97
- shimmer.wrap(connection, 'execute', createExecuteWrapper(agent, dbc));
98
- connection.execute.__whatap_wrapped__ = true;
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
- function escapeLiteral(sql) {
104
- if (sql == null) {
105
- sql = '';
106
- }
107
-
108
- if (date !== DateUtil.yyyymmdd()) {
109
- checkedSql.clear();
110
- nonLiteSql.clear();
111
- date = DateUtil.yyyymmdd();
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
- var sqlHash = HashUtil.hashFromString(sql);
115
- var psql = nonLiteSql.get(sqlHash);
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
- if (psql != null) {
118
- return psql;
119
- }
120
- psql = checkedSql.get(sqlHash);
106
+ // 커넥션 관리 함수
107
+ OracleObserver.prototype._wrapPoolOrConnection = function (obj, dbc) {
108
+ var self = this;
121
109
 
122
- if (psql != null) {
123
- return psql;
110
+ if (obj.__whatap_observed) {
111
+ return;
124
112
  }
113
+ obj.__whatap_observed = true;
125
114
 
126
- var els = new EscapeLiteralSQL(sql);
127
- els.process();
128
-
129
- var hash = HashUtil.hashFromString(els.getParsedSql());
130
-
131
- if (hash === sqlHash) {
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
- if (ctx == null || args[0] == null) {
148
- return original.apply(this, arguments);
149
- }
122
+ if (ctx == null || args.length === 0) {
123
+ return original.apply(this, args);
124
+ }
150
125
 
151
- if (dbcUrl === 'oracle://' || !dbc_hash) {
152
- return original.apply(this, arguments);
153
- }
126
+ var sql = args[0];
127
+ if (sql == null) {
128
+ return original.apply(this, args);
129
+ }
154
130
 
155
- const asyncResource = new AsyncResource('oracle-execute');
156
- const callbackResource = new AsyncResource('oracle-callback');
131
+ // DBC 단계 생성
132
+ var dbc_hash = HashUtil.hashFromString(dbc);
157
133
 
158
- return asyncResource.runInAsyncScope(() => {
159
- ctx.start_time = Date.now();
160
- ctx.elapsed = 0;
161
- AsyncSender.send_packet(PacketTypeEnum.TX_DB_CONN, ctx, [dbcUrl]);
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 finalSql === 'string' && finalSql.length > 0) {
143
+ if (typeof sql === 'string' && sql.length > 0) {
211
144
  try {
212
- psql = escapeLiteral(finalSql);
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-252', 'OracleObserver escapeliteral error', e, false);
147
+ Logger.printError('WHATAP-111', 'OracleObserver escapeliteral error', e, false);
216
148
  }
217
149
  } else {
218
- psql = escapeLiteral(finalSql);
150
+ sql = '';
151
+ psql = escapeLiteral(sql);
219
152
  }
220
153
 
221
- ctx.active_sqlhash = true;
222
- ctx.active_dbc = dbc_hash;
223
-
224
- function executeCallback(err, results) {
225
- var currentCtx = TraceContextManager.getCurrentContext();
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
- TraceContextManager.resume(currentCtx.id);
160
+ var els = new EscapeLiteralSQL(sql);
161
+ els.process();
231
162
 
232
- var sql_elapsed = Date.now() - sql_start_time;
233
- var resultCount = 0;
163
+ ctx.active_sqlhash = sql_step.hash;
164
+ ctx.active_dbc = sql_step.dbc;
165
+ //ctx.active_crud = sql_step.crud;
234
166
 
235
- if (err) {
236
- handleSqlError(currentCtx, err);
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
- if (!err && results) {
240
- if (results.rows && Array.isArray(results.rows)) {
241
- resultCount = results.rows.length;
242
- } else if (results.rowsAffected !== undefined) {
243
- resultCount = results.rowsAffected;
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
- try {
248
- TraceSQL.isSlowSQL(currentCtx);
249
- if (!err && results && results.rows && Array.isArray(results.rows) && psql != null && psql.type === 'S') {
250
- TraceSQL.isTooManyRecords(resultCount, currentCtx);
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
- currentCtx.elapsed = sql_elapsed;
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
- currentCtx.footprint('Oracle Query Done');
261
- }
222
+ sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
223
+ ctx.sql_time += sql_step.elapsed;
262
224
 
263
- var callbackWrapped = false;
264
- var hasCallback = false;
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
- for (var i = args.length - 1; i >= 0; i--) {
268
- if (typeof args[i] === 'function') {
269
- hasCallback = true;
270
- var originalCallback = args[i];
271
- args[i] = callbackResource.bind(function() {
272
- var callbackArgs = Array.prototype.slice.call(arguments);
273
- try {
274
- executeCallback(callbackArgs[0], callbackArgs[1]);
275
- } catch (e) {
276
- Logger.printError('WHATAP-CALLBACK', 'Error in callback hook', e, false);
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
- if (originalCallback && typeof originalCallback === 'function') {
279
- return originalCallback.apply(this, callbackArgs);
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
- callbackWrapped = true;
283
- break;
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
- const result = original.apply(this, args);
289
-
290
- // Promise 기반 처리
291
- if (!hasCallback && result && typeof result.then === 'function') {
292
- return result.then(function(res) {
293
- executeCallback(null, res);
294
- return res;
295
- }).catch(function(err) {
296
- executeCallback(err, null);
297
- throw err;
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
- return result;
302
- } catch (executeError) {
303
- executeCallback(executeError, null);
304
- throw executeError;
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
- var self = this;
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
- // getConnection 래핑
325
- if (mod.getConnection && !mod.getConnection.__whatap_wrapped__) {
326
- shimmer.wrap(mod, 'getConnection', function(original) {
327
- return function wrappedGetConnection() {
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
- setupDbcInfo(connectionInfo);
379
+ DataTextAgent.DBC.add(dbc_hash, dbc);
380
+ DataTextAgent.METHOD.add(dbc_hash, dbc);
381
+ DataTextAgent.ERROR.add(dbc_hash, dbc);
333
382
 
334
- if (ctx == null) {
335
- return original.apply(this, arguments);
336
- }
383
+ var dbc_step = null;
337
384
 
338
- const connectionResource = new AsyncResource('oracle-getconnection');
339
-
340
- return connectionResource.runInAsyncScope(() => {
341
- ctx.start_time = Date.now();
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
- if (connection) {
368
- hookConnectionMethods(connection, self.agent);
369
- }
390
+ ctx.footprint('Oracle Connecting Start');
391
+ ctx.db_opening = true;
392
+ ctx.profile.push(dbc_step);
393
+ }
370
394
 
371
- return originalCallback.apply(this, callbackArgs);
372
- });
373
- break;
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
- var result = original.apply(this, args);
420
+ if (connection) {
421
+ connectionAttributes.set(connection, connectionInfo);
422
+ self._wrapPoolOrConnection(connection, dbc);
423
+ }
378
424
 
379
- // Promise 기반 처리
380
- if (result && typeof result.then === 'function') {
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
- if (connection) {
390
- hookConnectionMethods(connection, self.agent);
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
- return connection;
394
- })).catch(connectionResource.bind(function(err) {
395
- if (ctx) {
396
- TraceContextManager.resume(ctx.id);
397
- ctx.elapsed = Date.now() - ctx.start_time;
398
- ctx.db_opening = false;
399
- ctx.footprint('Oracle Connecting Error');
400
- handleSqlError(ctx, err);
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
- throw err;
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
- return result;
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
- // createPool 래핑
413
- if (mod.createPool && !mod.createPool.__whatap_wrapped__) {
414
- shimmer.wrap(mod, 'createPool', function(original) {
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
- setupDbcInfo(poolAttrs);
523
+ if (originalGetConn.__whatap_wrapped) {
524
+ return originalGetConn;
525
+ }
420
526
 
421
- var result = original.apply(this, args);
527
+ function wrappedGetConnection() {
528
+ var args = Array.from(arguments);
529
+ var ctx = TraceContextManager.getCurrentContext();
422
530
 
423
- // 콜백 방식 처리
424
- if (args.length > 0 && typeof args[args.length - 1] === 'function') {
425
- return result;
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
- // Promise 방식 처리
429
- if (result && typeof result.then === 'function') {
430
- return result.then(function(pool) {
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
- if (pool.getConnection && !pool.getConnection.__whatap_wrapped__) {
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
- if (ctx == null) {
441
- return originalGetConn.apply(this, arguments);
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
- const poolConnectionResource = new AsyncResource('oracle-pool-getconnection');
445
-
446
- return poolConnectionResource.runInAsyncScope(() => {
447
- ctx.start_time = Date.now();
448
- ctx.footprint('Oracle Pool Connection Start');
449
- ctx.db_opening = true;
450
-
451
- var result = originalGetConn.apply(this, args);
452
-
453
- // Promise 기반 처리
454
- if (result && typeof result.then === 'function') {
455
- return result.then(poolConnectionResource.bind(function(connection) {
456
- if (ctx) {
457
- TraceContextManager.resume(ctx.id);
458
- ctx.elapsed = Date.now() - ctx.start_time;
459
- ctx.db_opening = false;
460
- ctx.footprint('Oracle Pool Connection Done');
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
- return pool;
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
- return result;
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
- mod.createPool.__whatap_wrapped__ = true;
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;