whatap 0.4.91 → 0.4.93
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 +1 -1
- package/lib/observers/net-observer.js +29 -62
- package/lib/observers/socket.io-observer.js +28 -114
- 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,
|
|
@@ -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;
|
|
@@ -4,137 +4,51 @@
|
|
|
4
4
|
* can be found in the LICENSE file.
|
|
5
5
|
*/
|
|
6
6
|
|
|
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 MeterService = require('../counter/meter/meter-service').MeterService;
|
|
7
|
+
var MeterSocketio = require('../counter/meter/meter-socket.io');
|
|
23
8
|
|
|
24
9
|
var SocketIOObserver = function(agent){
|
|
25
10
|
this.agent = agent;
|
|
26
11
|
this.packages = ['socket.io'];
|
|
27
12
|
};
|
|
28
13
|
|
|
29
|
-
SocketIOObserver.prototype.inject = function
|
|
30
|
-
if (mod.__whatap_observe__) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
mod.__whatap_observe__ = true;
|
|
34
|
-
Logger.initPrint("SocketIOObserver");
|
|
35
|
-
if (conf.trace_background_socket_enabled === false) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
14
|
+
SocketIOObserver.prototype.inject = function( mod ){
|
|
39
15
|
var self = this;
|
|
40
16
|
var aop = self.agent.aop;
|
|
41
17
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
})
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
SocketIOObserver.prototype.__createTransactionObserver = function (callback) {
|
|
48
|
-
var self = this;
|
|
49
|
-
|
|
50
|
-
return function (){
|
|
51
|
-
TraceContextManager._asyncLocalStorage.run(initCtx(), () => {
|
|
52
|
-
var ctx = TraceContextManager._asyncLocalStorage.getStore();
|
|
53
|
-
if(!ctx) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
MeterSocketio.connected(1);
|
|
58
|
-
|
|
59
|
-
var host;
|
|
60
|
-
const socket = arguments[0];
|
|
61
|
-
const address = socket.handshake.address;
|
|
62
|
-
if(address && address.includes(':')){
|
|
63
|
-
host = address.substring(address.lastIndexOf(':')+1);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
ctx.socket_connecting = true;
|
|
67
|
-
|
|
68
|
-
ctx.footprint('Socket Connecting: ' + host);
|
|
69
|
-
|
|
70
|
-
var step = new SocketStep();
|
|
71
|
-
step.start_time = ctx.getElapsedTime();
|
|
72
|
-
step.ipaddr = Buffer.from(IPUtil.stringToBytes(host));
|
|
73
|
-
// step.port = port;
|
|
74
|
-
|
|
75
|
-
ctx.socket_connecting = false;
|
|
76
|
-
step.elapsed = ctx.getElapsedTime() - step.start_time;
|
|
77
|
-
ctx.profile.push(step);
|
|
78
|
-
|
|
79
|
-
ctx.footprint('Socket Connecting Done');
|
|
80
|
-
|
|
81
|
-
self.__endTransaction(null, ctx);
|
|
82
|
-
|
|
83
|
-
return;
|
|
84
|
-
})
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
SocketIOObserver.prototype.__endTransaction = function(error, ctx) {
|
|
89
|
-
try {
|
|
90
|
-
var profile = new ProfilePack();
|
|
91
|
-
var wtx = new TxRecord();
|
|
92
|
-
wtx.endTime = DateUtil.currentTime();
|
|
93
|
-
profile.time = wtx.endTime;
|
|
94
|
-
wtx.elapsed = ctx.getElapsedTime();
|
|
95
|
-
|
|
96
|
-
ctx.service_hash = HashUtil.hashFromString(ctx.service_name);
|
|
97
|
-
DataTextAgent.SERVICE.add(ctx.service_hash, ctx.service_name);
|
|
98
|
-
|
|
99
|
-
wtx.service = ctx.service_hash;
|
|
100
|
-
wtx.cpuTime = ResourceProfile.getCPUTime() - ctx.start_cpu;
|
|
101
|
-
wtx.malloc = ResourceProfile.getUsedHeapSize()-ctx.start_malloc;
|
|
102
|
-
if(wtx.malloc < 0) { wtx.malloc = 0; }
|
|
103
|
-
wtx.status = 2;
|
|
104
|
-
|
|
105
|
-
MeterService.add(wtx.service, wtx.elapsed,
|
|
106
|
-
wtx.errorLevel, ctx.mcaller_pcode, ctx.mcaller_okind, ctx.mcaller_oid);
|
|
18
|
+
if(mod.__whatap_observe__) { return; }
|
|
19
|
+
mod.__whatap_observe__ = true;
|
|
107
20
|
|
|
108
|
-
|
|
109
|
-
|
|
21
|
+
aop.after(mod.prototype, ['listen','attach'], function(obj, args, ret) {
|
|
22
|
+
if (!ret.sockets) return;
|
|
110
23
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
DataProfileAgent.sendProfile(ctx, profile, false);
|
|
114
|
-
ctx = null;
|
|
115
|
-
}, 100);
|
|
24
|
+
aop.before(ret.sockets, ['on', 'addListener'], function(obj, args) {
|
|
25
|
+
if (args[0] !== 'connection') return;
|
|
116
26
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
TraceContextManager.end(ctx._id);
|
|
120
|
-
ctx = null;
|
|
121
|
-
}
|
|
27
|
+
aop.functionHook(args, -1, function(obj, args) {
|
|
28
|
+
if (!args[0]) return; //no client socket
|
|
122
29
|
|
|
123
|
-
|
|
30
|
+
var socket = args[0];
|
|
124
31
|
|
|
125
|
-
|
|
126
|
-
const ctx = TraceContextManager.start();
|
|
127
|
-
if (!ctx) {
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
32
|
+
MeterSocketio.connected(1);
|
|
130
33
|
|
|
131
|
-
|
|
132
|
-
|
|
34
|
+
socket.on('disconnect', function() {
|
|
35
|
+
MeterSocketio.disconnected();
|
|
36
|
+
});
|
|
133
37
|
|
|
134
|
-
|
|
135
|
-
|
|
38
|
+
aop.before(socket, ['emit', 'send'], function(obj, args) {
|
|
39
|
+
if (args[0] === 'newListener') return;
|
|
40
|
+
MeterSocketio.send(null, args);
|
|
41
|
+
});
|
|
136
42
|
|
|
137
|
-
|
|
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
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
});
|
|
138
52
|
}
|
|
139
53
|
|
|
140
54
|
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