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
@@ -5,110 +5,211 @@
5
5
  */
6
6
 
7
7
  var TraceContextManager = require('../trace/trace-context-manager'),
8
- ParsedSql = require('../trace/parsed-sql'),
9
- conf = require('../conf/configure'),
10
- IntKeyMap = require('../util/intkey-map'),
11
- EscapeLiteralSQL = require('../util/escape-literal-sql'),
12
- HashUtil = require('../util/hashutil'),
13
- Logger = require('../logger'),
14
- 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;
8
+ DataTextAgent = require('../data/datatext-agent'),
9
+ ParsedSql = require('../trace/parsed-sql'),
10
+ SqlStepX = require('../step/sql-stepx'),
11
+ DBCStep = require('../step/dbc-step'),
12
+ ResultSetStep = require('../step/resultset-step'),
13
+ HashUtil = require('../util/hashutil'),
14
+ IntKeyMap = require('../util/intkey-map'),
15
+ StatSql = require('../stat/stat-sql'),
16
+ StatError = require('../stat/stat-error'),
17
+ MeterSql = require('../counter/meter/meter-sql'),
18
+ EscapeLiteralSQL = require('../util/escape-literal-sql'),
19
+ TextTypes = require('../lang/text-types'),
20
+ Long = require('long'),
21
+ conf = require('../conf/configure'),
22
+ Logger = require('../logger'),
23
+ TraceSQL = require('../trace/trace-sql')
24
+ const DateUtil = require('../util/dateutil');
25
+ const MessageStep = require("../step/message-step");
26
+ // const ResourceProfile = require("../util/resourceprofile");
20
27
 
21
28
  var MssqlObserver = function (agent) {
22
29
  this.agent = agent;
30
+ this.aop = agent.aop;
23
31
  this.packages = ['mssql'];
24
32
  };
