whatap 0.5.26 → 1.0.0

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 (196) hide show
  1. package/agent/darwin/arm64/whatap_nodejs +0 -0
  2. package/agent/linux/amd64/whatap_nodejs +0 -0
  3. package/agent/linux/arm64/whatap_nodejs +0 -0
  4. package/build.txt +4 -0
  5. package/lib/conf/config-default.js +3 -10
  6. package/lib/conf/configure.js +349 -369
  7. package/lib/conf/license.js +1 -1
  8. package/lib/control/packagectr-helper.js +3 -34
  9. package/lib/core/agent.js +882 -176
  10. package/lib/core/interceptor.js +6 -6
  11. package/lib/core/shimmer.js +36 -82
  12. package/lib/counter/counter-manager.js +8 -79
  13. package/lib/counter/task/activetransaction.js +17 -68
  14. package/lib/io/data-inputx.js +3 -13
  15. package/lib/io/data-outputx.js +206 -268
  16. package/lib/logger.js +6 -6
  17. package/lib/net/security-master.js +20 -139
  18. package/lib/observers/apollo-server-observer.js +27 -33
  19. package/lib/observers/global-observer.js +80 -155
  20. package/lib/observers/http-observer.js +236 -666
  21. package/lib/observers/ioredis-observer.js +294 -0
  22. package/lib/observers/maria-observer.js +362 -204
  23. package/lib/observers/mongodb-observer.js +226 -169
  24. package/lib/observers/mongoose-observer.js +323 -518
  25. package/lib/observers/mssql-observer.js +418 -177
  26. package/lib/observers/mysql-observer.js +449 -342
  27. package/lib/observers/mysql2-observer.js +358 -396
  28. package/lib/observers/oracle-observer.js +384 -559
  29. package/lib/observers/pgsql-observer.js +489 -231
  30. package/lib/observers/prisma-observer.js +92 -303
  31. package/lib/observers/process-observer.js +35 -79
  32. package/lib/observers/redis-observer.js +331 -166
  33. package/lib/observers/socket.io-observer.js +187 -226
  34. package/lib/observers/websocket-observer.js +301 -175
  35. package/lib/pack/counter-pack.js +0 -3
  36. package/lib/pack/log-sink-pack.js +52 -14
  37. package/lib/pack/tagcount-pack.js +4 -4
  38. package/lib/{counter/task → system}/gc-action.js +74 -27
  39. package/lib/trace/trace-context-manager.js +25 -113
  40. package/lib/trace/trace-context.js +7 -21
  41. package/lib/trace/trace-httpc.js +11 -17
  42. package/lib/trace/trace-sql.js +21 -29
  43. package/lib/udp/async_sender.js +119 -0
  44. package/lib/udp/index.js +17 -0
  45. package/lib/udp/packet_enum.js +52 -0
  46. package/lib/udp/packet_queue.js +69 -0
  47. package/lib/udp/packet_type_enum.js +33 -0
  48. package/lib/udp/param_def.js +72 -0
  49. package/lib/udp/udp_session.js +336 -0
  50. package/lib/util/escape-literal-sql.js +5 -5
  51. package/lib/util/hashutil.js +18 -18
  52. package/lib/util/keygen.js +3 -0
  53. package/lib/util/linkedset.js +2 -1
  54. package/lib/util/nodeutil.js +1 -2
  55. package/lib/util/sql-util.js +178 -0
  56. package/lib/util/trace-helper.js +91 -0
  57. package/lib/util/transfer.js +58 -0
  58. package/lib/value/map-value.js +2 -3
  59. package/package.json +5 -10
  60. package/lib/conf/conf-sys-mon.js +0 -101
  61. package/lib/control/cmd-config.js +0 -24
  62. package/lib/control/control-handler.js +0 -367
  63. package/lib/core/request-agent.js +0 -27
  64. package/lib/counter/meter/meter-activex.js +0 -67
  65. package/lib/counter/meter/meter-httpc.js +0 -57
  66. package/lib/counter/meter/meter-resource.js +0 -9
  67. package/lib/counter/meter/meter-service.js +0 -168
  68. package/lib/counter/meter/meter-socket.io.js +0 -51
  69. package/lib/counter/meter/meter-sql.js +0 -71
  70. package/lib/counter/meter/meter-users.js +0 -58
  71. package/lib/counter/meter.js +0 -183
  72. package/lib/counter/task/agentinfo.js +0 -107
  73. package/lib/counter/task/gcstat.js +0 -34
  74. package/lib/counter/task/heapmem.js +0 -25
  75. package/lib/counter/task/httpc.js +0 -76
  76. package/lib/counter/task/metering-info.js +0 -125
  77. package/lib/counter/task/proc-cpu.js +0 -29
  78. package/lib/counter/task/realtimeuser.js +0 -31
  79. package/lib/counter/task/res/systemECSTask.js +0 -39
  80. package/lib/counter/task/res/systemKubeTask.js +0 -53
  81. package/lib/counter/task/res/util/awsEcsClientThread.js +0 -218
  82. package/lib/counter/task/res/util/linuxProcStatUtil.js +0 -14
  83. package/lib/counter/task/res-sys-cpu.js +0 -62
  84. package/lib/counter/task/service.js +0 -202
  85. package/lib/counter/task/socketio.js +0 -30
  86. package/lib/counter/task/sql.js +0 -105
  87. package/lib/counter/task/systemperf.js +0 -43
  88. package/lib/data/datapack-sender.js +0 -289
  89. package/lib/data/dataprofile-agent.js +0 -162
  90. package/lib/data/datatext-agent.js +0 -135
  91. package/lib/data/event-level.js +0 -15
  92. package/lib/data/test.js +0 -49
  93. package/lib/data/zipprofile.js +0 -197
  94. package/lib/env/constants.js +0 -21
  95. package/lib/error/error-handler.js +0 -437
  96. package/lib/kube/kube-client.js +0 -144
  97. package/lib/lang/text-types.js +0 -58
  98. package/lib/logsink/line-log-util.js +0 -87
  99. package/lib/logsink/line-log.js +0 -12
  100. package/lib/logsink/log-sender.js +0 -78
  101. package/lib/logsink/log-tracer.js +0 -40
  102. package/lib/logsink/sender-util.js +0 -56
  103. package/lib/logsink/zip/zip-send.js +0 -177
  104. package/lib/net/netflag.js +0 -55
  105. package/lib/net/receiver.js +0 -66
  106. package/lib/net/sender.js +0 -141
  107. package/lib/net/tcp-return.js +0 -18
  108. package/lib/net/tcp-session.js +0 -286
  109. package/lib/net/tcpreq-client-proxy.js +0 -70
  110. package/lib/net/tcprequest-mgr.js +0 -58
  111. package/lib/observers/cluster-observer.js +0 -22
  112. package/lib/observers/express-observer.js +0 -215
  113. package/lib/observers/file-observer.js +0 -184
  114. package/lib/observers/grpc-observer.js +0 -336
  115. package/lib/observers/memcached-observer.js +0 -56
  116. package/lib/observers/mongo-observer.js +0 -317
  117. package/lib/observers/net-observer.js +0 -77
  118. package/lib/observers/promise-observer.js +0 -31
  119. package/lib/observers/schedule-observer.js +0 -67
  120. package/lib/observers/stream-observer.js +0 -19
  121. package/lib/observers/thrift-observer.js +0 -197
  122. package/lib/pack/activestack-pack.js +0 -55
  123. package/lib/pack/apenum.js +0 -8
  124. package/lib/pack/errorsnap-pack.js +0 -69
  125. package/lib/pack/event-pack.js +0 -54
  126. package/lib/pack/hitmap-pack.js +0 -63
  127. package/lib/pack/hitmap-pack1.js +0 -152
  128. package/lib/pack/netstat.js +0 -15
  129. package/lib/pack/otype.js +0 -7
  130. package/lib/pack/profile-pack.js +0 -49
  131. package/lib/pack/realtimeuser-pack.js +0 -41
  132. package/lib/pack/stat-general-pack.js +0 -96
  133. package/lib/pack/staterror-pack.js +0 -120
  134. package/lib/pack/stathttpc-pack.js +0 -66
  135. package/lib/pack/stathttpc-rec.js +0 -78
  136. package/lib/pack/statremote-pack.js +0 -46
  137. package/lib/pack/statservice-pack.js +0 -63
  138. package/lib/pack/statservice-pack1.js +0 -88
  139. package/lib/pack/statservice-rec.js +0 -292
  140. package/lib/pack/statservice-rec_dep.js +0 -151
  141. package/lib/pack/statsql-pack.js +0 -69
  142. package/lib/pack/statsql-rec.js +0 -100
  143. package/lib/pack/statuseragent-pack.js +0 -44
  144. package/lib/pack/tagctr.js +0 -15
  145. package/lib/pack/text-pack.js +0 -50
  146. package/lib/pack/time-count.js +0 -25
  147. package/lib/pack/websocket.js +0 -15
  148. package/lib/pack/zip-pack.js +0 -70
  149. package/lib/pii/pii-item.js +0 -31
  150. package/lib/pii/pii-mask.js +0 -174
  151. package/lib/plugin/plugin-loadermanager.js +0 -57
  152. package/lib/plugin/plugin.js +0 -75
  153. package/lib/service/tx-record.js +0 -332
  154. package/lib/stat/stat-error.js +0 -116
  155. package/lib/stat/stat-httpc.js +0 -98
  156. package/lib/stat/stat-remote-ip.js +0 -46
  157. package/lib/stat/stat-remote-ipurl.js +0 -88
  158. package/lib/stat/stat-sql.js +0 -113
  159. package/lib/stat/stat-tranx.js +0 -58
  160. package/lib/stat/stat-tx-caller.js +0 -160
  161. package/lib/stat/stat-tx-domain.js +0 -111
  162. package/lib/stat/stat-tx-referer.js +0 -112
  163. package/lib/stat/stat-useragent.js +0 -48
  164. package/lib/stat/timingsender.js +0 -76
  165. package/lib/step/activestack-step.js +0 -38
  166. package/lib/step/dbc-step.js +0 -36
  167. package/lib/step/http-stepx.js +0 -67
  168. package/lib/step/message-step.js +0 -40
  169. package/lib/step/method-stepx.js +0 -45
  170. package/lib/step/resultset-step.js +0 -40
  171. package/lib/step/securemsg-step.js +0 -44
  172. package/lib/step/socket-step.js +0 -46
  173. package/lib/step/sql-stepx.js +0 -68
  174. package/lib/step/sqlxtype.js +0 -16
  175. package/lib/step/step.js +0 -66
  176. package/lib/step/stepenum.js +0 -54
  177. package/lib/topology/link.js +0 -63
  178. package/lib/topology/nodeinfo.js +0 -123
  179. package/lib/topology/status-detector.js +0 -111
  180. package/lib/util/anylist.js +0 -103
  181. package/lib/util/cardinality/hyperloglog.js +0 -106
  182. package/lib/util/cardinality/murmurhash.js +0 -31
  183. package/lib/util/cardinality/registerset.js +0 -75
  184. package/lib/util/errordata.js +0 -21
  185. package/lib/util/iputil_x.js +0 -527
  186. package/lib/util/kube-util.js +0 -73
  187. package/lib/util/paramsecurity.js +0 -80
  188. package/lib/util/pre-process.js +0 -13
  189. package/lib/util/process-seq.js +0 -166
  190. package/lib/util/property-util.js +0 -36
  191. package/lib/util/request-queue.js +0 -70
  192. package/lib/util/requestdouble-queue.js +0 -72
  193. package/lib/util/resourceprofile.js +0 -157
  194. package/lib/util/stop-watch.js +0 -30
  195. package/lib/util/system-util.js +0 -10
  196. package/lib/util/userid-util.js +0 -57
