whatap 0.4.78 → 0.4.80

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 (216) hide show
  1. package/.vscode/keep-context.json +3 -3
  2. package/README.md +51 -51
  3. package/bindings/darwin/x64/whatap.node +0 -0
  4. package/bindings/linux/ia32/whatap.node +0 -0
  5. package/bindings/linux/x64/whatap.node +0 -0
  6. package/help.txt +10 -10
  7. package/index.js +8 -8
  8. package/lib/conf/conf-sys-mon.js +100 -100
  9. package/lib/conf/config-default.js +238 -238
  10. package/lib/conf/configure.js +423 -423
  11. package/lib/conf/license.js +41 -41
  12. package/lib/control/cmd-config.js +23 -23
  13. package/lib/control/control-handler.js +344 -344
  14. package/lib/control/packagectr-helper.js +149 -149
  15. package/lib/core/agent.js +329 -328
  16. package/lib/core/interceptor.js +142 -142
  17. package/lib/core/request-agent.js +26 -26
  18. package/lib/counter/counter-manager.js +127 -127
  19. package/lib/counter/meter/meter-activex.js +66 -66
  20. package/lib/counter/meter/meter-httpc.js +57 -57
  21. package/lib/counter/meter/meter-resource.js +9 -9
  22. package/lib/counter/meter/meter-service.js +167 -167
  23. package/lib/counter/meter/meter-socket.io.js +50 -50
  24. package/lib/counter/meter/meter-sql.js +70 -70
  25. package/lib/counter/meter/meter-users.js +57 -57
  26. package/lib/counter/meter.js +183 -183
  27. package/lib/counter/task/activetransaction.js +93 -93
  28. package/lib/counter/task/agentinfo.js +105 -105
  29. package/lib/counter/task/counter-task.js +9 -9
  30. package/lib/counter/task/gcstat.js +34 -34
  31. package/lib/counter/task/heapmem.js +24 -24
  32. package/lib/counter/task/httpc.js +75 -75
  33. package/lib/counter/task/proc-cpu.js +28 -28
  34. package/lib/counter/task/realtimeuser.js +30 -30
  35. package/lib/counter/task/res/systemECSTask.js +54 -54
  36. package/lib/counter/task/res/systemKubeTask.js +52 -52
  37. package/lib/counter/task/res/util/awsEcsClientThread.js +166 -166
  38. package/lib/counter/task/res/util/linuxProcStatUtil.js +13 -13
  39. package/lib/counter/task/res-sys-cpu.js +61 -61
  40. package/lib/counter/task/service.js +201 -201
  41. package/lib/counter/task/socketio.js +29 -29
  42. package/lib/counter/task/sql.js +104 -104
  43. package/lib/counter/task/systemperf.js +42 -42
  44. package/lib/data/datapack-sender.js +256 -256
  45. package/lib/data/dataprofile-agent.js +136 -136
  46. package/lib/data/datatext-agent.js +135 -135
  47. package/lib/data/event-level.js +15 -15
  48. package/lib/data/test.js +48 -48
  49. package/lib/env/constants.js +20 -20
  50. package/lib/kube/kube-client.js +143 -143
  51. package/lib/lang/text-types.js +58 -58
  52. package/lib/logger.js +319 -319
  53. package/lib/net/netflag.js +54 -54
  54. package/lib/net/paramdef.js +40 -40
  55. package/lib/net/receiver.js +65 -65
  56. package/lib/net/security-master.js +182 -173
  57. package/lib/net/sender.js +140 -140
  58. package/lib/net/tcp-return.js +17 -17
  59. package/lib/net/tcp-session.js +285 -285
  60. package/lib/net/tcpreq-client-proxy.js +69 -69
  61. package/lib/net/tcprequest-mgr.js +57 -57
  62. package/lib/observers/cluster-observer.js +21 -21
  63. package/lib/observers/express-observer.js +214 -214
  64. package/lib/observers/file-observer.js +184 -184
  65. package/lib/observers/global-observer.js +30 -30
  66. package/lib/observers/http-observer.js +704 -704
  67. package/lib/observers/maria-observer.js +382 -382
  68. package/lib/observers/memcached-observer.js +55 -55
  69. package/lib/observers/mongo-observer.js +262 -265
  70. package/lib/observers/mongodb-observer.js +197 -197
  71. package/lib/observers/mongoose-observer.js +83 -83
  72. package/lib/observers/mssql-observer.js +205 -205
  73. package/lib/observers/mysql-observer.js +436 -394
  74. package/lib/observers/net-observer.js +72 -72
  75. package/lib/observers/pgsql-observer.js +295 -295
  76. package/lib/observers/process-observer.js +25 -25
  77. package/lib/observers/promise-observer.js +31 -31
  78. package/lib/observers/redis-observer.js +156 -109
  79. package/lib/observers/schedule-observer.js +66 -66
  80. package/lib/observers/socket.io-observer.js +54 -54
  81. package/lib/observers/stream-observer.js +19 -19
  82. package/lib/observers/thrift-observer.js +196 -196
  83. package/lib/pack/activestack-pack.js +54 -54
  84. package/lib/pack/counter-pack.js +649 -649
  85. package/lib/pack/errorsnap-pack.js +68 -68
  86. package/lib/pack/event-pack.js +53 -53
  87. package/lib/pack/hitmap-pack.js +62 -62
  88. package/lib/pack/hitmap-pack1.js +146 -146
  89. package/lib/pack/netstat.js +14 -14
  90. package/lib/pack/pack.js +49 -49
  91. package/lib/pack/packenum.js +60 -60
  92. package/lib/pack/param-pack.js +213 -213
  93. package/lib/pack/profile-pack.js +48 -48
  94. package/lib/pack/realtimeuser-pack.js +40 -40
  95. package/lib/pack/stat-general-pack.js +95 -95
  96. package/lib/pack/staterror-pack.js +119 -119
  97. package/lib/pack/stathttpc-pack.js +66 -66
  98. package/lib/pack/stathttpc-rec.js +78 -78
  99. package/lib/pack/statremote-pack.js +45 -45
  100. package/lib/pack/statservice-pack.js +62 -62
  101. package/lib/pack/statservice-pack1.js +87 -87
  102. package/lib/pack/statservice-rec.js +292 -292
  103. package/lib/pack/statservice-rec_dep.js +151 -151
  104. package/lib/pack/statsql-pack.js +69 -69
  105. package/lib/pack/statsql-rec.js +100 -100
  106. package/lib/pack/statuseragent-pack.js +43 -43
  107. package/lib/pack/tagcount-pack.js +398 -398
  108. package/lib/pack/tagctr.js +14 -14
  109. package/lib/pack/text-pack.js +49 -49
  110. package/lib/pack/time-count.js +25 -25
  111. package/lib/pack/websocket.js +14 -14
  112. package/lib/plugin/plugin-loadermanager.js +56 -56
  113. package/lib/plugin/plugin.js +75 -75
  114. package/lib/requestlog.js +326 -326
  115. package/lib/service/tx-record.js +288 -284
  116. package/lib/stat/stat-error.js +116 -116
  117. package/lib/stat/stat-httpc.js +97 -97
  118. package/lib/stat/stat-remoteip.js +46 -46
  119. package/lib/stat/stat-sql.js +112 -112
  120. package/lib/stat/stat-tranx.js +57 -57
  121. package/lib/stat/stat-tx-caller.js +159 -159
  122. package/lib/stat/stat-tx-domain.js +110 -110
  123. package/lib/stat/stat-tx-referer.js +111 -111
  124. package/lib/stat/stat-useragent.js +48 -48
  125. package/lib/stat/timingsender.js +72 -72
  126. package/lib/step/activestack-step.js +37 -37
  127. package/lib/step/dbc-step.js +35 -35
  128. package/lib/step/http-stepx.js +66 -66
  129. package/lib/step/message-step.js +39 -39
  130. package/lib/step/method-stepx.js +46 -46
  131. package/lib/step/resultset-step.js +39 -39
  132. package/lib/step/securemsg-step.js +43 -43
  133. package/lib/step/socket-step.js +46 -46
  134. package/lib/step/sql-stepx.js +67 -67
  135. package/lib/step/sqlxtype.js +15 -15
  136. package/lib/step/step.js +65 -65
  137. package/lib/step/stepenum.js +53 -53
  138. package/lib/trace/local-context.js +13 -13
  139. package/lib/trace/parsed-sql.js +13 -13
  140. package/lib/trace/profile-collector.js +70 -70
  141. package/lib/trace/serviceurl-pattern-detector.js +117 -117
  142. package/lib/trace/trace-context-manager.js +195 -195
  143. package/lib/trace/trace-context.js +134 -134
  144. package/lib/util/anylist.js +102 -102
  145. package/lib/util/array-util.js +100 -100
  146. package/lib/util/bitutil.js +27 -27
  147. package/lib/util/cardinality/hyperloglog.js +105 -105
  148. package/lib/util/cardinality/murmurhash.js +31 -31
  149. package/lib/util/cardinality/registerset.js +74 -74
  150. package/lib/util/config-util.js +17 -17
  151. package/lib/util/cypher.js +89 -89
  152. package/lib/util/datetimehelper.js +237 -229
  153. package/lib/util/dateutil.js +110 -106
  154. package/lib/util/errordata.js +20 -20
  155. package/lib/util/escape-literal-sql.js +342 -342
  156. package/lib/util/hashutil2.js +126 -126
  157. package/lib/util/hexa32.js +57 -57
  158. package/lib/util/index.js +78 -78
  159. package/lib/util/intint-map.js +47 -47
  160. package/lib/util/intkey-linkedmap.js +26 -26
  161. package/lib/util/intkey-map.js +25 -25
  162. package/lib/util/intset.js +82 -82
  163. package/lib/util/iputil.js +119 -119
  164. package/lib/util/iputil_x.js +526 -526
  165. package/lib/util/keygen.js +17 -17
  166. package/lib/util/kube-util.js +72 -72
  167. package/lib/util/longint-linkedmap.js +35 -35
  168. package/lib/util/longkey-linkedmap.js +25 -25
  169. package/lib/util/longlong-linkedmap.js +37 -37
  170. package/lib/util/nodeutil.js +67 -67
  171. package/lib/util/oidutil.js +96 -93
  172. package/lib/util/paramsecurity.js +78 -78
  173. package/lib/util/pathtree.js +172 -172
  174. package/lib/util/pre-process.js +13 -13
  175. package/lib/util/process-seq.js +165 -165
  176. package/lib/util/property-util.js +35 -35
  177. package/lib/util/request-queue.js +42 -42
  178. package/lib/util/requestdouble-queue.js +72 -72
  179. package/lib/util/resourceprofile.js +156 -156
  180. package/lib/util/seedrandom.js +242 -242
  181. package/lib/util/stop-watch.js +29 -29
  182. package/lib/util/string-util.js +9 -9
  183. package/lib/util/stringkey-linkedmap.js +28 -28
  184. package/lib/util/stringnum-linkedmap.js +31 -31
  185. package/lib/util/stringset.js +65 -65
  186. package/lib/util/system-util.js +9 -9
  187. package/lib/util/userid-util.js +57 -57
  188. package/lib/util/utils.js +67 -67
  189. package/lib/value/blob-value.js +61 -61
  190. package/lib/value/boolean-value.js +51 -51
  191. package/lib/value/decimal-value.js +71 -71
  192. package/lib/value/double-summary.js +105 -105
  193. package/lib/value/double-value.js +50 -50
  194. package/lib/value/float-array.js +59 -59
  195. package/lib/value/float-value.js +64 -64
  196. package/lib/value/int-array.js +59 -59
  197. package/lib/value/int-map-value.js +151 -151
  198. package/lib/value/int-value.js +64 -64
  199. package/lib/value/ip4-value.js +83 -83
  200. package/lib/value/list-value.js +136 -136
  201. package/lib/value/long-array.js +59 -59
  202. package/lib/value/long-summary.js +105 -105
  203. package/lib/value/map-value.js +175 -175
  204. package/lib/value/metric-value.js +157 -157
  205. package/lib/value/null-value.js +42 -42
  206. package/lib/value/number-value.js +34 -34
  207. package/lib/value/summary-value.js +29 -29
  208. package/lib/value/text-array.js +117 -117
  209. package/lib/value/text-value.js +59 -59
  210. package/lib/value/texthash-value.js +49 -49
  211. package/lib/value/value.js +14 -14
  212. package/lib/value/valueenum.js +99 -99
  213. package/logs/whatap-20230906.log +54 -0
  214. package/package.json +28 -28
  215. package/whatap.conf +1 -1
  216. package/logs/whatap-20230616.log +0 -13