33
+ var dbc_hash=0;
34
+ MssqlObserver.prototype.inject = function (mod, modName) {
25
35
 
26
- var dbc_hash = 0;
27
- var dbc = 'mssql://';
36
+ if(mod.__whatap_observe__) {return;}
37
+ mod.__whatap_observe__ = true;
28
38
 
29
- var hookedInstances = new WeakSet();
39
+ Logger.initPrint("MssqlObserver");
30
40
 
31
- var checkedSql = new IntKeyMap(2000).setMax(2000);
32
- var nonLiteSql = new IntKeyMap(5000).setMax(5000);
33
- var date = DateUtil.yyyymmdd();
41
+ var self = this;
34
42
 
35
- function handleSqlError(ctx, err) {
36
- if (!err) return;
43
+ var requestCommand = ['_bulk', '_query', '_execute'];
37
44
 
38
- try {
39
- var errorClass = err.code || err.name || err.constructor?.name || 'MSSQLError';
40
- var errorMessage = err.message || 'mssql error';
41
- var errorStack = '';
45
+ requestCommand.forEach(function (command) {
46
+ self.aop.both(mod.Request.prototype, command,
47
+ function (obj, args) {
42
48
 
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
- }
51
-
52
- var shouldAddError = false;
53
- if (conf._is_trace_ignore_err_cls_contains === true && errorClass &&
54
- errorClass.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;
62
- }
63
-
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);
49
+ var ctx = TraceContextManager.getCurrentContext();
50
+ if(ctx == null) { return; }
51
+
52
+ var sql_step = new SqlStepX();
53
+ var sql = (typeof args[0] === 'string') ? args[0] : JSON.stringify(args[0]),
54
+ psql = null;
55
+
56
+
57
+ if(dbc_hash===0){
58
+ if(obj.parent && obj.parent.config) {
59
+ var config = obj.parent.config,
60
+ dbc = 'mssql://';
61
+ try {
62
+ dbc += (config.server || '');
63
+ dbc += ':';
64
+ dbc += (config.port || '');
65
+ dbc += '/';
66
+ dbc += (config.database || '');
67
+ dbc_hash = HashUtil.hashFromString(dbc);
68
+ DataTextAgent.DBC.add(dbc_hash, dbc);
69
+ DataTextAgent.METHOD.add(dbc_hash, dbc);
70
+ DataTextAgent.ERROR.add(dbc_hash, dbc)
71
+ } catch(e) {
72
+ }
73
+ }
74
+ }
75
+ var dbc_step = new DBCStep();
76
+ dbc_step.hash = dbc_hash;
77
+ dbc_step.start_time = ctx.getElapsedTime();
78
+ ctx.profile.push(dbc_step);
79
+
80
+ sql_step.dbc = dbc_hash;
81
+
82
+ try {
83
+ psql = escapeLiteral(sql);
84
+ } catch(e) {
85
+ Logger.printError("WHATAP-192", "MssqlObserver escapeliteral error", e);
86
+ }
87
+
88
+ if(psql != null) {
89
+ DataTextAgent.SQL.add(sql_step.hash, sql);
90
+ // = psql.type.charCodeAt(0);
91
+ sql_step.hash = psql.sql;
92
+ }
93
+ sql_step.start_time = ctx.getElapsedTime();
94
+ ctx.profile.push(sql_step);
95
+ self.aop.functionHook(args, -1, function (obj, args) {
96
+ TraceContextManager.resume(ctx);
97
+ if(args[0] != null) {
98
+ ctx.error_message = args[0].message;
99
+ ctx.error_class = args[0].name || args[0].constructor?.name || 'MSSQLError';
100
+ if (conf.trace_sql_error_stack && conf.trace_sql_error_depth) {
101
+ var traceDepth = conf.trace_sql_error_depth;
102
+
103
+ var errorStack = args[0].stack.split("\n");
104
+ if (errorStack.length > traceDepth) {
105
+ errorStack = errorStack.slice(0, traceDepth + 1);
106
+ }
107
+ ctx.error_message = errorStack.join("\n");
108
+ sql_step.error = ctx.error = StatError.addError('mssql-' + args[0].code, args[0].message, ctx.service_hash, TextTypes.SQL, null);
109
+ }
110
+ if(conf._is_trace_ignore_err_cls_contains === true && args[0].code.indexOf(conf.trace_ignore_err_cls_contains) < 0){
111
+ sql_step.error = StatError.addError( 'mssql-'+args[0].code, args[0].message|| 'mssql error', ctx.service_hash, TextTypes.SQL, sql_step.hash); /*long*/
112
+ if (ctx.error.isZero()) { ctx.error = sql_step.error; }
113
+ } else if(conf._is_trace_ignore_err_msg_contains === true && args[0].message.indexOf(conf.trace_ignore_err_msg_contains) < 0){
114
+ sql_step.error = StatError.addError( 'mssql-'+args[0].code, args[0].message|| 'mssql error', ctx.service_hash, TextTypes.SQL, sql_step.hash); /*long*/
115
+ if (ctx.error.isZero()) { ctx.error = sql_step.error; }
116
+ } else if(conf._is_trace_ignore_err_cls_contains === false && conf._is_trace_ignore_err_msg_contains === false) {
117
+ sql_step.error = StatError.addError( 'mssql-'+args[0].code, args[0].message|| 'mssql error', ctx.service_hash, TextTypes.SQL, sql_step.hash); /*long*/
118
+ if (ctx.error.isZero()) { ctx.error = sql_step.error; }
119
+ }
120
+ }
121
+
122
+ sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
123
+ TraceSQL.isSlowSQL(ctx);
124
+
125
+ MeterSql.add(dbc_hash, sql_step.elapsed, args[0] != null);
126
+ StatSql.addSqlTime(ctx.service_hash, sql_step.dbc,
127
+ sql_step.hash, sql_step.elapsed, args[0] != null, 0);
128
+
129
+ if(psql && psql.type == 'S') {
130
+ var result_step = new ResultSetStep();
131
+ result_step.dbc = sql_step.dbc;
132
+ result_step.sqlhash = sql_step.hash;
133
+ try {
134
+ result_step.fetch = args[1][0].length;
135
+ ctx.rs_count = ctx.rs_count ? ctx.rs_count + args[1][0].length : args[1][0].length;
136
+ } catch(e) {
137
+ }
138
+ ctx.profile.push(result_step);
139
+
140
+ MeterSql.addFetch(dbc_hash, result_step.fetch, 0);
141
+ StatSql.addFetch(dbc_hash, result_step.sqlhash, result_step.fetch, 0);
142
+
143
+ TraceSQL.isTooManyRecords(sql_step, result_step.fetch, ctx);
144
+ } else if(psql && psql.type == 'U') {
145
+
146
+ }
147
+ });
148
+ }, function (obj, args, ret, lctx) {
149
+ });
150
+ });
151
+ var conn_dbc_hash=0;
152
+ self.aop.both(mod, 'connect',
153
+ function (obj, args, lctx) {
154
+
155
+ var ctx = TraceContextManager.getCurrentContext();
156
+ if(ctx == null) { return; }
157
+ lctx.context = ctx;
158
+
159
+ var conn = '';
160
+ if(args[0]) { //좀더 로직 개선 필요...
161
+ conn += args[0]['server'] || '';
162
+ conn += args[0]['database'] || '';
70
163
  }
71
- if (errorStack || err.stack) {
72
- errors.push(errorStack || err.stack);
164
+ if(conn.length === 0) { return; }
165
+ if(conn_dbc_hash==0){ //한번만 전송되게 함.
166
+ conn = 'mssql://' + conn;
167
+ conn_dbc_hash = HashUtil.hashFromString(conn);
168
+ DataTextAgent.DBC.add(conn_dbc_hash, conn);
169
+ DataTextAgent.METHOD.add(conn_dbc_hash, dbc);
170
+ DataTextAgent.ERROR.add(conn_dbc_hash, dbc)
73
171
  }
74
172
 
75
- AsyncSender.send_packet(PacketTypeEnum.TX_ERROR, ctx, errors);
76
- }
77
- } catch (e) {
78
- Logger.printError('WHATAP-209', 'Error handling MSSQL error', e, false);
79
- }
80
- }
173
+ var dbc_step = new DBCStep();
174
+ dbc_step.hash = conn_dbc_hash;
175
+ dbc_step.start_time = ctx.getElapsedTime();
81
176
 
82
- function setupDbcInfo(config) {
83
- if (dbc_hash === 0 && config) {
84
- dbc = 'mssql://';
85
- dbc += (config.server || '') + ':';
86
- dbc += (config.port || '') + '/';
87
- dbc += config.database || '';
88
- dbc_hash = HashUtil.hashFromString(dbc);
89
- }
90
- }
177
+ lctx.step = dbc_step;
178
+ },
179
+ function (obj, args, ret, lctx) {
180
+ var pool = ret;
181
+ var ctx = lctx.context,
182
+ step = lctx.step;
183
+
184
+ if(ctx == null || step == null) { return; }
185
+ step.elapsed = ctx.getElapsedTime() - step.start_time;
186
+ ctx.profile.push(step);
187
+ });
188
+ };
189
+
190
+ var checkedSql = new IntKeyMap(2000).setMax(2000);
191
+ var nonLiteSql = new IntKeyMap(5000).setMax(5000);
192
+ var date = DateUtil.yyyymmdd();
91
193
 