@@ -5,211 +5,110 @@
5
5
  */
6
6
 
7
7
  var TraceContextManager = require('../trace/trace-context-manager'),
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");
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;
27
20
 
28
21
  var MssqlObserver = function (agent) {
29
22
  this.agent = agent;
30
- this.aop = agent.aop;
31
23
  this.packages = ['mssql'];
32
24
  };
33
- var dbc_hash=0;
34
- MssqlObserver.prototype.inject = function (mod, modName) {
35
25
 
36
- if(mod.__whatap_observe__) {return;}
37
- mod.__whatap_observe__ = true;
38
-
39
- Logger.initPrint("MssqlObserver");
40
-
41
- var self = this;
42
-
43
- var requestCommand = ['_bulk', '_query', '_execute'];
44
-
45
- requestCommand.forEach(function (command) {
46
- self.aop.both(mod.Request.prototype, command,
47
- function (obj, args) {
48
-
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);
26
+ var dbc_hash = 0;
27
+ var dbc = 'mssql://';
79
28
 
80
- sql_step.dbc = dbc_hash;
29
+ var hookedInstances = new WeakSet();
81
30
 
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);
31
+ var checkedSql = new IntKeyMap(2000).setMax(2000);
32
+ var nonLiteSql = new IntKeyMap(5000).setMax(5000);
33
+ var date = DateUtil.yyyymmdd();
139
34
 
140
- MeterSql.addFetch(dbc_hash, result_step.fetch, 0);
141
- StatSql.addFetch(dbc_hash, result_step.sqlhash, result_step.fetch, 0);
35
+ function handleSqlError(ctx, err) {
36
+ if (!err) return;
142
37
 
143
- TraceSQL.isTooManyRecords(sql_step, result_step.fetch, ctx);
144
- } else if(psql && psql.type == 'U') {
38
+ try {
39
+ var errorClass = err.code || err.name || err.constructor?.name || 'MSSQLError';
40
+ var errorMessage = err.message || 'mssql error';
41
+ var errorStack = '';
145
42
 
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'] || '';
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);
163
48
  }
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)
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);
70
+ }
71
+ if (errorStack || err.stack) {
72
+ errors.push(errorStack || err.stack);
171
73
  }