@@ -1,705 +1,705 @@
1
- /**
2
- * Copyright 2016 the WHATAP project authors. All rights reserved.
3
- * Use of this source code is governed by a license that
4
- * can be found in the LICENSE file.
5
- */
6
-
7
- const { reqlog_x_txid } = require('../conf/config-default');
8
- const controlHandler = require('../control/control-handler');
9
- const RequestLog = require('../requestlog');
10
- var TraceContextManager = require('../trace/trace-context-manager'),
11
- URLPatternDetector = require('../trace/serviceurl-pattern-detector').Detector,
12
- DataTextAgent = require('../data/datatext-agent'),
13
- DataProfileAgent = require('../data/dataprofile-agent'),
14
- EventLevel = require('../data/event-level'),
15
- HttpStepX = require('../step/http-stepx'),
16
- TxRecord = require('../service/tx-record'),
17
- StatError = require('../stat/stat-error'),
18
- StatHttpc = require('../stat/stat-httpc'),
19
- StatTranxMtCaller = require('../stat/stat-tx-caller'),
20
- ProfilePack = require('../pack/profile-pack'),
21
- DataInputX = require('../io/data-inputx'),
22
- SecurityMaster = require('../net/security-master'),
23
- MeterService = require('../counter/meter/meter-service').MeterService,
24
- MeterUsers = require('../counter/meter/meter-users'),
25
- MeterHttpC = require('../counter/meter/meter-httpc'),
26
- conf = require('../conf/configure'),
27
- HashUtil = require('../util/hashutil'),
28
- UserIdUtil = require('../util/userid-util'),
29
- DateUtil = require('../util/dateutil'),
30
- IPUtil = require('../util/iputil'),
31
- Hexa32 = require('../util/hexa32'),
32
- ResourceProfile = require('../util/resourceprofile'),
33
- TextTypes = require('../lang/text-types'),
34
- MessageStep = require('../step/message-step'),
35
- PluginLoaderManager = require('../plugin/plugin-loadermanager'),
36
- Long = require('long'),
37
- KeyGen = require('../util/keygen'),
38
- Logger = require('../logger');
39
-
40
- var _exts=new Set([".css",".js",".png", ".htm", ".html", ".gif", ".jpg", ".css", ".txt", ".ico"]);
41
-
42
- var configIpHeaderKey = conf.trace_http_client_ip_header_key;
43
- var configUserAgentKey = undefined;
44
- var configRefererKey = undefined;
45
- var trace_origin_url = false;
46
- conf.on('trace_http_client_ip_header_key', function(newProperty) {
47
- configIpHeaderKey = newProperty;
48
- });
49
- conf.on('trace_normalize_urls', function (newProps) {
50
- URLPatternDetector.build(true);
51
- });
52
- conf.on('trace_auto_normalize_enabled', function (newProps) {
53
- URLPatternDetector.build(true);
54
- });
55
- conf.on('trace_normalize_enabled', function (newProps) {
56
- URLPatternDetector.build(true);
57
- });
58
- conf.on('trace_user_agent_header_key', function (newProps) {
59
- configUserAgentKey = newProps;
60
- });
61
- conf.on('trace_referer_header_key', function (newProps) {
62
- configRefererKey = newProps;
63
- });
64
- conf.on('trace_origin_url', function (newProps) {
65
- trace_origin_url = newProps;
66
- })
67
-
68
- var staticConents = function (newProps) {
69
- var x=new Set();
70
- var words = !newProps?[]:newProps.split(',');
71
- for(var i = 0 ; i < words.length ; i++) {
72
- var ex = words[i].trim();
73
- if(ex.length>0){
74
- if(ex.startsWith(".")){
75
- x.add(ex);
76
- }else{
77
- x.add("."+ex );
78
- }
79
- }
80
- }
81
-
82
- _exts =x;
83
- };
84
- conf.on('web_static_content_extensions', staticConents);
85
- staticConents(conf["web_static_content_extensions"]);
86
-
87
- var HttpObserver = function(agent){
88
- this.agent = agent;
89
- this.packages = ['http','https'];
90
- URLPatternDetector.build(true);
91
- };
92
-
93
- HttpObserver.prototype.__createTransactionObserver = function(callback, isHttps, server) {
94
- var self = this;
95
- var aop = this.agent.aop;
96
-
97
- return function (req, res) {
98
- var ctx = initCtx(req, res);
99
- if( ctx == null ) { return callback(req, res); }
100
-
101
- PluginLoaderManager.do('httpservicestart', ctx, req, res);
102
- if(trace_origin_url === true){
103
- var originUrlHash = HashUtil.hashFromString('Origin url');
104
- var step = new MessageStep();
105
- step.hash = originUrlHash;
106
- step.start_time = ctx.getElapsedTime();
107
- step.desc = req.url;
108
-
109
- DataTextAgent.MESSAGE.add(originUrlHash, 'Origin url');
110
- ctx.profile.add(step);
111
- }
112
-
113
- aop.after(res, 'end', function(obj, args) {
114
- if(TraceContextManager.resume(ctx._id) == null) { return; }
115
- PluginLoaderManager.do('httpserviceend', ctx, req, res);
116
-
117
- ctx.isStaticContents = isStatic(req.url);
118
- ctx.http_method = req.method;
119
- if(conf.profile_http_querystring_enabled){
120
- ctx.http_query = JSON.stringify(req.query);
121
- }
122
- ctx.http_content_type = (req.headers['content_type'] || '');
123
- ctx.status = Math.floor(obj.statusCode / 100);
124
-
125
- // 에러가 발생했지만 스택수집안했을 경우
126
- if (ctx.status >= 4 && ctx.error.isZero()) {
127
- ctx.error = StatError.addError(obj.statusCode, obj.statusMessage,
128
- ctx.service_hash);
129
- ctx.statusCode = obj.statusCode;
130
- ctx.statusMessage = obj.statusMessage;
131
- }
132
-
133
- self.__endTransaction(null, ctx, req, res);
134
- });
135
-
136
- try {
137
- return callback.apply(this, arguments);
138
- } catch (e) {
139
- Logger.printError("WHATAP-606", 'Hooking request failed..', e, false);
140
- self.__endTransaction(e, ctx, req, res);
141
- throw e;
142
- }
143
- };
144
- };
145
-
146
- function isStatic(u){
147
- var x = u.indexOf('.');
148
- if(x<=0) return false;
149
-
150
- var ext = u.substring(x);
151
- return _exts.has(ext);
152
- }
153
- function initCtx(req, res) {
154
- /*url이 없으면 추적하지 않는다*/
155
- if(req.url == null) { return null; }
156
-
157
- var ctx = TraceContextManager.start();
158
- if(ctx == null) { return null; }
159
-
160
- req.__ctx_id__ = ctx._id;
161
-
162
- var url = req.url,
163
- index = url.indexOf('?');
164
- if(index >= 0) {
165
- url = url.slice(0, index);
166
- }
167
- ctx.service_name = URLPatternDetector.normalize(url);
168
- try {
169
- if(conf.trace_service_port_enabled === true && server.address()) {
170
- ctx.service_name += ' {' + server.address().port + '}';
171
- }
172
- } catch(e){
173
- }
174
-
175
- try {
176
- if(conf.trace_transaction_name_header_key != null) {
177
- ctx.service_name = req.headers[conf.trace_transaction_name_header_key] + ctx.service_name;
178
- }
179
- } catch(e) {
180
- }
181
-
182
- ctx.service_hash = HashUtil.hashFromString(ctx.service_name);
183
- // DataTextAgent.SERVICE.add(ctx.service_hash, ctx.service_name);
184
-
185
- ctx.isStaticContents = isStatic(req.url);
186
-
187
- var referer = undefined;
188
- if(configRefererKey && req.headers[configRefererKey]){
189
- referer = req.headers[configRefererKey];
190
- }else if(req.headers.referer){
191
- referer = req.headers.referer;
192
- }
193
- if (referer) {
194
- ctx.referer = HashUtil.hashFromString(referer);
195
- DataTextAgent.REFERER.add(ctx.referer, referer);
196
- }
197
-
198
- if(configUserAgentKey && req.headers[configUserAgentKey]){
199
- ctx.userAgentString = req.headers[configUserAgentKey];
200
- }else if(req.headers['user-agent']){
201
- ctx.userAgentString = req.headers['user-agent'];
202
- }
203
- if(ctx.userAgentString){
204
- ctx.userAgent = HashUtil.hashFromString(ctx.userAgentString);
205
- DataTextAgent.USERAGENT.add(ctx.userAgent, ctx.userAgentString);
206
- }
207
-
208
- ctx.http_host=req.headers.host;
209
- if (ctx.http_host) {
210
- ctx.http_host_hash = HashUtil.hashFromString(ctx.http_host);
211
- DataTextAgent.HTTP_DOMAIN.add(ctx.http_host_hash, ctx.http_host);
212
- }
213
-
214
- ctx.start_malloc = ResourceProfile.getUsedHeapSize();
215
- ctx.start_cpu = ResourceProfile.getCPUTime();
216
- ctx.http_method = req.method;
217
- if(conf.profile_http_querystring_enabled){
218
- ctx.http_query = JSON.stringify(req.query);
219
- }
220
- ctx.http_content_type = (req.headers['content_type'] || '');
221
- var remote_addr;
222
- try {
223
- remote_addr = req.headers[configIpHeaderKey] || req.connection.remoteAddress || "0.0.0.0";
224
- remote_addr=IPUtil.checkIp4(remote_addr);
225
- ctx.remoteIp = IPUtil.stringToInt(remote_addr);
226
- switch (conf.trace_user_using_type || 3) {
227
- case 1:
228
- ctx.userid = Long.fromNumber(ctx.remoteIp);
229
- MeterUsers.add(ctx.userid);
230
- break;
231
- case 2:
232
- // MeterUsers.add(ctx.userid);
233
- break;
234
- case 3:
235
- ctx.userid = UserIdUtil.getUserId(req, res, 0);
236
- MeterUsers.add(ctx.userid);
237
- break;
238
- }
239
-
240
- } catch (e) {
241
- }
242
- /************************************/
243
- /* Header / param Trace */
244
- /************************************/
245
- var header_enabled = false;
246
- if(conf.profile_http_header_enabled === true && req.headers) {
247
- header_enabled = true;
248
- var prefix = conf.profile_header_url_prefix;
249
- if(prefix && ctx.service_name.indexOf(prefix) < 0) {
250
- header_enabled = false;
251
- }
252
- }
253
-
254
- if(header_enabled) {
255
- var step = new MessageStep();
256
- step.hash = HashUtil.hashFromString("HTTP-HEADERS");
257
- step.start_time = ctx.getElapsedTime();
258
- step.desc = JSON.stringify(req.headers);
259
- DataTextAgent.MESSAGE.add(step.hash, "HTTP-HEADERS");
260
- ctx.profile.push(step);
261
- }
262
- /************************************/
263
- /* Multi Server Transaction Trace */
264
- /************************************/
265
- if(conf.mtrace_enabled) {
266
- var poid=req.headers['x-wtap-po'];
267
- if (poid != null) {
268
- ctx.setCallerPOID(poid);
269
- try{
270
- if(conf.mtid_mtrace_enabled) {
271
- var mt_caller=req.headers[conf._trace_mtrace_caller_key];
272
- if(mt_caller){
273
- var x = mt_caller.indexOf(',');
274
- if (x > 0) {
275
- ctx.mtid = Hexa32.toLong32(mt_caller.substring(0, x));
276
- ctx.mtid_build_checked = true;
277
- var y = mt_caller.indexOf(',', x + 1);
278
- if (y > 0) {
279
- ctx.mdepth = parseInt(mt_caller.substring(x + 1, y));
280
- var z = mt_caller.indexOf(',', y + 1);
281
- if (z < 0) {
282
- ctx.mcaller_txid = Hexa32.toLong32(mt_caller.substring(y + 1));
283
- } else {
284
- ctx.mcaller_txid = Hexa32.toLong32(mt_caller.substring(y + 1, z));
285
- }
286
- }
287
- }
288
- }
289
- }
290
- if (conf.stat_mtrace_enabled) {
291
- var inf=req.headers[conf._trace_mtrace_spec_key1];
292
- if(inf != null && inf.length > 0){
293
- var px = inf.indexOf(',');
294
- ctx.mcaller_spec = inf.substring(0, px);
295
- ctx.mcaller_url = inf.substring(px + 1);
296
- }
297
- }
298
- } catch(e) {
299
- Logger.printError('WHATAP-850', 'Multi Server Transaction ', e, true);
300
- }
301
- }
302
- }
303
-
304
- return ctx;
305
- };
306
-
307
- HttpObserver.prototype.__endTransaction = function(error, ctx, req, res) {
308
- var param_enabled = false;
309
- if(conf.profile_http_parameter_enabled === true) {
310
- param_enabled = true;
311
- var prefix = conf.profile_http_parameter_url_prefix;
312
- if(prefix && ctx.service_name.indexOf(prefix) < 0) {
313
- param_enabled = false;
314
- }
315
- }
316
-
317
- if(param_enabled) {
318
- var query = JSON.stringify(req.query || '');
319
- var body = JSON.stringify(req.body || '');
320
- //var param = JSON.stringify(req.params || '');
321
- //console.log(query.length + " // " + body.length);
322
- var step = new MessageStep();
323
- step.hash = HashUtil.hashFromString("HTTP-PARAMETERS");
324
- step.start_time = ctx.getElapsedTime();
325
- if(query.length > 2) {
326
- step.desc = '[GET] ' + query;
327
- } else {
328
- step.desc = '[POST] ' + body;
329
- }
330
- DataTextAgent.MESSAGE.add(step.hash, "HTTP-PARAMETERS");
331
- ctx.profile.push(step);
332
- }
333
-
334
- if(error) {
335
- TraceContextManager.end(ctx != null ? ctx._id : null);
336
- ctx = null;
337
- return;
338
- }
339
-
340
- if(ctx == null || TraceContextManager.isExist(ctx._id) === false) { return; }
341
-
342
- if(ctx.isStaticContents !== true && conf._trace_ignore_url_set[ctx.service_hash]){
343
- ctx.isStaticContents = true;
344
- }
345
-
346
- if(conf._is_trace_ignore_url_prefix === true && ctx.service_name.startsWith(conf.trace_ignore_url_prefix) === true){
347
- ctx.isStaticContents = true;
348
- }
349
-
350
- if(ctx.isStaticContents){
351
- TraceContextManager.end(ctx._id);
352
- ctx = null;
353
- return;
354
- }
355
-
356
- try {
357
- var profile = new ProfilePack();
358
- var wtx = new TxRecord();
359
- // profile.time = ctx.start_time;
360
- wtx.endTime = DateUtil.currentTime();
361
- profile.time = wtx.endTime;
362
- wtx.elapsed = ctx.getElapsedTime();
363
-
364
- ctx.service_hash = HashUtil.hashFromString(ctx.service_name);
365
- DataTextAgent.SERVICE.add(ctx.service_hash, ctx.service_name);
366
-
367
- wtx.service = ctx.service_hash;
368
- wtx.cpuTime = ResourceProfile.getCPUTime() - ctx.start_cpu;
369
- wtx.malloc = ResourceProfile.getUsedHeapSize()-ctx.start_malloc;
370
- if(wtx.malloc < 0) { wtx.malloc = 0; }
371
-
372
- wtx.seq = ctx.txid;
373
- wtx.sqlCount = ctx.sql_count;
374
- wtx.sqlTime = ctx.sql_time;
375
- wtx.sqlFetchCount = ctx.rs_count;
376
- wtx.sqlFetchTime = parseInt(ctx.rs_time);
377
- wtx.ipaddr = ctx.remoteIp;
378
- wtx.userid = ctx.userid;
379
-
380
- if (ctx.error.isZero() === false) {
381
- wtx.error = ctx.error;
382
- wtx.errorLevel = EventLevel.WARNING;
383
- }
384
- wtx.userAgent = ctx.userAgent;
385
- wtx.referer = ctx.referer;
386
-
387
- wtx.httpcCount = ctx.httpc_count;
388
- wtx.httpcTime = ctx.httpc_time;
389
- wtx.status = ctx.status;
390
-
391
- wtx.http_method=TxRecord.HTTP_METHOD[ctx.http_method] || TxRecord.WEB_GET;
392
- wtx.http_host = ctx.http_host;
393
- wtx.mtid=ctx.mtid;
394
- wtx.mdepth=ctx.mdepth;
395
- wtx.mcaller=ctx.mcaller_txid;
396
- wtx.mcaller_pcode = ctx.mcaller_pcode;
397
- wtx.mcaller_okind = ctx.mcaller_okind;
398
- wtx.mcaller_oid = ctx.mcaller_oid;
399
-
400
- MeterService.add(wtx.service, wtx.elapsed,
401
- wtx.errorLevel, ctx.mcaller_pcode, ctx.mcaller_okind, ctx.mcaller_oid);
402
-
403
- profile.oid = SecurityMaster.OID;
404
- profile.service = wtx;
405
- if(Boolean(conf.reqlog_enabled) == true) {
406
- ctx.endTime = wtx.endTime;
407
- ctx.elapsed = wtx.elapsed;
408
- RequestLog.setRecord(ctx);
409
- }
410
- //duplicated executed... so end() first
411
- TraceContextManager.end(ctx._id);
412
- setTimeout(function () {
413
- DataProfileAgent.sendProfile(ctx, profile, false);
414
- TraceContextManager.end(ctx._id);
415
- ctx = null;
416
- }, 100);
417
-
418
- } catch (e) {
419
- Logger.printError('WHATAP-607', 'End transaction error..', e, false);
420
- TraceContextManager.end(ctx._id);
421
- ctx = null;
422
- }
423
-
424
- };
425
-
426
- var transfer_poid;
427
- function transferPOID(ctx) {
428
- if (transfer_poid)
429
- return transfer_poid;
430
- transfer_poid=Hexa32.toString32(SecurityMaster.PCODE)+','
431
- +Hexa32.toString32(SecurityMaster.OKIND)+','+Hexa32.toString32(SecurityMaster.OID);
432
- return transfer_poid;
433
- }
434
-
435
- function transferMTID_CALLERTX(ctx) {
436
- if (ctx.transfer_id)
437
- return ctx.transfer_id;
438
- var x = Hexa32.toString32(ctx.mtid) + ',' + (ctx.mdepth + 1) + ',' + Hexa32.toString32(ctx.txid);
439
- ctx.transfer_id = x;
440
- return ctx.transfer_id;
441
- }
442
- function transferSPEC_URL(ctx) {
443
- if (ctx.transfer_info)
444
- return ctx.transfer_info;
445
- var x = conf.mtrace_spec + ',' + ctx.service_hash;
446
- ctx.transfer_info = x;
447
- return ctx.transfer_info;
448
- }
449
- var check_seq = 1;
450
- function interTxTraceAutoOn(ctx) {
451
- if (conf.mtrace_enabled ==false || ctx.httpc_checked || ctx.mtid.isZero()===false)
452
- return;
453
- ctx.httpc_checked = true;
454
- if(conf.mtrace_rate>=100){
455
- ctx.mtid = KeyGen.next();
456
- return;
457
- }
458
- check_seq++;
459
- switch (Math.floor(conf.mtrace_rate / 10)) {
460
- case 10:
461
- ctx.mtid = KeyGen.next();
462
- break;
463
- case 9:
464
- if (check_seq % 10 !== 0)
465
- ctx.mtid = KeyGen.next();
466
- break;
467
- case 8:
468
- if (check_seq % 5 !== 0)
469
- ctx.mtid = KeyGen.next();
470
- break;
471
- case 7:
472
- if (check_seq % 4 !== 0)
473
- ctx.mtid = KeyGen.next();
474
- break;
475
- case 6:
476
- if (check_seq % 3 !== 0)
477
- ctx.mtid = KeyGen.next();
478
- break;
479
- case 5:
480
- if (check_seq % 2 === 0)
481
- ctx.mtid = KeyGen.next();
482
- break;
483
- case 4:
484
- if (check_seq % 3 === 0 || check_seq % 5 === 0)
485
- ctx.mtid = KeyGen.next();
486
- break;
487
- case 3:
488
- if (check_seq % 4 === 0 || check_seq % 5 === 0)
489
- ctx.mtid = KeyGen.next();
490
- break;
491
- case 2:
492
- if (check_seq % 5 === 0)
493
- ctx.mtid = KeyGen.next();
494
- break;
495
- case 1:
496
- if (check_seq % 10 === 0)
497
- ctx.mtid = KeyGen.next();
498
- break;
499
- }
500
- }
501
- HttpObserver.prototype.inject = function( mod, moduleName ) {
502
- var self = this;
503
- var aop = self.agent.aop;
504
-
505
- if(mod.__whatap_observe__) { return; }
506
- mod.__whatap_observe__ = true;
507
- Logger.initPrint("HttpObserver");
508
- if( conf.profile_enabled === false ) { return; }
509
-
510
- aop.after(mod, 'createServer', function (obj, args, ret) {
511
- aop.before(ret, 'listen', function (obj, args) {
512
- conf['whatap.port'] = (args[0] || 80);
513
- });
514
- });
515
-
516
- aop.before(mod.Server.prototype, ['on', 'addListener'], function (obj, args) {
517
- if(args[0] !== 'request') {return;}
518
-
519
- args[args.length-1] = self.__createTransactionObserver(args[args.length-1],
520
- moduleName === 'https', obj);
521
- });
522
-
523
- if( conf.httpc_enabled === false ) { return; }
524
-
525
- aop.both(mod, 'request',
526
- function (obj, args, lctx) {
527
- var ctx = lctx.context;
528
- if (ctx == null || (args[0].host == null && args[0].hostname == null) ) { return; } // for axios
529
-
530
- var isHttpsRepeat = false;
531
- if(moduleName === 'https') {
532
- args[0].__isHttps = true;
533
- }
534
-
535
- if(moduleName === 'http' && args[0].__isHttps) {
536
- isHttpsRepeat = true;
537
- }
538
-
539
- if(!isHttpsRepeat) {
540
- try {
541
- if(args[0].method === 'OPTION') {
542
- return;
543
- }
544
-
545
- var dataConsumption = false;
546
-
547
- if(args.length > 0) {
548
- var info = args[0];
549
-
550
- interTxTraceAutoOn(ctx);
551
-
552
- if(conf.mtrace_enabled){
553
- if(info.headers){
554
- info.headers['x-wtap-po']=transferPOID(ctx);
555
- }else{
556
- info.headers={
557
- 'x-wtap-po': transferPOID(ctx)
558
- };
559
- }
560
- if(conf.stat_mtrace_enabled){
561
- info.headers[conf._trace_mtrace_spec_key1]=transferSPEC_URL(ctx);
562
- }
563
- if(conf.mtid_mtrace_enabled && ctx.mtid.isZero()===false){
564
- info.headers[conf._trace_mtrace_caller_key]=transferMTID_CALLERTX(ctx);
565
- }
566
-
567
- }
568
- ctx.httpc_url = info.path || '/';
569
- ctx.httpc_host = info.host || info.hostname || '';
570
- ctx.httpc_port = info.port || -1;
571
- }
572
- ctx.footprint('Http Call Start');
573
-
574
- if (ctx.httpc_port < 0) { ctx.httpc_port = 80 };
575
-
576
- } catch(e) {
577
- return Logger.printError('WHATAP-852', 'Http Repeat ', e, true);
578
- }
579
-
580
- aop.functionHook(args, -1, function(obj, args) {
581
- if(TraceContextManager.resume(ctx._id) == null) { return; }
582
-
583
- var res = args[0];
584
- aop.before(res, ['on', 'addListener'], function(obj, args) {
585
- if(!dataConsumption && args[0] === 'data') {
586
- dataConsumption = true;
587
- }
588
- });
589
- aop.before(res, 'pipe', function() {
590
- dataConsumption = true;
591
- });
592
- aop.before(res, 'resume', function() {
593
- dataConsumption = true;
594
- });
595
-
596
- if (dataConsumption) { return; }
597
- // endHttpc(ctx, step);
598
- });
599
- }
600
- },
601
- function (obj, args, ret, lctx) {
602
- if(moduleName === 'http' && args[0].__isHttps) {
603
- return;
604
- }
605
-
606
- var ctx = lctx.context;
607
- if (ctx == null || ( args[0].host == null && args[0].hostname == null)) { return; }
608
-
609
- ret.on('response', function(response){
610
- var statusCode = response.statusCode;
611
- if(statusCode >= 400){
612
- if (step.error.isZero()) {
613
- step.error = StatError.addError(statusCode, response.statusMessage , ctx.service_hash,
614
- TextTypes.HTTPC_URL, step.url);
615
- if (ctx.error.isZero()) {
616
- ctx.error = step.error;
617
- ctx.statusCode = statusCode;
618
- ctx.statusMessage = response.statusMessage;
619
- }
620
- }
621
- }
622
- })
623
- ret.on('error', function(err) {
624
- if (TraceContextManager.resume(ctx._id) == null) { return; }
625
-
626
- if (step.error.isZero()) {
627
- step.error = StatError.addError(err.code, err.message, ctx.service_hash,
628
- TextTypes.HTTPC_URL, step.url);
629
- if (ctx.error.isZero()) {
630
- ctx.error = step.error;
631
- ctx.statusCode = err.code;
632
- ctx.statusMessage = err.message;
633
- }
634
- }
635
-
636
- endHttpc(ctx, step);
637
- });
638
-
639
- var step = new HttpStepX();
640
- step.start_time = ctx.getElapsedTime();
641
- step.url = HashUtil.hashFromString(ctx.httpc_url);
642
- DataTextAgent.HTTPC_URL.add(step.url, ctx.httpc_url);
643
- step.host = HashUtil.hashFromString(ctx.httpc_host);
644
- DataTextAgent.HTTPC_HOST.add(step.host, ctx.httpc_host);
645
- step.port = ctx.httpc_port;
646
-
647
- aop.before(ret, 'write', function (obj, args) {
648
- if(conf.profile_httpc_parameter_enabled == true) {
649
- if(args.length == 1) {
650
- var step = new MessageStep();
651
- step.hash = HashUtil.hashFromString("HTTPC-REQUEST-BODY");
652
- step.start_time = ctx.getElapsedTime();
653
- step.desc = args[0];
654
- DataTextAgent.MESSAGE.add(step.hash, "HTTPC-REQUEST-BODY");
655
- ctx.profile.push(step);
656
- }
657
- }
658
- });
659
-
660
- aop.before(ret, 'end', function (obj, args) {
661
- ctx.active_httpc_hash = step.url;
662
- ctx.profile.push(step);
663
- });
664
-
665
- ret.on('socket', function(socket) {
666
- // socket reuse chk
667
- if(conf.setSocketChk(socket) == false) {
668
- aop.before(socket, 'end', function (obj, args) {
669
- if(ctx == null) { return; }
670
- TraceContextManager.resume(ctx._id);
671
- endHttpc(ctx, step);
672
- });
673
-
674
- socket.on('timeout', function () {
675
- if (TraceContextManager.resume(ctx._id) == null) { return; }
676
- if (step.error.isZero()) {
677
- var msgObj = { 'class': 'Timeout', 'msg': 'Timeout' };
678
- step.error = StatError.addError('Timeout','Timeout', ctx.service_hash);
679
- if (ctx.error.isZero()) {
680
- ctx.error = step.error;
681
- ctx.statusCode = 'Timeout';
682
- ctx.statusMessage = 'Timeout';
683
- }
684
- }
685
- endHttpc(ctx, step);
686
- });
687
- }
688
- });
689
- });
690
-
691
- function endHttpc(ctx, step) {
692
- if(ctx == null || step == null) { return; }
693
-
694
- step.elapsed = ctx.getElapsedTime() - step.start_time;
695
-
696
- ctx.httpc_count++;
697
- ctx.httpc_time += step.elapsed;
698
-
699
- MeterHttpC.add(step.host, step.elapsed, step.error.isZero()===false);
700
- StatHttpc.addHttpcTime(ctx.service_hash, step.url, step.host, step.port, step.elapsed, step.error.isZero()===false);
701
- ctx.footprint('Http Call Done');
702
- }
703
- };
704
-
1
+ /**
2
+ * Copyright 2016 the WHATAP project authors. All rights reserved.
3
+ * Use of this source code is governed by a license that
4
+ * can be found in the LICENSE file.
5
+ */
6
+
7
+ const { reqlog_x_txid } = require('../conf/config-default');
8
+ const controlHandler = require('../control/control-handler');
9
+ const RequestLog = require('../requestlog');
10
+ var TraceContextManager = require('../trace/trace-context-manager'),
11
+ URLPatternDetector = require('../trace/serviceurl-pattern-detector').Detector,
12
+ DataTextAgent = require('../data/datatext-agent'),
13
+ DataProfileAgent = require('../data/dataprofile-agent'),
14
+ EventLevel = require('../data/event-level'),
15
+ HttpStepX = require('../step/http-stepx'),
16
+ TxRecord = require('../service/tx-record'),
17
+ StatError = require('../stat/stat-error'),
18
+ StatHttpc = require('../stat/stat-httpc'),
19
+ StatTranxMtCaller = require('../stat/stat-tx-caller'),
20
+ ProfilePack = require('../pack/profile-pack'),
21
+ DataInputX = require('../io/data-inputx'),
22
+ SecurityMaster = require('../net/security-master'),
23
+ MeterService = require('../counter/meter/meter-service').MeterService,
24
+ MeterUsers = require('../counter/meter/meter-users'),
25
+ MeterHttpC = require('../counter/meter/meter-httpc'),
26
+ conf = require('../conf/configure'),
27
+ HashUtil = require('../util/hashutil'),
28
+ UserIdUtil = require('../util/userid-util'),
29
+ DateUtil = require('../util/dateutil'),
30
+ IPUtil = require('../util/iputil'),
31
+ Hexa32 = require('../util/hexa32'),
32
+ ResourceProfile = require('../util/resourceprofile'),
33
+ TextTypes = require('../lang/text-types'),
34
+ MessageStep = require('../step/message-step'),
35
+ PluginLoaderManager = require('../plugin/plugin-loadermanager'),
36
+ Long = require('long'),
37
+ KeyGen = require('../util/keygen'),
38
+ Logger = require('../logger');
39
+
40
+ var _exts=new Set([".css",".js",".png", ".htm", ".html", ".gif", ".jpg", ".css", ".txt", ".ico"]);
41
+
42
+ var configIpHeaderKey = conf.trace_http_client_ip_header_key;
43
+ var configUserAgentKey = undefined;
44
+ var configRefererKey = undefined;
45
+ var trace_origin_url = conf.trace_origin_url;
46
+ conf.on('trace_http_client_ip_header_key', function(newProperty) {
47
+ configIpHeaderKey = newProperty;
48
+ });
49
+ conf.on('trace_normalize_urls', function (newProps) {
50
+ URLPatternDetector.build(true);
51
+ });
52
+ conf.on('trace_auto_normalize_enabled', function (newProps) {
53
+ URLPatternDetector.build(true);
54
+ });
55
+ conf.on('trace_normalize_enabled', function (newProps) {
56
+ URLPatternDetector.build(true);
57
+ });
58
+ conf.on('trace_user_agent_header_key', function (newProps) {
59
+ configUserAgentKey = newProps;
60
+ });
61
+ conf.on('trace_referer_header_key', function (newProps) {
62
+ configRefererKey = newProps;
63
+ });
64
+ conf.on('trace_origin_url', function (newProps) {
65
+ trace_origin_url = newProps;
66
+ })
67
+
68
+ var staticConents = function (newProps) {
69
+ var x=new Set();
70
+ var words = !newProps?[]:newProps.split(',');
71
+ for(var i = 0 ; i < words.length ; i++) {
72
+ var ex = words[i].trim();
73
+ if(ex.length>0){
74
+ if(ex.startsWith(".")){
75
+ x.add(ex);
76
+ }else{
77
+ x.add("."+ex );
78
+ }
79
+ }
80
+ }
81
+
82
+ _exts =x;
83
+ };
84
+ conf.on('web_static_content_extensions', staticConents);
85
+ staticConents(conf["web_static_content_extensions"]);
86
+
87
+ var HttpObserver = function(agent){
88
+ this.agent = agent;
89
+ this.packages = ['http','https'];
90
+ URLPatternDetector.build(true);
91
+ };
92
+
93
+ HttpObserver.prototype.__createTransactionObserver = function(callback, isHttps, server) {
94
+ var self = this;
95
+ var aop = this.agent.aop;
96
+
97
+ return function (req, res) {
98
+ var ctx = initCtx(req, res);
99
+ if( ctx == null ) { return callback(req, res); }
100
+
101
+ PluginLoaderManager.do('httpservicestart', ctx, req, res);
102
+ if(trace_origin_url === true){
103
+ var originUrlHash = HashUtil.hashFromString('Origin url');
104
+ var step = new MessageStep();
105
+ step.hash = originUrlHash;
106
+ step.start_time = ctx.getElapsedTime();
107
+ step.desc = req.url;
108
+
109
+ DataTextAgent.MESSAGE.add(originUrlHash, 'Origin url');
110
+ ctx.profile.add(step);
111
+ }
112
+
113
+ aop.after(res, 'end', function(obj, args) {
114
+ if(TraceContextManager.resume(ctx._id) == null) { return; }
115
+ PluginLoaderManager.do('httpserviceend', ctx, req, res);
116
+
117
+ ctx.isStaticContents = isStatic(req.url);
118
+ ctx.http_method = req.method;
119
+ if(conf.profile_http_querystring_enabled){
120
+ ctx.http_query = JSON.stringify(req.query);
121
+ }
122
+ ctx.http_content_type = (req.headers['content_type'] || '');
123
+ ctx.status = Math.floor(obj.statusCode / 100);
124
+
125
+ // 에러가 발생했지만 스택수집안했을 경우
126
+ if (ctx.status >= 4 && ctx.error.isZero()) {
127
+ ctx.error = StatError.addError(obj.statusCode, obj.statusMessage,
128
+ ctx.service_hash);
129
+ ctx.statusCode = obj.statusCode;
130
+ ctx.statusMessage = obj.statusMessage;
131
+ }
132
+
133
+ self.__endTransaction(null, ctx, req, res);
134
+ });
135
+
136
+ try {
137
+ return callback.apply(this, arguments);
138
+ } catch (e) {
139
+ Logger.printError("WHATAP-606", 'Hooking request failed..', e, false);
140
+ self.__endTransaction(e, ctx, req, res);
141
+ throw e;
142
+ }
143
+ };
144
+ };
145
+
146
+ function isStatic(u){
147
+ var x = u.lastIndexOf('.');
148
+ if(x<=0) return false;
149
+
150
+ var ext = u.substring(x);
151
+ return _exts.has(ext);
152
+ }
153
+ function initCtx(req, res) {
154
+ /*url이 없으면 추적하지 않는다*/
155
+ if(req.url == null) { return null; }
156
+
157
+ var ctx = TraceContextManager.start();
158
+ if(ctx == null) { return null; }
159
+
160
+ req.__ctx_id__ = ctx._id;
161
+
162
+ var url = req.url,
163
+ index = url.indexOf('?');
164
+ if(index >= 0) {
165
+ url = url.slice(0, index);
166
+ }
167
+ ctx.service_name = URLPatternDetector.normalize(url);
168
+ try {
169
+ if(conf.trace_service_port_enabled === true && server.address()) {
170
+ ctx.service_name += ' {' + server.address().port + '}';
171
+ }
172
+ } catch(e){
173
+ }
174
+
175
+ try {
176
+ if(conf.trace_transaction_name_header_key != null) {
177
+ ctx.service_name = req.headers[conf.trace_transaction_name_header_key] + ctx.service_name;
178
+ }
179
+ } catch(e) {
180
+ }
181
+
182
+ ctx.service_hash = HashUtil.hashFromString(ctx.service_name);
183
+ // DataTextAgent.SERVICE.add(ctx.service_hash, ctx.service_name);
184
+
185
+ ctx.isStaticContents = isStatic(req.url);
186
+
187
+ var referer = undefined;
188
+ if(configRefererKey && req.headers[configRefererKey]){
189
+ referer = req.headers[configRefererKey];
190
+ }else if(req.headers.referer){
191
+ referer = req.headers.referer;
192
+ }
193
+ if (referer) {
194
+ ctx.referer = HashUtil.hashFromString(referer);
195
+ DataTextAgent.REFERER.add(ctx.referer, referer);
196
+ }
197
+
198
+ if(configUserAgentKey && req.headers[configUserAgentKey]){
199
+ ctx.userAgentString = req.headers[configUserAgentKey];
200
+ }else if(req.headers['user-agent']){
201
+ ctx.userAgentString = req.headers['user-agent'];
202
+ }
203
+ if(ctx.userAgentString){
204
+ ctx.userAgent = HashUtil.hashFromString(ctx.userAgentString);
205
+ DataTextAgent.USERAGENT.add(ctx.userAgent, ctx.userAgentString);
206
+ }
207
+
208
+ ctx.http_host=req.headers.host;
209
+ if (ctx.http_host) {
210
+ ctx.http_host_hash = HashUtil.hashFromString(ctx.http_host);
211
+ DataTextAgent.HTTP_DOMAIN.add(ctx.http_host_hash, ctx.http_host);
212
+ }
213
+
214
+ ctx.start_malloc = ResourceProfile.getUsedHeapSize();
215
+ ctx.start_cpu = ResourceProfile.getCPUTime();
216
+ ctx.http_method = req.method;
217
+ if(conf.profile_http_querystring_enabled){
218
+ ctx.http_query = JSON.stringify(req.query);
219
+ }
220
+ ctx.http_content_type = (req.headers['content_type'] || '');
221
+ var remote_addr;
222
+ try {
223
+ remote_addr = req.headers[configIpHeaderKey] || req.connection.remoteAddress || "0.0.0.0";
224
+ remote_addr=IPUtil.checkIp4(remote_addr);
225
+ ctx.remoteIp = IPUtil.stringToInt(remote_addr);
226
+ switch (conf.trace_user_using_type || 3) {
227
+ case 1:
228
+ ctx.userid = Long.fromNumber(ctx.remoteIp);
229
+ MeterUsers.add(ctx.userid);
230
+ break;
231
+ case 2:
232
+ // MeterUsers.add(ctx.userid);
233
+ break;
234
+ case 3:
235
+ ctx.userid = UserIdUtil.getUserId(req, res, 0);
236
+ MeterUsers.add(ctx.userid);
237
+ break;
238
+ }
239
+
240
+ } catch (e) {
241
+ }
242
+ /************************************/
243
+ /* Header / param Trace */
244
+ /************************************/
245
+ var header_enabled = false;
246
+ if(conf.profile_http_header_enabled === true && req.headers) {
247
+ header_enabled = true;
248
+ var prefix = conf.profile_header_url_prefix;
249
+ if(prefix && ctx.service_name.indexOf(prefix) < 0) {
250
+ header_enabled = false;
251
+ }
252
+ }
253
+
254
+ if(header_enabled) {
255
+ var step = new MessageStep();
256
+ step.hash = HashUtil.hashFromString("HTTP-HEADERS");
257
+ step.start_time = ctx.getElapsedTime();
258
+ step.desc = JSON.stringify(req.headers);
259
+ DataTextAgent.MESSAGE.add(step.hash, "HTTP-HEADERS");
260
+ ctx.profile.push(step);
261
+ }
262
+ /************************************/
263
+ /* Multi Server Transaction Trace */
264
+ /************************************/
265
+ if(conf.mtrace_enabled) {
266
+ var poid=req.headers['x-wtap-po'];
267
+ if (poid != null) {
268
+ ctx.setCallerPOID(poid);
269
+ try{
270
+ if(conf.mtid_mtrace_enabled) {
271
+ var mt_caller=req.headers[conf._trace_mtrace_caller_key];
272
+ if(mt_caller){
273
+ var x = mt_caller.indexOf(',');
274
+ if (x > 0) {
275
+ ctx.mtid = Hexa32.toLong32(mt_caller.substring(0, x));
276
+ ctx.mtid_build_checked = true;
277
+ var y = mt_caller.indexOf(',', x + 1);
278
+ if (y > 0) {
279
+ ctx.mdepth = parseInt(mt_caller.substring(x + 1, y));
280
+ var z = mt_caller.indexOf(',', y + 1);
281
+ if (z < 0) {
282
+ ctx.mcaller_txid = Hexa32.toLong32(mt_caller.substring(y + 1));
283
+ } else {
284
+ ctx.mcaller_txid = Hexa32.toLong32(mt_caller.substring(y + 1, z));
285
+ }
286
+ }
287
+ }
288
+ }
289
+ }
290
+ if (conf.stat_mtrace_enabled) {
291
+ var inf=req.headers[conf._trace_mtrace_spec_key1];
292
+ if(inf != null && inf.length > 0){
293
+ var px = inf.indexOf(',');
294
+ ctx.mcaller_spec = inf.substring(0, px);
295
+ ctx.mcaller_url = inf.substring(px + 1);
296
+ }
297
+ }
298
+ } catch(e) {
299
+ Logger.printError('WHATAP-850', 'Multi Server Transaction ', e, true);
300
+ }
301
+ }
302
+ }
303
+
304
+ return ctx;
305
+ };
306
+
307
+ HttpObserver.prototype.__endTransaction = function(error, ctx, req, res) {
308
+ var param_enabled = false;
309
+ if(conf.profile_http_parameter_enabled === true) {
310
+ param_enabled = true;
311
+ var prefix = conf.profile_http_parameter_url_prefix;
312
+ if(prefix && ctx.service_name.indexOf(prefix) < 0) {
313
+ param_enabled = false;
314
+ }
315
+ }
316
+
317
+ if(param_enabled) {
318
+ var query = JSON.stringify(req.query || '');
319
+ var body = JSON.stringify(req.body || '');
320
+ //var param = JSON.stringify(req.params || '');
321
+ //console.log(query.length + " // " + body.length);
322
+ var step = new MessageStep();
323
+ step.hash = HashUtil.hashFromString("HTTP-PARAMETERS");
324
+ step.start_time = ctx.getElapsedTime();
325
+ if(query.length > 2) {
326
+ step.desc = '[GET] ' + query;
327
+ } else {
328
+ step.desc = '[POST] ' + body;
329
+ }
330
+ DataTextAgent.MESSAGE.add(step.hash, "HTTP-PARAMETERS");
331
+ ctx.profile.push(step);
332
+ }
333
+
334
+ if(error) {
335
+ TraceContextManager.end(ctx != null ? ctx._id : null);
336
+ ctx = null;
337
+ return;
338
+ }
339
+
340
+ if(ctx == null || TraceContextManager.isExist(ctx._id) === false) { return; }
341
+
342
+ if(ctx.isStaticContents !== true && conf._trace_ignore_url_set[ctx.service_hash]){
343
+ ctx.isStaticContents = true;
344
+ }
345
+
346
+ if(conf._is_trace_ignore_url_prefix === true && ctx.service_name.startsWith(conf.trace_ignore_url_prefix) === true){
347
+ ctx.isStaticContents = true;
348
+ }
349
+
350
+ if(ctx.isStaticContents){
351
+ TraceContextManager.end(ctx._id);
352
+ ctx = null;
353
+ return;
354
+ }
355
+
356
+ try {
357
+ var profile = new ProfilePack();
358
+ var wtx = new TxRecord();
359
+ // profile.time = ctx.start_time;
360
+ wtx.endTime = DateUtil.currentTime();
361
+ profile.time = wtx.endTime;
362
+ wtx.elapsed = ctx.getElapsedTime();
363
+
364
+ ctx.service_hash = HashUtil.hashFromString(ctx.service_name);
365
+ DataTextAgent.SERVICE.add(ctx.service_hash, ctx.service_name);
366
+
367
+ wtx.service = ctx.service_hash;
368
+ wtx.cpuTime = ResourceProfile.getCPUTime() - ctx.start_cpu;
369
+ wtx.malloc = ResourceProfile.getUsedHeapSize()-ctx.start_malloc;
370
+ if(wtx.malloc < 0) { wtx.malloc = 0; }
371
+
372
+ wtx.seq = ctx.txid;
373
+ wtx.sqlCount = ctx.sql_count;
374
+ wtx.sqlTime = ctx.sql_time;
375
+ wtx.sqlFetchCount = ctx.rs_count;
376
+ wtx.sqlFetchTime = parseInt(ctx.rs_time);
377
+ wtx.ipaddr = ctx.remoteIp;
378
+ wtx.userid = ctx.userid;
379
+
380
+ if (ctx.error.isZero() === false) {
381
+ wtx.error = ctx.error;
382
+ wtx.errorLevel = EventLevel.WARNING;
383
+ }
384
+ wtx.userAgent = ctx.userAgent;
385
+ wtx.referer = ctx.referer;
386
+
387
+ wtx.httpcCount = ctx.httpc_count;
388
+ wtx.httpcTime = ctx.httpc_time;
389
+ wtx.status = ctx.status;
390
+
391
+ wtx.http_method=TxRecord.HTTP_METHOD[ctx.http_method] || TxRecord.WEB_GET;
392
+ wtx.http_host = ctx.http_host;
393
+ wtx.mtid=ctx.mtid;
394
+ wtx.mdepth=ctx.mdepth;
395
+ wtx.mcaller=ctx.mcaller_txid;
396
+ wtx.mcaller_pcode = ctx.mcaller_pcode;
397
+ wtx.mcaller_okind = ctx.mcaller_okind;
398
+ wtx.mcaller_oid = ctx.mcaller_oid;
399
+
400
+ MeterService.add(wtx.service, wtx.elapsed,
401
+ wtx.errorLevel, ctx.mcaller_pcode, ctx.mcaller_okind, ctx.mcaller_oid);
402
+
403
+ profile.oid = SecurityMaster.OID;
404
+ profile.service = wtx;
405
+ if(Boolean(conf.reqlog_enabled) == true) {
406
+ ctx.endTime = wtx.endTime;
407
+ ctx.elapsed = wtx.elapsed;
408
+ RequestLog.setRecord(ctx);
409
+ }
410
+ //duplicated executed... so end() first
411
+ TraceContextManager.end(ctx._id);
412
+ setTimeout(function () {
413
+ DataProfileAgent.sendProfile(ctx, profile, false);
414
+ TraceContextManager.end(ctx._id);
415
+ ctx = null;
416
+ }, 100);
417
+
418
+ } catch (e) {
419
+ Logger.printError('WHATAP-607', 'End transaction error..', e, false);
420
+ TraceContextManager.end(ctx._id);
421
+ ctx = null;
422
+ }
423
+
424
+ };
425
+
426
+ var transfer_poid;
427
+ function transferPOID(ctx) {
428
+ if (transfer_poid)
429
+ return transfer_poid;
430
+ transfer_poid=Hexa32.toString32(SecurityMaster.PCODE)+','
431
+ +Hexa32.toString32(SecurityMaster.OKIND)+','+Hexa32.toString32(SecurityMaster.OID);
432
+ return transfer_poid;
433
+ }
434
+
435
+ function transferMTID_CALLERTX(ctx) {
436
+ if (ctx.transfer_id)
437
+ return ctx.transfer_id;
438
+ var x = Hexa32.toString32(ctx.mtid) + ',' + (ctx.mdepth + 1) + ',' + Hexa32.toString32(ctx.txid);
439
+ ctx.transfer_id = x;
440
+ return ctx.transfer_id;
441
+ }
442
+ function transferSPEC_URL(ctx) {
443
+ if (ctx.transfer_info)
444
+ return ctx.transfer_info;
445
+ var x = conf.mtrace_spec + ',' + ctx.service_hash;
446
+ ctx.transfer_info = x;
447
+ return ctx.transfer_info;
448
+ }
449
+ var check_seq = 1;
450
+ function interTxTraceAutoOn(ctx) {
451
+ if (conf.mtrace_enabled ==false || ctx.httpc_checked || ctx.mtid.isZero()===false)
452
+ return;
453
+ ctx.httpc_checked = true;
454
+ if(conf.mtrace_rate>=100){
455
+ ctx.mtid = KeyGen.next();
456
+ return;
457
+ }
458
+ check_seq++;
459
+ switch (Math.floor(conf.mtrace_rate / 10)) {
460
+ case 10:
461
+ ctx.mtid = KeyGen.next();
462
+ break;
463
+ case 9:
464
+ if (check_seq % 10 !== 0)
465
+ ctx.mtid = KeyGen.next();
466
+ break;
467
+ case 8:
468
+ if (check_seq % 5 !== 0)
469
+ ctx.mtid = KeyGen.next();
470
+ break;
471
+ case 7:
472
+ if (check_seq % 4 !== 0)
473
+ ctx.mtid = KeyGen.next();
474
+ break;
475
+ case 6:
476
+ if (check_seq % 3 !== 0)
477
+ ctx.mtid = KeyGen.next();
478
+ break;
479
+ case 5:
480
+ if (check_seq % 2 === 0)
481
+ ctx.mtid = KeyGen.next();
482
+ break;
483
+ case 4:
484
+ if (check_seq % 3 === 0 || check_seq % 5 === 0)
485
+ ctx.mtid = KeyGen.next();
486
+ break;
487
+ case 3:
488
+ if (check_seq % 4 === 0 || check_seq % 5 === 0)
489
+ ctx.mtid = KeyGen.next();
490
+ break;
491
+ case 2:
492
+ if (check_seq % 5 === 0)
493
+ ctx.mtid = KeyGen.next();
494
+ break;
495
+ case 1:
496
+ if (check_seq % 10 === 0)
497
+ ctx.mtid = KeyGen.next();
498
+ break;
499
+ }
500
+ }
501
+ HttpObserver.prototype.inject = function( mod, moduleName ) {
502
+ var self = this;
503
+ var aop = self.agent.aop;
504
+
505
+ if(mod.__whatap_observe__) { return; }
506
+ mod.__whatap_observe__ = true;
507
+ Logger.initPrint("HttpObserver");
508
+ if( conf.profile_enabled === false ) { return; }
509
+
510
+ aop.after(mod, 'createServer', function (obj, args, ret) {
511
+ aop.before(ret, 'listen', function (obj, args) {
512
+ conf['whatap.port'] = (args[0] || 80);
513
+ });
514
+ });
515
+
516
+ aop.before(mod.Server.prototype, ['on', 'addListener'], function (obj, args) {
517
+ if(args[0] !== 'request') {return;}
518
+
519
+ args[args.length-1] = self.__createTransactionObserver(args[args.length-1],
520
+ moduleName === 'https', obj);
521
+ });
522
+
523
+ if( conf.httpc_enabled === false ) { return; }
524
+
525
+ aop.both(mod, 'request',
526
+ function (obj, args, lctx) {
527
+ var ctx = lctx.context;
528
+ if (ctx == null || (args[0].host == null && args[0].hostname == null) ) { return; } // for axios
529
+
530
+ var isHttpsRepeat = false;
531
+ if(moduleName === 'https') {
532
+ args[0].__isHttps = true;
533
+ }
534
+
535
+ if(moduleName === 'http' && args[0].__isHttps) {
536
+ isHttpsRepeat = true;
537
+ }
538
+
539
+ if(!isHttpsRepeat) {
540
+ try {
541
+ if(args[0].method === 'OPTION') {
542
+ return;
543
+ }
544
+
545
+ var dataConsumption = false;
546
+
547
+ if(args.length > 0) {
548
+ var info = args[0];
549
+
550
+ interTxTraceAutoOn(ctx);
551
+
552
+ if(conf.mtrace_enabled){
553
+ if(info.headers){
554
+ info.headers['x-wtap-po']=transferPOID(ctx);
555
+ }else{
556
+ info.headers={
557
+ 'x-wtap-po': transferPOID(ctx)
558
+ };
559
+ }
560
+ if(conf.stat_mtrace_enabled){
561
+ info.headers[conf._trace_mtrace_spec_key1]=transferSPEC_URL(ctx);
562
+ }
563
+ if(conf.mtid_mtrace_enabled && ctx.mtid.isZero()===false){
564
+ info.headers[conf._trace_mtrace_caller_key]=transferMTID_CALLERTX(ctx);
565
+ }
566
+
567
+ }
568
+ ctx.httpc_url = info.path || '/';
569
+ ctx.httpc_host = info.host || info.hostname || '';
570
+ ctx.httpc_port = info.port || -1;
571
+ }
572
+ ctx.footprint('Http Call Start');
573
+
574
+ if (ctx.httpc_port < 0) { ctx.httpc_port = 80 };
575
+
576
+ } catch(e) {
577
+ return Logger.printError('WHATAP-852', 'Http Repeat ', e, true);
578
+ }
579
+
580
+ aop.functionHook(args, -1, function(obj, args) {
581
+ if(TraceContextManager.resume(ctx._id) == null) { return; }
582
+
583
+ var res = args[0];
584
+ aop.before(res, ['on', 'addListener'], function(obj, args) {
585
+ if(!dataConsumption && args[0] === 'data') {
586
+ dataConsumption = true;
587
+ }
588
+ });
589
+ aop.before(res, 'pipe', function() {
590
+ dataConsumption = true;
591
+ });
592
+ aop.before(res, 'resume', function() {
593
+ dataConsumption = true;
594
+ });
595
+
596
+ if (dataConsumption) { return; }
597
+ // endHttpc(ctx, step);
598
+ });
599
+ }
600
+ },
601
+ function (obj, args, ret, lctx) {
602
+ if(moduleName === 'http' && args[0].__isHttps) {
603
+ return;
604
+ }
605
+
606
+ var ctx = lctx.context;
607
+ if (ctx == null || ( args[0].host == null && args[0].hostname == null)) { return; }
608
+
609
+ ret.on('response', function(response){
610
+ var statusCode = response.statusCode;
611
+ if(statusCode >= 400){
612
+ if (step.error.isZero()) {
613
+ step.error = StatError.addError(statusCode, response.statusMessage , ctx.service_hash,
614
+ TextTypes.HTTPC_URL, step.url);
615
+ if (ctx.error.isZero()) {
616
+ ctx.error = step.error;
617
+ ctx.statusCode = statusCode;
618
+ ctx.statusMessage = response.statusMessage;
619
+ }
620
+ }
621
+ }
622
+ })
623
+ ret.on('error', function(err) {
624
+ if (TraceContextManager.resume(ctx._id) == null) { return; }
625
+
626
+ if (step.error.isZero()) {
627
+ step.error = StatError.addError(err.code, err.message, ctx.service_hash,
628
+ TextTypes.HTTPC_URL, step.url);
629
+ if (ctx.error.isZero()) {
630
+ ctx.error = step.error;
631
+ ctx.statusCode = err.code;
632
+ ctx.statusMessage = err.message;
633
+ }
634
+ }
635
+
636
+ endHttpc(ctx, step);
637
+ });
638
+
639
+ var step = new HttpStepX();
640
+ step.start_time = ctx.getElapsedTime();
641
+ step.url = HashUtil.hashFromString(ctx.httpc_url);
642
+ DataTextAgent.HTTPC_URL.add(step.url, ctx.httpc_url);
643
+ step.host = HashUtil.hashFromString(ctx.httpc_host);
644
+ DataTextAgent.HTTPC_HOST.add(step.host, ctx.httpc_host);
645
+ step.port = ctx.httpc_port;
646
+
647
+ aop.before(ret, 'write', function (obj, args) {
648
+ if(conf.profile_httpc_parameter_enabled == true) {
649
+ if(args.length == 1) {
650
+ var step = new MessageStep();
651
+ step.hash = HashUtil.hashFromString("HTTPC-REQUEST-BODY");
652
+ step.start_time = ctx.getElapsedTime();
653
+ step.desc = args[0];
654
+ DataTextAgent.MESSAGE.add(step.hash, "HTTPC-REQUEST-BODY");
655
+ ctx.profile.push(step);
656
+ }
657
+ }
658
+ });
659
+
660
+ aop.before(ret, 'end', function (obj, args) {
661
+ ctx.active_httpc_hash = step.url;
662
+ ctx.profile.push(step);
663
+ });
664
+
665
+ ret.on('socket', function(socket) {
666
+ // socket reuse chk
667
+ if(conf.setSocketChk(socket) == false) {
668
+ aop.before(socket, 'end', function (obj, args) {
669
+ if(ctx == null) { return; }
670
+ TraceContextManager.resume(ctx._id);
671
+ endHttpc(ctx, step);
672
+ });
673
+
674
+ socket.on('timeout', function () {
675
+ if (TraceContextManager.resume(ctx._id) == null) { return; }
676
+ if (step.error.isZero()) {
677
+ var msgObj = { 'class': 'Timeout', 'msg': 'Timeout' };
678
+ step.error = StatError.addError('Timeout','Timeout', ctx.service_hash);
679
+ if (ctx.error.isZero()) {
680
+ ctx.error = step.error;
681
+ ctx.statusCode = 'Timeout';
682
+ ctx.statusMessage = 'Timeout';
683
+ }
684
+ }
685
+ endHttpc(ctx, step);
686
+ });
687
+ }
688
+ });
689
+ });
690
+
691
+ function endHttpc(ctx, step) {
692
+ if(ctx == null || step == null) { return; }
693
+
694
+ step.elapsed = ctx.getElapsedTime() - step.start_time;
695
+
696
+ ctx.httpc_count++;
697
+ ctx.httpc_time += step.elapsed;
698
+
699
+ MeterHttpC.add(step.host, step.elapsed, step.error.isZero()===false);
700
+ StatHttpc.addHttpcTime(ctx.service_hash, step.url, step.host, step.port, step.elapsed, step.error.isZero()===false);
701
+ ctx.footprint('Http Call Done');
702
+ }
703
+ };
704
+
705
705
  exports.HttpObserver = HttpObserver;