92
194
  function escapeLiteral(sql) {
93
- if (sql == null) {
94
- sql = '';
95
- }
195
+ if(sql == null) { sql = ''; }
96
196
 
97
- if (date !== DateUtil.yyyymmdd()) {
197
+ if(date !== DateUtil.yyyymmdd()) {
98
198
  checkedSql.clear();
99
199
  nonLiteSql.clear();
100
200
  date = DateUtil.yyyymmdd();
201
+ Logger.print('WHATAP-SQL-CLEAR', 'MssqlObserver CLEAR OK!!!!!!!!!!!!!!!!', false);
101
202
  }
102
203
 
103
204
  var sqlHash = HashUtil.hashFromString(sql);
104
205
  var psql = nonLiteSql.get(sqlHash);
105
206
 
106
- if (psql != null) {
207
+ if(psql != null) {
107
208
  return psql;
108
209
  }
109
210
  psql = checkedSql.get(sqlHash);
110
211
 
111
- if (psql != null) {
212
+ if(psql != null) {
112
213
  return psql;
113
214
  }
114
215
 
@@ -116,8 +217,9 @@ function escapeLiteral(sql) {
116
217
  els.process();
117
218
 
118
219
  var hash = HashUtil.hashFromString(els.getParsedSql());
220
+ DataTextAgent.SQL.add(hash, els.getParsedSql());
119
221
 
120
- if (hash === sqlHash) {
222
+ if(hash === sqlHash) {
121
223
  psql = new ParsedSql(els.sqlType, hash, null);
122
224
  nonLiteSql.put(sqlHash, psql);
123
225
  } else {
@@ -127,347 +229,4 @@ function escapeLiteral(sql) {
127
229
  return psql;
128
230
  }
129
231
 
130
- function createRequestWrapper(agent, dbcUrl, command) {
131
- return function(original) {
132
- return function wrappedRequest() {
133
- var args = Array.prototype.slice.call(arguments);
134
- var ctx = TraceContextManager.getCurrentContext();
135
-
136
- if (ctx == null || args[0] == null) {
137
- return original.apply(this, arguments);
138
- }
139
-
140
- if (dbcUrl === 'mssql://' || !dbc_hash) {
141
- return original.apply(this, arguments);
142
- }
143
-
144
- const asyncResource = new AsyncResource('mssql-request');
145
- const callbackResource = new AsyncResource('mssql-callback');
146
-
147
- return asyncResource.runInAsyncScope(() => {
148
- ctx.start_time = Date.now();
149
- ctx.elapsed = 0;
150
- AsyncSender.send_packet(PacketTypeEnum.TX_DB_CONN, ctx, [dbcUrl]);
151
-
152
- var sql_start_time = Date.now();
153
- ctx.footprint('MsSQL ' + command + ' Start');
154
- ctx.sql_count++;
155
-
156
- var sql = args.length > 0 ? args[0] : undefined;
157
- var finalSql = '';
158
-
159
- try {
160
- if (typeof sql === 'string') {
161
- finalSql = sql;
162
- } else if (sql !== null && typeof sql === 'object') {
163
- finalSql = JSON.stringify(sql);
164
- }
165
- } catch (formatError) {
166
- Logger.printError('WHATAP-210', 'Error formatting MSSQL query', formatError, false);
167
- finalSql = '';
168
- }
169
-
170
- if (typeof finalSql !== 'string' || finalSql.length === 0) {
171
- finalSql = '';
172
- }
173
-
174
- var psql = null;
175
- if (typeof finalSql === 'string' && finalSql.length > 0) {
176
- try {
177
- psql = escapeLiteral(finalSql);
178
- Logger.print('WHATAP-203', 'Processing SQL: ' + finalSql.substring(0, 200), false);
179
- } catch (e) {
180
- Logger.printError('WHATAP-211', 'MssqlObserver escapeliteral error', e, false);
181
- }
182
- } else {
183
- psql = escapeLiteral(finalSql);
184
- }
185
-
186
- ctx.active_sqlhash = true;
187
- ctx.active_dbc = dbc_hash;
188
-
189
- function requestCallback(err, results) {
190
- var currentCtx = TraceContextManager.getCurrentContext();
191
- if (currentCtx == null) {
192
- return;
193
- }
194
-
195
- TraceContextManager.resume(currentCtx.id);
196
-
197
- var sql_elapsed = Date.now() - sql_start_time;
198
- var resultCount = 0;
199
-
200
- if (err) {
201
- handleSqlError(currentCtx, err);
202
- }
203
-
204
- if (!err && results) {
205
- if (Array.isArray(results) && results.length > 0) {
206
- if (results[0] && Array.isArray(results[0])) {
207
- resultCount = results[0].length;
208
- } else if (results[0] && results[0].recordset && Array.isArray(results[0].recordset)) {
209
- resultCount = results[0].recordset.length;
210
- }
211
- } else if (results.recordset && Array.isArray(results.recordset)) {
212
- resultCount = results.recordset.length;
213
- } else if (results.rowsAffected && Array.isArray(results.rowsAffected)) {
214
- resultCount = results.rowsAffected.reduce((sum, count) => sum + count, 0);
215
- }
216
- }
217
-
218
- try {
219
- TraceSQL.isSlowSQL(currentCtx);
220
- if (!err && psql != null && psql.type === 'S') {
221
- TraceSQL.isTooManyRecords(resultCount, currentCtx);
222
- }
223
- } catch (e) {
224
- Logger.printError('WHATAP-212', 'Error in TraceSQL processing', e, false);
225
- }
226
-
227
- currentCtx.elapsed = sql_elapsed;
228
- currentCtx.active_sqlhash = false;
229
- AsyncSender.send_packet(PacketTypeEnum.TX_SQL, currentCtx, [dbcUrl, finalSql, String(resultCount)]);
230
-
231
- currentCtx.footprint('MsSQL ' + command + ' Done');
232
- }
233
-
234
- var callbackWrapped = false;
235
- var hasCallback = false;
236
-
237
- // 콜백 찾기 및 래핑
238
- for (var i = args.length - 1; i >= 0; i--) {
239
- if (typeof args[i] === 'function') {
240
- hasCallback = true;
241
- var originalCallback = args[i];
242
- args[i] = callbackResource.bind(function() {
243
- var callbackArgs = Array.prototype.slice.call(arguments);
244
- try {
245
- requestCallback(callbackArgs[0], callbackArgs[1]);
246
- } catch (e) {
247
- Logger.printError('WHATAP-213', 'Error in callback hook', e, false);
248
- }
249
- if (originalCallback && typeof originalCallback === 'function') {
250
- return originalCallback.apply(this, callbackArgs);
251
- }
252
- });
253
- callbackWrapped = true;
254
- break;
255
- }
256
- }
257
-
258
- try {
259
- const result = original.apply(this, args);
260
-
261
- // Promise 기반 처리
262
- if (!hasCallback && result && typeof result.then === 'function') {
263
- return result.then(function(res) {
264
- requestCallback(null, res);
265
- return res;
266
- }).catch(function(err) {
267
- requestCallback(err, null);
268
- throw err;
269
- });
270
- }
271
-
272
- return result;
273
- } catch (requestError) {
274
- requestCallback(requestError, null);
275
- throw requestError;
276
- }
277
- });
278
- };
279
- };
280
- }
281
-
282
- MssqlObserver.prototype.inject = function (mod, moduleName) {
283
- if (mod.__whatap_observe__) {
284
- return;
285
- }
286
- mod.__whatap_observe__ = true;
287
- Logger.initPrint("MssqlObserver");
288
-
289
- if (conf.sql_enabled === false) {
290
- return;
291
- }
292
-
293
- var self = this;
294
-
295
- // Request 클래스의 메서드들 후킹
296
- if (mod.Request && mod.Request.prototype) {
297
- var requestCommands = ['_bulk', '_query', '_execute'];
298
-
299
- requestCommands.forEach(function(command) {
300
- if (mod.Request.prototype[command] && !mod.Request.prototype[command].__whatap_wrapped__) {
301
- shimmer.wrap(mod.Request.prototype, command, function(original) {
302
- return function wrappedRequestCommand() {
303
- var args = Array.prototype.slice.call(arguments);
304
- var ctx = TraceContextManager.getCurrentContext();
305
-
306
- if (ctx == null) {
307
- return original.apply(this, arguments);
308
- }
309
-
310
- // DBC 정보 설정
311
- if (dbc_hash === 0 && this.parent && this.parent.config) {
312
- setupDbcInfo(this.parent.config);
313
- }
314
-
315
- return createRequestWrapper(self.agent, dbc, command)(original).apply(this, args);
316
- };
317
- });
318
- mod.Request.prototype[command].__whatap_wrapped__ = true;
319
- }
320
- });
321
- }
322
-
323
- // connect 함수 후킹
324
- if (mod.connect && !mod.connect.__whatap_wrapped__) {
325
- shimmer.wrap(mod, 'connect', function(original) {
326
- return function wrappedConnect() {
327
- var args = Array.prototype.slice.call(arguments);
328
- var ctx = TraceContextManager.getCurrentContext();
329
-
330
- if (ctx == null) {
331
- return original.apply(this, arguments);
332
- }
333
-
334
- // 연결 정보 설정
335
- if (args[0]) {
336
- setupDbcInfo(args[0]);
337
- }
338
-
339
- const connectionResource = new AsyncResource('mssql-connect');
340
-
341
- return connectionResource.runInAsyncScope(() => {
342
- ctx.start_time = Date.now();
343
- ctx.db_opening = true;
344
- ctx.footprint('MsSQL Connecting Start');
345
-
346
- // 콜백 래핑
347
- for (var i = args.length - 1; i >= 0; i--) {
348
- if (typeof args[i] === 'function') {
349
- var originalCallback = args[i];
350
- args[i] = connectionResource.bind(function() {
351
- var callbackArgs = Array.prototype.slice.call(arguments);
352
- var err = callbackArgs[0];
353
-
354
- if (ctx) {
355
- TraceContextManager.resume(ctx.id);
356
- ctx.elapsed = Date.now() - ctx.start_time;
357
-
358
- if (err) {
359
- handleSqlError(ctx, err);
360
- ctx.footprint('MsSQL Connecting Error');
361
- } else {
362
- ctx.footprint('MsSQL Connecting Done');
363
- }
364
- }
365
-
366
- return originalCallback.apply(this, callbackArgs);
367
- });
368
- break;
369
- }
370
- }
371
-
372
- var result = original.apply(this, args);
373
-
374
- // Promise 기반 처리
375
- if (result && typeof result.then === 'function') {
376
- return result.then(connectionResource.bind(function(pool) {
377
- if (ctx) {
378
- TraceContextManager.resume(ctx.id);
379
- ctx.elapsed = Date.now() - ctx.start_time;
380
- ctx.db_opening = false;
381
- ctx.footprint('MsSQL Connecting Done');
382
- }
383
- return pool;
384
- })).catch(connectionResource.bind(function(err) {
385
- if (ctx) {
386
- TraceContextManager.resume(ctx.id);
387
- ctx.elapsed = Date.now() - ctx.start_time;
388
- ctx.db_opening = false;
389
- ctx.footprint('MsSQL Connecting Error');
390
- handleSqlError(ctx, err);
391
- }
392
- throw err;
393
- }));
394
- }
395
-
396
- return result;
397
- });
398
- };
399
- });
400
- mod.connect.__whatap_wrapped__ = true;
401
- }
402
-
403
- // ConnectionPool 클래스 후킹 (있는 경우)
404
- if (mod.ConnectionPool && !mod.ConnectionPool.__whatap_wrapped__) {
405
- shimmer.wrap(mod, 'ConnectionPool', function(original) {
406
- return function wrappedConnectionPool() {
407
- var args = Array.prototype.slice.call(arguments);
408
-
409
- // 연결 정보 설정
410
- if (args[0]) {
411
- setupDbcInfo(args[0]);
412
- }
413
-
414
- var pool = new (Function.prototype.bind.apply(original, [null].concat(args)));
415
-
416
- if (pool && !hookedInstances.has(pool)) {
417
- hookedInstances.add(pool);
418
-
419
- // connect 메서드 후킹
420
- if (pool.connect && !pool.connect.__whatap_wrapped__) {
421
- shimmer.wrap(pool, 'connect', function(original) {
422
- return function wrappedPoolConnect() {
423
- var args = Array.prototype.slice.call(arguments);
424
- var ctx = TraceContextManager.getCurrentContext();
425
-
426
- if (ctx == null) {
427
- return original.apply(this, arguments);
428
- }
429
-
430
- const connectionResource = new AsyncResource('mssql-pool-connect');
431
-
432
- return connectionResource.runInAsyncScope(() => {
433
- ctx.start_time = Date.now();
434
- ctx.footprint('MsSQL Pool Connecting Start');
435
-
436
- var result = original.apply(this, args);
437
-
438
- // Promise 기반 처리
439
- if (result && typeof result.then === 'function') {
440
- return result.then(connectionResource.bind(function(res) {
441
- if (ctx) {
442
- TraceContextManager.resume(ctx.id);
443
- ctx.elapsed = Date.now() - ctx.start_time;
444
- ctx.footprint('MsSQL Pool Connecting Done');
445
- }
446
- return res;
447
- })).catch(connectionResource.bind(function(err) {
448
- if (ctx) {
449
- TraceContextManager.resume(ctx.id);
450
- ctx.elapsed = Date.now() - ctx.start_time;
451
- ctx.footprint('MsSQL Pool Connecting Error');
452
- handleSqlError(ctx, err);
453
- }
454
- throw err;
455
- }));
456
- }
457
-
458
- return result;
459
- });
460
- };
461
- });
462
- pool.connect.__whatap_wrapped__ = true;
463
- }
464
- }
465
-
466
- return pool;
467
- };
468
- });
469
- mod.ConnectionPool.__whatap_wrapped__ = true;
470
- }
471
- };
472
-
473
232
  exports.MssqlObserver = MssqlObserver;