172
74
 
173
- var dbc_step = new DBCStep();
174
- dbc_step.hash = conn_dbc_hash;
175
- dbc_step.start_time = ctx.getElapsedTime();
176
-
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
- };
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
+ }
189
81
 
190
- var checkedSql = new IntKeyMap(2000).setMax(2000);
191
- var nonLiteSql = new IntKeyMap(5000).setMax(5000);
192
- var date = DateUtil.yyyymmdd();
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
+ }
193
91
 
194
92
  function escapeLiteral(sql) {
195
- if(sql == null) { sql = ''; }
93
+ if (sql == null) {
94
+ sql = '';
95
+ }
196
96
 
197
- if(date !== DateUtil.yyyymmdd()) {
97
+ if (date !== DateUtil.yyyymmdd()) {
198
98
  checkedSql.clear();
199
99
  nonLiteSql.clear();
200
100
  date = DateUtil.yyyymmdd();
201
- Logger.print('WHATAP-SQL-CLEAR', 'MssqlObserver CLEAR OK!!!!!!!!!!!!!!!!', false);
202
101
  }
203
102
 
204
103
  var sqlHash = HashUtil.hashFromString(sql);
205
104
  var psql = nonLiteSql.get(sqlHash);
206
105
 
207
- if(psql != null) {
106
+ if (psql != null) {
208
107
  return psql;
209
108
  }
210
109
  psql = checkedSql.get(sqlHash);
211
110
 
212
- if(psql != null) {
111
+ if (psql != null) {
213
112
  return psql;
214
113
  }
215
114
 
@@ -217,9 +116,8 @@ function escapeLiteral(sql) {
217
116
  els.process();
218
117
 
219
118
  var hash = HashUtil.hashFromString(els.getParsedSql());
220
- DataTextAgent.SQL.add(hash, els.getParsedSql());
221
119
 
222
- if(hash === sqlHash) {
120
+ if (hash === sqlHash) {
223
121
  psql = new ParsedSql(els.sqlType, hash, null);
224
122
  nonLiteSql.put(sqlHash, psql);
225
123
  } else {
@@ -229,4 +127,347 @@ function escapeLiteral(sql) {
229
127
  return psql;
230
128
  }
231
129
 
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
+
232
473
  exports.MssqlObserver = MssqlObserver;