whatap 0.4.92 → 0.4.94

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,7 @@ Whatap allows for application performance monitoring.
7
7
 
8
8
  Works on Linux(32bit, 64bit), MacOSx(32bit, 64bit), Windows(32bit, 64bit).
9
9
 
10
- *Node.js 지원 버젼: 4.3.2 이상
10
+ *Node.js 지원 버젼: 16.4.0 이상
11
11
 
12
12
  ![step01](http://apm.whatap.io/images/icon_step01.png)
13
13
 
@@ -15,7 +15,7 @@ Works on Linux(32bit, 64bit), MacOSx(32bit, 64bit), Windows(32bit, 64bit).
15
15
 
16
16
  npm 에서 다음과 같은 명령어를 통해 whatap을 설치 할 수 있습니다.
17
17
 
18
- $ npm install --save whatap
18
+ $ npm install whatap
19
19
 
20
20
 
21
21
 
@@ -37,11 +37,22 @@ whatap.conf 파일은 다음과 같은 내용을 포함합니다.
37
37
 
38
38
  #### Usage
39
39
 
40
- 루트 디렉토리의 Node.js Application에 다음과 같은 코드를 추가 해 주세요.
40
+ 루트 디렉토리에 위치한 Node.js 애플리케이션에서 Whatap 모니터링 기능을 활성화하려면,
41
+ 애플리케이션의 진입점 파일에 Whatap 에이전트를 초기화하는 코드를 추가해야 합니다.
41
42
 
43
+ Node.js 애플리케이션에 Whatap 모니터링을 적용하는 방법은 모듈 시스템의 종류(CommonJS 또는 ECMAScript Modules, ESM)에 따라 약간 다릅니다. 아래에서는 두 가지 모듈 시스템에 대해 Whatap 에이전트를 초기화하고 사용하는 방법을 설명합니다.
44
+
45
+
46
+ #### CommonJS 모듈 시스템 사용 시
47
+ Whatap 에이전트를 CommonJS 방식으로 가져오고 초기화하려면, 다음 코드를 애플리케이션의 진입점 파일에 추가하세요:
48
+
42
49
  var WhatapAgent = require('whatap').NodeAgent;
43
50
 
51
+ #### ECMAScript 모듈(ESM) 시스템 사용 시
52
+ ESM 방식으로 Whatap 에이전트를 가져오고 사용하려면, 다음과 같이 코드를 작성하세요:
44
53
 
54
+ import WhatapAgent from 'whatap';
55
+ WhatapAgent.NodeAgent;
45
56
 
46
57
  ![step04](http://apm.whatap.io/images/icon_step04.png)
47
58
 
@@ -36,7 +36,7 @@ var ConfigDefault = {
36
36
  "web_static_content_extensions": str("web_static_content_extensions" , "js, htm, html, gif, png, jpg, css, txt, ico"),
37
37
  "trace_auto_service_enabled": false,
38
38
  "trace_auto_service_backstack_enabled": true,
39
- "trace_background_socket_enabled": true,
39
+ "trace_background_socket_enabled": bool('trace_background_socket_enabled', true),
40
40
  "trace_node_schedule_enabled": bool('trace_node_schedule_enabled',false),
41
41
  "trace_active_callstack_depth": 40,
42
42
  "trace_activeserivce_yellow_time": 3000,
@@ -57,7 +57,9 @@ var ConfigDefault = {
57
57
 
58
58
  "profile_http_querystring_enabled": bool('profile_http_querystring_enabled',false),
59
59
  "profile_http_header_enabled": bool('profile_http_header_enabled',false),
60
+ "profile_http_header_ignore_keys": str('profile_http_header_ignore_keys','Cookie,cookie,accept,user-agent,referer'),
60
61
  "profile_http_parameter_enabled": bool('profile_http_parameter_enabled',false),
62
+ "profile_http_parameter_keys": str('profile_http_parameter_keys',''),
61
63
  "profile_httpc_parameter_enabled": bool('profile_httpc_parameter_enabled',false),
62
64
  "profile_http_parameter_url_prefix": "/",
63
65
  "profile_http_header_url_prefix": "/",
@@ -85,6 +87,7 @@ var ConfigDefault = {
85
87
  "trace_user_agent_header_key": str('trace_user_agent_header_key',''),
86
88
  "trace_referer_header_key": str('trace_referer_header_key',''),
87
89
  "profile_sql_param_enabled": bool('profile_sql_param_enabled',false),
90
+ "profile_sql_resource_enabled": bool('profile_sql_resource_enabled',false),
88
91
  "error_snap_enabled" : true,
89
92
  "trace_user_enabled": bool('trace_user_enabled',true),
90
93
  "trace_user_using_ip": bool('trace_user_using_ip',true),
@@ -96,6 +99,9 @@ var ConfigDefault = {
96
99
  "trace_sql_error_depth": num('trace_sql_error_depth', 50),
97
100
  "transaction_status_error_enable": bool("transaction_status_error_enable", true),
98
101
 
102
+ "trace_sampling_enabled": bool("trace_sampling_enabled", false),
103
+ "trace_sampling_tps": bool("trace_sampling_tps", 1000),
104
+
99
105
  "profile_error_sql_time_max": num("profile_error_sql_time_max", 30000),
100
106
  "profile_error_step_enabled": bool('profile_error_step_enabled', true),
101
107
  "hook_direct_patch_classes": "",
@@ -139,6 +145,7 @@ var ConfigDefault = {
139
145
  "trace_sql_normalize_enabled" : true,
140
146
  "httpc_not_found_ignore": bool('httpc_not_found_ignore', false),
141
147
  "httpc_not_found_ignore_time": num('httpc_not_found_ignore', 300000),
148
+ "ignore_sql_error_code_set": str('ignore_sql_error_code_set', ''),
142
149
 
143
150
  //2017.05.02 AUTO ONAME
144
151
  "auto_oname_enabled" : bool('auto_oname_enabled',false),
@@ -32,11 +32,14 @@ var TraceContextManager = require('../trace/trace-context-manager'),
32
32
  ResourceProfile = require('../util/resourceprofile'),
33
33
  TextTypes = require('../lang/text-types'),
34
34
  MessageStep = require('../step/message-step'),
35
+ SecureMsgStep = require('../step/securemsg-step'),
35
36
  PluginLoaderManager = require('../plugin/plugin-loadermanager'),
36
37
  Long = require('long'),
37
38
  KeyGen = require('../util/keygen'),
38
39
  Logger = require('../logger'),
39
40
  IntKeyLinkedMap = require("../util/intkey-linkedmap");
41
+ const ParamSecurity = require("../util/paramsecurity");
42
+ const {Buffer} = require("buffer");
40
43
 
41
44
  var _exts=new Set([".css",".js",".png", ".htm", ".html", ".gif", ".jpg", ".css", ".txt", ".ico"]);
42
45
 
@@ -53,6 +56,9 @@ var httpc_status_ignore_set = conf.getProperty('httpc_status_ignore_set', '');
53
56
  var profile_error_step_enabled = conf.getProperty('profile_error_step_enabled', '');
54
57
  var httpc_not_found_ignore = conf.getProperty('httpc_not_found_ignore', false);
55
58
  var httpc_not_found_ignore_time = conf.getProperty('httpc_not_found_ignore_time', 300000);
59
+ var profile_http_header_ignore_keys = conf.getProperty('profile_http_header_ignore_keys', 'Cookie,cookie,accept,user-agent,referer');
60
+ var profile_http_parameter_enabled = conf.getProperty('profile_http_parameter_enabled', true);
61
+ var profile_http_parameter_keys = conf.getProperty('profile_http_parameter_keys', '');
56
62
  conf.on('trace_http_client_ip_header_key', function(newProperty) {
57
63
  configIpHeaderKey = newProperty;
58
64
  });
@@ -101,6 +107,15 @@ conf.on('httpc_not_found_ignore', function (newProps) {
101
107
  conf.on('httpc_not_found_ignore_time', function (newProps) {
102
108
  httpc_not_found_ignore_time = newProps;
103
109
  })
110
+ conf.on('profile_http_header_ignore_keys', function (newProps) {
111
+ profile_http_header_ignore_keys = newProps;
112
+ })
113
+ conf.on('profile_http_parameter_enabled', function (newProps) {
114
+ profile_http_parameter_enabled = newProps;
115
+ })
116
+ conf.on('profile_http_parameter_keys', function (newProps) {
117
+ profile_http_parameter_keys = newProps;
118
+ })
104
119
  var staticConents = function (newProps) {
105
120
  var x=new Set();
106
121
  var words = !newProps?[]:newProps.split(',');
@@ -121,7 +136,7 @@ conf.on('web_static_content_extensions', staticConents);
121
136
  staticConents(conf["web_static_content_extensions"]);
122
137
 
123
138
  var httpc_not_found_ignore_map = null;
124
- var httpc_not_found_ignore_url = [];
139
+ var httpc_not_found_ignore_url = new Set();
125
140
 
126
141
  var HttpObserver = function(agent){
127
142
  this.agent = agent;
@@ -156,7 +171,7 @@ HttpObserver.prototype.__createTransactionObserver = function(callback, isHttps,
156
171
  if(ctx == null) { return; }
157
172
  PluginLoaderManager.do('httpserviceend', ctx, req, res);
158
173
 
159
- var not_found_ignore = httpc_not_found_ignore_url.includes(req.url);
174
+ var not_found_ignore = httpc_not_found_ignore_url.has(req.url);
160
175
  if (httpc_not_found_ignore && !not_found_ignore && obj.statusCode === 404) {
161
176
  const url_hash = HashUtil.hashFromString(req.url);
162
177
  const currentTime = new Date().getTime();
@@ -324,10 +339,28 @@ function initCtx(req, res) {
324
339
  var step = new MessageStep();
325
340
  step.hash = HashUtil.hashFromString("HTTP-HEADERS");
326
341
  step.start_time = ctx.getElapsedTime();
327
- if(req.headers && Object.keys(req.headers).length > 0)
328
- step.desc = Object.keys(req.headers).map(key => `${key}=${req.headers[key]}`).join('\n');
329
- DataTextAgent.MESSAGE.add(step.hash, "HTTP-HEADERS");
330
- ctx.profile.push(step);
342
+
343
+ var header_ignore_key_set = new Set();
344
+ if(profile_http_header_ignore_keys) {
345
+ header_ignore_key_set = new Set(profile_http_header_ignore_keys.split(','));
346
+ }
347
+
348
+ try{
349
+ step.desc = Object.keys(req.headers).map(function (key) {
350
+ if (!header_ignore_key_set.has(key)) {
351
+ return `${key}=${req.headers[key]}`;
352
+ }
353
+ }).filter(element => {
354
+ if (element) return element
355
+ }).join('\n');
356
+
357
+ DataTextAgent.MESSAGE.add(step.hash, "HTTP-HEADERS");
358
+ ctx.profile.push(step);
359
+ }catch (e) {
360
+ step = null;
361
+ header_ignore_key_set = null;
362
+ Logger.printError('WHATAP-614', 'Header parsing error', e, false);
363
+ }
331
364
  }
332
365
  /************************************/
333
366
  /* Multi Server Transaction Trace */
@@ -391,21 +424,33 @@ HttpObserver.prototype.__endTransaction = function(error, ctx, req, res) {
391
424
  }
392
425
  }
393
426
 
394
- if(param_enabled) {
395
- var query = JSON.stringify(req.query || '');
396
- var body = JSON.stringify(req.body || '');
397
- //var param = JSON.stringify(req.params || '');
398
- //console.log(query.length + " // " + body.length);
399
- var step = new MessageStep();
400
- step.hash = HashUtil.hashFromString("HTTP-PARAMETERS");
401
- step.start_time = ctx.getElapsedTime();
402
- if(query.length > 2) {
403
- step.desc = '[GET] ' + query;
404
- } else {
405
- step.desc = '[POST] ' + body;
427
+ if (param_enabled && req.query && Object.keys(req.query).length > 0) {
428
+ const query = req.query;
429
+ let secureMsgStep = new SecureMsgStep(ctx.getElapsedTime());
430
+ secureMsgStep.hash = HashUtil.hashFromString("HTTP-PARAMETERS");
431
+
432
+ const profileHttpParameterKeysSet = profile_http_parameter_keys ? new Set(profile_http_parameter_keys.split(',')) : null;
433
+
434
+ try {
435
+ const desc = Object.entries(query)
436
+ .filter(([key]) => !profileHttpParameterKeysSet || profileHttpParameterKeysSet.has(key))
437
+ .map(([key, value]) => `${key}=${value}`)
438
+ .join('\n');
439
+
440
+ if (desc) {
441
+ const crc = { value: 0 };
442
+ secureMsgStep.value = toParamBytes(desc, crc);
443
+ secureMsgStep.crc = crc.value;
444
+
445
+ DataTextAgent.MESSAGE.add(secureMsgStep.hash, "HTTP-PARAMETERS");
446
+ ctx.profile.push(secureMsgStep);
447
+ } else {
448
+ secureMsgStep = null;
449
+ }
450
+ } catch (e) {
451
+ secureMsgStep = null;
452
+ Logger.printError('WHATAP-613', 'Parameter parsing error', e, false);
406
453
  }
407
- DataTextAgent.MESSAGE.add(step.hash, "HTTP-PARAMETERS");
408
- ctx.profile.push(step);
409
454
  }
410
455
 
411
456
  if(profile_error_step_enabled && ctx.statusMessage){
@@ -823,7 +868,7 @@ function updateNotFoundIgnoreMap(url, url_hash, currentTime) {
823
868
  }
824
869
 
825
870
  if (ignore_value.count >= 50) {
826
- httpc_not_found_ignore_url.push(url);
871
+ httpc_not_found_ignore_url.add(url);
827
872
  httpc_not_found_ignore_map.remove(url_hash);
828
873
  Logger.print('WHATAP-610', "The ignore option for URL " + url + " is applied.", false);
829
874
  }
@@ -839,4 +884,15 @@ function shouldEndCurrentTransaction(not_found_ignore, ctx, res, requestPath) {
839
884
  return !is_ignore;
840
885
  }
841
886
 
887
+ var toParamBytes = function (p, crc) {
888
+ if (p == null || p.length === 0) {
889
+ return null;
890
+ }
891
+ try {
892
+ return ParamSecurity.encrypt(Buffer.from(p, 'utf8'), crc);
893
+ } catch (e) {
894
+ return null;
895
+ }
896
+ };
897
+
842
898
  exports.HttpObserver = HttpObserver;
@@ -24,6 +24,7 @@ var TraceContextManager = require('../trace/trace-context-manager'),
24
24
  DateUtil = require('../util/dateutil'),
25
25
  Buffer = require('buffer').Buffer,
26
26
  MessageStep = require("../step/message-step");
27
+ // const ResourceProfile = require("../util/resourceprofile");
27
28
 
28
29
  var MariaObserver = function (agent) {
29
30
  this.agent = agent;
@@ -145,6 +146,11 @@ var queryHook = function (dbc, agent) {
145
146
  sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
146
147
  ctx.sql_time += sql_step.elapsed;
147
148
 
149
+ // if(conf.getProperty('profile_sql_resource_enabled', false)){
150
+ // sql_step.start_cpu = ResourceProfile.getCPUTime();
151
+ // sql_step.start_mem = ResourceProfile.getUsedHeapSize();
152
+ // }
153
+
148
154
  ctx.footprint('Maria Query Done');
149
155
 
150
156
  MeterSql.add(dbc_hash, sql_step.elapsed, false);
@@ -136,15 +136,21 @@ MongooseObserver.prototype.inject = function (mod, modName) {
136
136
 
137
137
  const mongooseCollection = _ret.mongooseCollection;
138
138
  try {
139
- var sql = mongooseCollection.modelName + ' ' + _ret.op ;//+ ': ' + JSON.stringify(Object.keys(args[0]));
140
- if(_args[0]) { sql += ' field=' + JSON.stringify(Object.keys(_args[0])); }
141
- if(_args[1]) { sql += ' value=' + JSON.stringify(Object.keys(_args[1])); }
142
-
143
- sql_step.hash = HashUtil.hashFromString(sql);
144
- sql_step.start_time = ctx.getElapsedTime();
145
- sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
146
- DataTextAgent.SQL.add(sql_step.hash, sql);
147
- ctx.profile.push(sql_step);
139
+ if(mongooseCollection && mongooseCollection.modelName){
140
+ var sql = mongooseCollection.modelName + ' ' + _ret.op;//+ ': ' + JSON.stringify(Object.keys(args[0]));
141
+ if (_args[0]) {
142
+ sql += ' field=' + JSON.stringify(Object.keys(_args[0]));
143
+ }
144
+ if (_args[1]) {
145
+ sql += ' value=' + JSON.stringify(Object.keys(_args[1]));
146
+ }
147
+
148
+ sql_step.hash = HashUtil.hashFromString(sql);
149
+ sql_step.start_time = ctx.getElapsedTime();
150
+ sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
151
+ DataTextAgent.SQL.add(sql_step.hash, sql);
152
+ ctx.profile.push(sql_step);
153
+ }
148
154
  } catch(e) {
149
155
  Logger.printError("WHATAP-611", "Mongodb query error", e, false);
150
156
  sql_step = null;
@@ -22,6 +22,7 @@ var TraceContextManager = require('../trace/trace-context-manager'),
22
22
  Logger = require('../logger');
23
23
  const DateUtil = require('../util/dateutil');
24
24
  const MessageStep = require("../step/message-step");
25
+ // const ResourceProfile = require("../util/resourceprofile");
25
26
 
26
27
  var MssqlObserver = function (agent) {
27
28
  this.agent = agent;
@@ -126,6 +127,11 @@ MssqlObserver.prototype.inject = function (mod, modName) {
126
127
  StatSql.addSqlTime(ctx.service_hash, sql_step.dbc,
127
128
  sql_step.hash, sql_step.elapsed, args[0] != null, 0);
128
129
 
130
+ // if(conf.getProperty('profile_sql_resource_enabled', false)){
131
+ // sql_step.start_cpu = ResourceProfile.getCPUTime();
132
+ // sql_step.start_mem = ResourceProfile.getUsedHeapSize();
133
+ // }
134
+
129
135
  if(psql && psql.type == 'S') {
130
136
  var result_step = new ResultSetStep();
131
137
  result_step.dbc = sql_step.dbc;
@@ -24,6 +24,7 @@ var TraceContextManager = require('../trace/trace-context-manager'),
24
24
  DateUtil = require('../util/dateutil'),
25
25
  Buffer = require('buffer').Buffer,
26
26
  MessageStep = require("../step/message-step");
27
+ // const ResourceProfile = require('../util/resourceprofile');
27
28
 
28
29
  var MysqlObserver = function (agent) {
29
30
  this.agent = agent;
@@ -167,6 +168,11 @@ var queryHook = function (dbc, agent) {
167
168
  sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
168
169
  ctx.sql_time += sql_step.elapsed;
169
170
 
171
+ // if(conf.getProperty('profile_sql_resource_enabled', false)){
172
+ // sql_step.start_cpu = ResourceProfile.getCPUTime();
173
+ // sql_step.start_mem = ResourceProfile.getUsedHeapSize();
174
+ // }
175
+
170
176
  ctx.footprint('MySql Query Done');
171
177
 
172
178
  MeterSql.add(dbc_hash, sql_step.elapsed, false);
@@ -360,7 +366,7 @@ MysqlObserver.prototype.inject = function (mod, moduleName) {
360
366
 
361
367
  var dbc_pool_hash = 0;
362
368
  aop.after(mod, ['createPool', 'createPoolCluster'], function (obj, args, ret) {
363
- if (dbc_pool_hash == 0) {
369
+ if (dbc_pool_hash == 0 && dbc === 'mysql://') {
364
370
  if (args.length > 0) {
365
371
  var info = args[0];
366
372
  //Open [DatabaseName] connection 메세지 보여줄때 필요함.
@@ -5,25 +5,26 @@
5
5
  */
6
6
 
7
7
  var TraceContextManager = require('../trace/trace-context-manager'),
8
- SocketStep = require('../step/socket-step'),
9
- conf = require('../conf/configure'),
10
- IPUtil = require('../util/iputil'),
11
- Logger = require('../logger');
8
+ SocketStep = require('../step/socket-step'),
9
+ conf = require('../conf/configure'),
10
+ IPUtil = require('../util/iputil'),
11
+ Logger = require('../logger');
12
12
 
13
- var NetObserver = function (agent) {
13
+ var trace_background_socket_enabled = conf.getProperty('trace_background_socket_enabled', false);
14
+ conf.on('trace_background_socket_enabled', function (newProps) {
15
+ trace_background_socket_enabled = newProps;
16
+ })
17
+
18
+ var NetObserver = function(agent){
14
19
  this.agent = agent;
15
- this.packages = ['net', 'dgram'];
20
+ this.packages = ['net'];
16
21
  };
17
22
 
18
23
  NetObserver.prototype.inject = function (mod, moduleName) {
19
- if (mod.__whatap_observe__) {
20
- return;
21
- }
24
+ if(mod.__whatap_observe__) { return; }
22
25
  mod.__whatap_observe__ = true;
23
26
  Logger.initPrint("NetObserver");
24
- if (conf.trace_background_socket_enabled === false) {
25
- return;
26
- }
27
+ if ( !trace_background_socket_enabled ) { return; }
27
28
 
28
29
  var self = this;
29
30
  var aop = self.agent.aop;
@@ -31,80 +32,46 @@ NetObserver.prototype.inject = function (mod, moduleName) {
31
32
  aop.both(mod.Socket.prototype, ['connect'],
32
33
  function (obj, args, lctx) {
33
34
  var ctx = lctx.context;
34
- if (ctx == null) {
35
+ if(!ctx || !trace_background_socket_enabled){
35
36
  return;
36
37
  }
37
- var host, port;
38
- if (args.length > 1) {
39
- host = args[1];
40
- port = args[0];
38
+ var info, host, port;
39
+ if(args.length > 0){
40
+ info = args[0];
41
+ host = info.host;
42
+ port = info.port;
41
43
  }
42
- if (port == undefined) {
44
+ if(port == undefined){
43
45
  lctx.step = null;
44
46
  return;
45
47
  }
46
- ctx.socket_connecting = true;
48
+ ctx.socket_connecting=true;
47
49
 
48
- ctx.footprint('Socket Connecting: ' + host + ':' + port);
50
+ ctx.footprint('Socket Connecting: ' + host+':'+port);
49
51
 
50
52
  var step = new SocketStep();
51
53
  step.start_time = ctx.getElapsedTime();
52
54
  step.ipaddr = Buffer.from(IPUtil.stringToBytes(host));
53
55
  step.port = port;
56
+ // obj.on('lookup', function(err, ip, addressType){
57
+ // if(step != null) {
58
+ // step.ipaddr = new Buffer(IPUtil.stringToBytes(ip));
59
+ // }
60
+ // });
54
61
  ctx.profile.push(step);
55
62
  lctx.step = step;
56
63
  },
57
64
  function (obj, args, ret, lctx) {
58
65
  var ctx = lctx.context;
59
66
  var step = lctx.step;
60
- if (ctx == null || step == null) {
67
+ if(!ctx || !step || !trace_background_socket_enabled){
61
68
  return;
62
69
  }
63
- ctx.socket_connecting = false;
70
+ ctx.socket_connecting=false;
64
71
  step.elapsed = ctx.getElapsedTime() - step.start_time;
65
72
  ctx.footprint('Socket Connecting Done');
66
73
  }
67
74
  );
68
-
69
- aop.both(mod, ['createSocket'],
70
- function (obj, args, lctx) {
71
- var ctx = lctx.context;
72
- if (ctx == null) {
73
- return;
74
- }
75
- },
76
- function (obj, args, ret, lctx) {
77
- var ctx = lctx.context;
78
- if (ctx == null) {
79
- return;
80
- }
81
- aop.after(ret, 'send', function (_obj, _args, _ret, _lctx) {
82
- var host, port;
83
- if (_args.length > 2) {
84
- host = _args[2];
85
- port = _args[1];
86
- }
87
- if (port == undefined) {
88
- lctx.step = null;
89
- return;
90
- }
91
- ctx.socket_connecting = true;
92
-
93
- ctx.footprint('Socket Connecting: ' + host + ':' + port);
94
-
95
- var step = new SocketStep();
96
- step.start_time = ctx.getElapsedTime();
97
- step.ipaddr = Buffer.from(IPUtil.stringToBytes(host));
98
- step.port = port;
99
-
100
- ctx.socket_connecting = false;
101
- step.elapsed = ctx.getElapsedTime() - step.start_time;
102
- ctx.profile.push(step);
103
-
104
- ctx.footprint('Socket Connecting Done');
105
- })
106
- }
107
- );
108
75
  };
109
76
 
110
77
  exports.NetObserver = NetObserver;
@@ -24,6 +24,7 @@ var TraceContextManager = require('../trace/trace-context-manager'),
24
24
  Buffer = require('buffer').Buffer,
25
25
  DateUtil = require('../util/dateutil'),
26
26
  MessageStep = require("../step/message-step");
27
+ // const ResourceProfile = require("../util/resourceprofile");
27
28
 
28
29
  var PgSqlObserver = function (agent) {
29
30
  this.agent = agent;
@@ -134,6 +135,12 @@ var queryHook = function (dbc_local, agent) {
134
135
 
135
136
  sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
136
137
  ctx.sql_time += sql_step.elapsed;
138
+
139
+ // if(conf.getProperty('profile_sql_resource_enabled', false)){
140
+ // sql_step.start_cpu = ResourceProfile.getCPUTime();
141
+ // sql_step.start_mem = ResourceProfile.getUsedHeapSize();
142
+ // }
143
+
137
144
  ctx.footprint('PgSql Query Done');
138
145
 
139
146
  MeterSql.add(dbc_hash, sql_step.elapsed, false);
@@ -4,51 +4,179 @@
4
4
  * can be found in the LICENSE file.
5
5
  */
6
6
 
7
- var MeterSocketio = require('../counter/meter/meter-socket.io');
7
+ var MeterSocketio = require('../counter/meter/meter-socket.io'),
8
+ TraceContextManager = require('../trace/trace-context-manager'),
9
+ SocketStep = require('../step/socket-step'),
10
+ conf = require('../conf/configure'),
11
+ IPUtil = require('../util/iputil'),
12
+ Logger = require('../logger');
13
+ const {Detector: URLPatternDetector} = require("whatap/lib/trace/serviceurl-pattern-detector");
14
+ const HashUtil = require("whatap/lib/util/hashutil");
15
+ const DataTextAgent = require("whatap/lib/data/datatext-agent");
16
+ const ResourceProfile = require("whatap/lib/util/resourceprofile");
17
+ const ProfilePack = require('../pack/profile-pack');
18
+ const TxRecord = require('../service/tx-record');
19
+ const DateUtil = require('../util/dateutil');
20
+ const SecurityMaster = require('../net/security-master');
21
+ const DataProfileAgent = require('../data/dataprofile-agent');
22
+ const MessageStep = require("whatap/lib/step/message-step");
23
+ const MeterUsers = require("whatap/lib/counter/meter/meter-users");
24
+ const DataPackSender = require("whatap/lib/data/datapack-sender");
25
+ const MeterService = require('../counter/meter/meter-service').MeterService;
26
+
27
+ var trace_background_socket_enabled = conf.getProperty('trace_background_socket_enabled', false);
28
+ conf.on('trace_background_socket_enabled', function (newProps) {
29
+ trace_background_socket_enabled = newProps;
30
+ })
31
+ var trace_sampling_enabled = conf.getProperty('trace_sampling_enabled', false);
32
+ conf.on('trace_sampling_enabled', function (newProps) {
33
+ trace_sampling_enabled = newProps;
34
+ })
35
+ var trace_sampling_tps = conf.getProperty('trace_sampling_tps', 1000);
36
+ conf.on('trace_sampling_tps', function (newProps) {
37
+ trace_sampling_tps = newProps;
38
+ })
8
39
 
9
40
  var SocketIOObserver = function(agent){
10
41
  this.agent = agent;
11
42
  this.packages = ['socket.io'];
12
43
  };
13
44
 
14
- SocketIOObserver.prototype.inject = function( mod ){
45
+ var socket_count = {
46
+ count: 0,
47
+ start_time: null
48
+ };
49
+
50
+ SocketIOObserver.prototype.inject = function (mod, moduleName) {
51
+ if (mod.__whatap_observe__) {
52
+ return;
53
+ }
54
+ mod.__whatap_observe__ = true;
55
+ Logger.initPrint("SocketIOObserver");
56
+
15
57
  var self = this;
16
58
  var aop = self.agent.aop;
17
59
 
18
- if(mod.__whatap_observe__) { return; }
19
- mod.__whatap_observe__ = true;
60
+ aop.after(mod.Server.prototype, 'on', function (obj, args, ret, lctx) {
61
+ aop.after(mod.Socket.prototype, 'emit', function (_obj, _args, _ret, _lctx) {
62
+ if(!trace_background_socket_enabled) {
63
+ return;
64
+ }
65
+ if(trace_sampling_enabled){
66
+ var now = Date.now();
67
+ if(!socket_count.start_time) {
68
+ socket_count.start_time = now;
69
+ }
20
70
 
21
- aop.after(mod.prototype, ['listen','attach'], function(obj, args, ret) {
22
- if (!ret.sockets) return;
71
+ if ((now - socket_count.start_time) > 5000) {
72
+ socket_count.start_time = now;
73
+ socket_count.count = 0;
74
+ }
23
75
 
24
- aop.before(ret.sockets, ['on', 'addListener'], function(obj, args) {
25
- if (args[0] !== 'connection') return;
76
+ socket_count.count++;
77
+ if(socket_count.count > trace_sampling_tps) {
78
+ MeterService.add(0, 1, 0, 0, 0, 0);
79
+ return;
80
+ }
81
+ }
26
82
 
27
- aop.functionHook(args, -1, function(obj, args) {
28
- if (!args[0]) return; //no client socket
83
+ TraceContextManager._asyncLocalStorage.run(initCtx(_obj, _args), () => {
84
+ try{
85
+ var ctx = TraceContextManager._asyncLocalStorage.getStore();
86
+ if (!ctx) {
87
+ return;
88
+ }
29
89
 
30
- var socket = args[0];
90
+ var socket = _obj;
91
+ var host;
92
+ if (socket.handshake && socket.handshake.address && socket.handshake.address.includes(':')) {
93
+ host = socket.handshake.address.substring(socket.handshake.address.lastIndexOf(':') + 1);
94
+ }
31
95
 
32
- MeterSocketio.connected(1);
96
+ ctx.socket_connecting = true;
97
+ ctx.footprint('Socket Connecting: ' + host);
33
98
 
34
- socket.on('disconnect', function() {
35
- MeterSocketio.disconnected();
36
- });
99
+ var step = new SocketStep();
100
+ step.start_time = ctx.getElapsedTime();
101
+ step.ipaddr = Buffer.from(IPUtil.stringToBytes(host));
102
+ // step.port = port;
37
103
 
38
- aop.before(socket, ['emit', 'send'], function(obj, args) {
39
- if (args[0] === 'newListener') return;
40
- MeterSocketio.send(null, args);
41
- });
104
+ ctx.socket_connecting = false;
105
+ step.elapsed = ctx.getElapsedTime() - step.start_time;
106
+ ctx.profile.push(step);
42
107
 
43
- aop.before(socket, ['on', 'addListener'], function(obj, args) {
44
- if (args[0] === 'disconnect') return;
45
- aop.functionHook(args, -1, function (obj, args) {
46
- MeterSocketio.receive(null, args[0]);
47
- });
48
- });
108
+ ctx.footprint('Socket Connecting Done');
109
+
110
+ self.__endTransaction(null, ctx);
111
+ return;
112
+ }catch (e) {
113
+ Logger.printError('WHATAP-616', 'socket.io transaction error..', e, false);
114
+ return;
115
+ }
49
116
  });
50
117
  });
51
118
  });
119
+ };
120
+
121
+ SocketIOObserver.prototype.__endTransaction = function(error, ctx) {
122
+ try {
123
+ var profile = new ProfilePack();
124
+ var wtx = new TxRecord();
125
+ wtx.endTime = DateUtil.currentTime();
126
+ profile.time = wtx.endTime;
127
+ wtx.elapsed = ctx.getElapsedTime();
128
+
129
+ DataTextAgent.SERVICE.add(ctx.service_hash, ctx.service_name);
130
+
131
+ wtx.seq = ctx.txid;
132
+ wtx.service = ctx.service_hash;
133
+ wtx.cpuTime = ResourceProfile.getCPUTime() - ctx.start_cpu;
134
+ wtx.malloc = ResourceProfile.getUsedHeapSize()-ctx.start_malloc;
135
+ if(wtx.malloc < 0) { wtx.malloc = 0; }
136
+ wtx.status = 2;
137
+
138
+ wtx.ipaddr = ctx.remoteIp;
139
+
140
+ MeterService.add(wtx.service, wtx.elapsed,
141
+ wtx.errorLevel, ctx.mcaller_pcode, ctx.mcaller_okind, ctx.mcaller_oid);
142
+
143
+ profile.oid = SecurityMaster.OID;
144
+ profile.service = wtx;
145
+
146
+ TraceContextManager.end(ctx._id);
147
+
148
+ setTimeout(function () {
149
+ DataProfileAgent.sendProfile(ctx, profile, false);
150
+ TraceContextManager.end(ctx._id);
151
+ ctx = null;
152
+ }, 100);
153
+ } catch (e) {
154
+ Logger.printError('WHATAP-615', 'Socket.io end transaction error..', e, false);
155
+ TraceContextManager.end(ctx._id);
156
+ ctx = null;
157
+ }
158
+
159
+ };
160
+
161
+ function initCtx(socket, args) {
162
+ const ctx = TraceContextManager.start();
163
+ if (!ctx) {return;}
164
+
165
+ var remote_addr;
166
+ const address = socket.handshake.address;
167
+ if(address && address.includes(':')){
168
+ remote_addr = address.substring(address.lastIndexOf(':')+1);
169
+ }
170
+
171
+ ctx.start_malloc = ResourceProfile.getUsedHeapSize();
172
+ ctx.start_cpu = ResourceProfile.getCPUTime();
173
+
174
+ remote_addr=IPUtil.checkIp4(remote_addr);
175
+ ctx.remoteIp = IPUtil.stringToInt(remote_addr);
176
+ ctx.userid = Long.fromNumber(ctx.remoteIp);
177
+ MeterUsers.add(ctx.userid);
178
+
179
+ return ctx;
52
180
  }
53
181
 
54
182
  exports.SocketIOObserver = SocketIOObserver;
@@ -33,19 +33,23 @@ function charToInt(ch) {
33
33
  function IPUtil() {
34
34
  }
35
35
  IPUtil.prototype.stringToBytes = function (ipStr) {
36
- if(ipStr ===null || ipStr === undefined){
36
+ try{
37
+ if (ipStr === null || ipStr === undefined) {
38
+ return emptyBytes;
39
+ }
40
+ var ipArr = ipStr.split(".");
41
+ if (ipArr.length < 4)
42
+ return emptyBytes;
43
+
44
+ var buf = [0, 0, 0, 0];
45
+ buf[0] = wordToInt(ipArr[0]) & 0xFF;
46
+ buf[1] = wordToInt(ipArr[1]) & 0xFF;
47
+ buf[2] = wordToInt(ipArr[2]) & 0xFF;
48
+ buf[3] = wordToInt(ipArr[3]) & 0xFF;
49
+ return buf;
50
+ }catch (e) {
37
51
  return emptyBytes;
38
52
  }
39
- var ipArr = ipStr.split(".");
40
- if (ipArr.length < 4)
41
- return emptyBytes;
42
-
43
- var buf = [0,0,0,0];
44
- buf[0] = wordToInt(ipArr[0]) & 0xFF;
45
- buf[1] = wordToInt(ipArr[1]) & 0xFF;
46
- buf[2] = wordToInt(ipArr[2]) & 0xFF;
47
- buf[3] = wordToInt(ipArr[3]) & 0xFF;
48
- return buf;
49
53
  }
50
54
 
51
55
  IPUtil.prototype.stringToInt = function (ip) {
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "whatap",
3
3
  "homepage": "http://www.whatap.io",
4
- "version": "0.4.92",
5
- "releaseDate": "20240206",
4
+ "version": "0.4.94",
5
+ "releaseDate": "20240307",
6
6
  "description": "Monitoring and Profiling Service",
7
7
  "main": "index.js",
8
8
  "scripts": {},