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 +14 -3
- package/lib/conf/config-default.js +8 -1
- package/lib/observers/http-observer.js +77 -21
- package/lib/observers/maria-observer.js +6 -0
- package/lib/observers/mongoose-observer.js +15 -9
- package/lib/observers/mssql-observer.js +6 -0
- package/lib/observers/mysql-observer.js +7 -1
- package/lib/observers/net-observer.js +29 -62
- package/lib/observers/pgsql-observer.js +7 -0
- package/lib/observers/socket.io-observer.js +153 -25
- package/lib/util/iputil.js +15 -11
- package/package.json +2 -2
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.
|
|
10
|
+
*Node.js 지원 버젼: 16.4.0 이상
|
|
11
11
|
|
|
12
12
|

|
|
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
|
|
18
|
+
$ npm install whatap
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
@@ -37,11 +37,22 @@ whatap.conf 파일은 다음과 같은 내용을 포함합니다.
|
|
|
37
37
|
|
|
38
38
|
#### Usage
|
|
39
39
|
|
|
40
|
-
루트
|
|
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
|

|
|
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.
|
|
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
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
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.
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
|
9
|
-
conf
|
|
10
|
-
IPUtil
|
|
11
|
-
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
|
|
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'
|
|
20
|
+
this.packages = ['net'];
|
|
16
21
|
};
|
|
17
22
|
|
|
18
23
|
NetObserver.prototype.inject = function (mod, moduleName) {
|
|
19
|
-
if
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
24
|
+
if(mod.__whatap_observe__) { return; }
|
|
22
25
|
mod.__whatap_observe__ = true;
|
|
23
26
|
Logger.initPrint("NetObserver");
|
|
24
|
-
if (
|
|
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
|
|
35
|
+
if(!ctx || !trace_background_socket_enabled){
|
|
35
36
|
return;
|
|
36
37
|
}
|
|
37
|
-
var host, port;
|
|
38
|
-
if
|
|
39
|
-
|
|
40
|
-
|
|
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
|
|
44
|
+
if(port == undefined){
|
|
43
45
|
lctx.step = null;
|
|
44
46
|
return;
|
|
45
47
|
}
|
|
46
|
-
ctx.socket_connecting
|
|
48
|
+
ctx.socket_connecting=true;
|
|
47
49
|
|
|
48
|
-
ctx.footprint('Socket Connecting: ' + host
|
|
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
|
|
67
|
+
if(!ctx || !step || !trace_background_socket_enabled){
|
|
61
68
|
return;
|
|
62
69
|
}
|
|
63
|
-
ctx.socket_connecting
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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
|
-
|
|
22
|
-
|
|
71
|
+
if ((now - socket_count.start_time) > 5000) {
|
|
72
|
+
socket_count.start_time = now;
|
|
73
|
+
socket_count.count = 0;
|
|
74
|
+
}
|
|
23
75
|
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
28
|
-
|
|
83
|
+
TraceContextManager._asyncLocalStorage.run(initCtx(_obj, _args), () => {
|
|
84
|
+
try{
|
|
85
|
+
var ctx = TraceContextManager._asyncLocalStorage.getStore();
|
|
86
|
+
if (!ctx) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
29
89
|
|
|
30
|
-
|
|
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
|
-
|
|
96
|
+
ctx.socket_connecting = true;
|
|
97
|
+
ctx.footprint('Socket Connecting: ' + host);
|
|
33
98
|
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
});
|
|
104
|
+
ctx.socket_connecting = false;
|
|
105
|
+
step.elapsed = ctx.getElapsedTime() - step.start_time;
|
|
106
|
+
ctx.profile.push(step);
|
|
42
107
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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;
|
package/lib/util/iputil.js
CHANGED
|
@@ -33,19 +33,23 @@ function charToInt(ch) {
|
|
|
33
33
|
function IPUtil() {
|
|
34
34
|
}
|
|
35
35
|
IPUtil.prototype.stringToBytes = function (ipStr) {
|
|
36
|
-
|
|
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