whatap 1.0.1 → 1.0.2
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 +32 -78
- package/lib/conf/conf-sys-mon.js +101 -0
- package/lib/conf/config-default.js +10 -3
- package/lib/conf/configure.js +369 -349
- package/lib/conf/license.js +1 -1
- package/lib/control/cmd-config.js +24 -0
- package/lib/control/control-handler.js +367 -0
- package/lib/control/packagectr-helper.js +34 -3
- package/lib/core/agent.js +176 -882
- package/lib/core/interceptor.js +6 -6
- package/lib/core/request-agent.js +27 -0
- package/lib/core/shimmer.js +82 -36
- package/lib/counter/counter-manager.js +79 -8
- package/lib/counter/meter/meter-activex.js +67 -0
- package/lib/counter/meter/meter-httpc.js +57 -0
- package/lib/counter/meter/meter-resource.js +9 -0
- package/lib/counter/meter/meter-service.js +168 -0
- package/lib/counter/meter/meter-socket.io.js +51 -0
- package/lib/counter/meter/meter-sql.js +71 -0
- package/lib/counter/meter/meter-users.js +58 -0
- package/lib/counter/meter.js +183 -0
- package/lib/counter/task/activetransaction.js +68 -17
- package/lib/counter/task/agentinfo.js +107 -0
- package/lib/{system → counter/task}/gc-action.js +27 -74
- package/lib/counter/task/gcstat.js +34 -0
- package/lib/counter/task/heapmem.js +25 -0
- package/lib/counter/task/httpc.js +76 -0
- package/lib/counter/task/metering-info.js +125 -0
- package/lib/counter/task/proc-cpu.js +29 -0
- package/lib/counter/task/realtimeuser.js +31 -0
- package/lib/counter/task/res/systemECSTask.js +39 -0
- package/lib/counter/task/res/systemKubeTask.js +53 -0
- package/lib/counter/task/res/util/awsEcsClientThread.js +218 -0
- package/lib/counter/task/res/util/linuxProcStatUtil.js +14 -0
- package/lib/counter/task/res-sys-cpu.js +62 -0
- package/lib/counter/task/service.js +202 -0
- package/lib/counter/task/socketio.js +30 -0
- package/lib/counter/task/sql.js +105 -0
- package/lib/counter/task/systemperf.js +43 -0
- package/lib/data/datapack-sender.js +289 -0
- package/lib/data/dataprofile-agent.js +162 -0
- package/lib/data/datatext-agent.js +135 -0
- package/lib/data/event-level.js +15 -0
- package/lib/data/test.js +49 -0
- package/lib/data/zipprofile.js +197 -0
- package/lib/env/constants.js +21 -0
- package/lib/error/error-handler.js +437 -0
- package/lib/io/data-inputx.js +13 -3
- package/lib/io/data-outputx.js +268 -206
- package/lib/kube/kube-client.js +144 -0
- package/lib/lang/text-types.js +58 -0
- package/lib/logger.js +6 -6
- package/lib/logsink/line-log-util.js +87 -0
- package/lib/logsink/line-log.js +12 -0
- package/lib/logsink/log-sender.js +78 -0
- package/lib/logsink/log-tracer.js +40 -0
- package/lib/logsink/sender-util.js +56 -0
- package/lib/logsink/zip/zip-send.js +177 -0
- package/lib/net/netflag.js +55 -0
- package/lib/net/receiver.js +66 -0
- package/lib/net/security-master.js +139 -20
- package/lib/net/sender.js +141 -0
- package/lib/net/tcp-return.js +18 -0
- package/lib/net/tcp-session.js +286 -0
- package/lib/net/tcpreq-client-proxy.js +70 -0
- package/lib/net/tcprequest-mgr.js +58 -0
- package/lib/observers/apollo-server-observer.js +33 -27
- package/lib/observers/cluster-observer.js +22 -0
- package/lib/observers/express-observer.js +215 -0
- package/lib/observers/file-observer.js +184 -0
- package/lib/observers/global-observer.js +155 -80
- package/lib/observers/grpc-observer.js +336 -0
- package/lib/observers/http-observer.js +666 -236
- package/lib/observers/maria-observer.js +204 -362
- package/lib/observers/memcached-observer.js +56 -0
- package/lib/observers/mongo-observer.js +317 -0
- package/lib/observers/mongodb-observer.js +169 -226
- package/lib/observers/mongoose-observer.js +518 -323
- package/lib/observers/mssql-observer.js +177 -418
- package/lib/observers/mysql-observer.js +342 -449
- package/lib/observers/mysql2-observer.js +396 -358
- package/lib/observers/net-observer.js +77 -0
- package/lib/observers/oracle-observer.js +559 -384
- package/lib/observers/pgsql-observer.js +231 -489
- package/lib/observers/prisma-observer.js +303 -92
- package/lib/observers/process-observer.js +79 -35
- package/lib/observers/promise-observer.js +31 -0
- package/lib/observers/redis-observer.js +166 -331
- package/lib/observers/schedule-observer.js +67 -0
- package/lib/observers/socket.io-observer.js +226 -187
- package/lib/observers/stream-observer.js +19 -0
- package/lib/observers/thrift-observer.js +197 -0
- package/lib/observers/websocket-observer.js +175 -301
- package/lib/pack/activestack-pack.js +55 -0
- package/lib/pack/apenum.js +8 -0
- package/lib/pack/counter-pack.js +3 -0
- package/lib/pack/errorsnap-pack.js +69 -0
- package/lib/pack/event-pack.js +54 -0
- package/lib/pack/hitmap-pack.js +63 -0
- package/lib/pack/hitmap-pack1.js +152 -0
- package/lib/pack/log-sink-pack.js +14 -52
- package/lib/pack/netstat.js +15 -0
- package/lib/pack/otype.js +7 -0
- package/lib/pack/profile-pack.js +49 -0
- package/lib/pack/realtimeuser-pack.js +41 -0
- package/lib/pack/stat-general-pack.js +96 -0
- package/lib/pack/staterror-pack.js +120 -0
- package/lib/pack/stathttpc-pack.js +66 -0
- package/lib/pack/stathttpc-rec.js +78 -0
- package/lib/pack/statremote-pack.js +46 -0
- package/lib/pack/statservice-pack.js +63 -0
- package/lib/pack/statservice-pack1.js +88 -0
- package/lib/pack/statservice-rec.js +292 -0
- package/lib/pack/statservice-rec_dep.js +151 -0
- package/lib/pack/statsql-pack.js +69 -0
- package/lib/pack/statsql-rec.js +100 -0
- package/lib/pack/statuseragent-pack.js +44 -0
- package/lib/pack/tagcount-pack.js +4 -4
- package/lib/pack/tagctr.js +15 -0
- package/lib/pack/text-pack.js +50 -0
- package/lib/pack/time-count.js +25 -0
- package/lib/pack/websocket.js +15 -0
- package/lib/pack/zip-pack.js +70 -0
- package/lib/pii/pii-item.js +31 -0
- package/lib/pii/pii-mask.js +174 -0
- package/lib/plugin/plugin-loadermanager.js +57 -0
- package/lib/plugin/plugin.js +75 -0
- package/lib/service/tx-record.js +332 -0
- package/lib/stat/stat-error.js +116 -0
- package/lib/stat/stat-httpc.js +98 -0
- package/lib/stat/stat-remote-ip.js +46 -0
- package/lib/stat/stat-remote-ipurl.js +88 -0
- package/lib/stat/stat-sql.js +113 -0
- package/lib/stat/stat-tranx.js +58 -0
- package/lib/stat/stat-tx-caller.js +160 -0
- package/lib/stat/stat-tx-domain.js +111 -0
- package/lib/stat/stat-tx-referer.js +112 -0
- package/lib/stat/stat-useragent.js +48 -0
- package/lib/stat/timingsender.js +76 -0
- package/lib/step/activestack-step.js +38 -0
- package/lib/step/dbc-step.js +36 -0
- package/lib/step/http-stepx.js +67 -0
- package/lib/step/message-step.js +40 -0
- package/lib/step/method-stepx.js +45 -0
- package/lib/step/resultset-step.js +40 -0
- package/lib/step/securemsg-step.js +44 -0
- package/lib/step/socket-step.js +46 -0
- package/lib/step/sql-stepx.js +68 -0
- package/lib/step/sqlxtype.js +16 -0
- package/lib/step/step.js +66 -0
- package/lib/step/stepenum.js +54 -0
- package/lib/topology/link.js +63 -0
- package/lib/topology/nodeinfo.js +123 -0
- package/lib/topology/status-detector.js +111 -0
- package/lib/trace/trace-context-manager.js +113 -25
- package/lib/trace/trace-context.js +21 -7
- package/lib/trace/trace-httpc.js +17 -11
- package/lib/trace/trace-sql.js +29 -21
- package/lib/util/anylist.js +103 -0
- package/lib/util/cardinality/hyperloglog.js +106 -0
- package/lib/util/cardinality/murmurhash.js +31 -0
- package/lib/util/cardinality/registerset.js +75 -0
- package/lib/util/errordata.js +21 -0
- package/lib/util/escape-literal-sql.js +5 -5
- package/lib/util/hashutil.js +18 -18
- package/lib/util/iputil_x.js +527 -0
- package/lib/util/keygen.js +0 -3
- package/lib/util/kube-util.js +73 -0
- package/lib/util/linkedset.js +1 -2
- package/lib/util/nodeutil.js +2 -1
- package/lib/util/paramsecurity.js +80 -0
- package/lib/util/pre-process.js +13 -0
- package/lib/util/process-seq.js +166 -0
- package/lib/util/property-util.js +36 -0
- package/lib/util/request-queue.js +70 -0
- package/lib/util/requestdouble-queue.js +72 -0
- package/lib/util/resourceprofile.js +157 -0
- package/lib/util/stop-watch.js +30 -0
- package/lib/util/system-util.js +10 -0
- package/lib/util/userid-util.js +57 -0
- package/lib/value/map-value.js +3 -2
- package/package.json +9 -4
- package/whatap.conf +1 -4
- package/agent/darwin/arm64/whatap_nodejs +0 -0
- package/agent/linux/amd64/whatap_nodejs +0 -0
- package/agent/linux/arm64/whatap_nodejs +0 -0
- package/build.txt +0 -4
- package/lib/observers/ioredis-observer.js +0 -294
- package/lib/udp/async_sender.js +0 -119
- package/lib/udp/index.js +0 -17
- package/lib/udp/packet_enum.js +0 -52
- package/lib/udp/packet_queue.js +0 -69
- package/lib/udp/packet_type_enum.js +0 -33
- package/lib/udp/param_def.js +0 -72
- package/lib/udp/udp_session.js +0 -336
- package/lib/util/sql-util.js +0 -178
- package/lib/util/trace-helper.js +0 -91
- package/lib/util/transfer.js +0 -58
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Created by yunhoi on 12/06/2017.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
var TraceContextManager = require('../trace/trace-context-manager'),
|
|
6
|
+
Logger = require('../logger');
|
|
7
|
+
|
|
8
|
+
var PromiseObserver = function (agent) {
|
|
9
|
+
this.agent = agent;
|
|
10
|
+
this.packages = ['promise', 'bluebird'];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
PromiseObserver.prototype.inject = function (mod, moduleName) {
|
|
14
|
+
|
|
15
|
+
var self = this;
|
|
16
|
+
var aop = self.agent.aop;
|
|
17
|
+
|
|
18
|
+
if(mod.__whatap_observe__) {return;}
|
|
19
|
+
mod.__whatap_observe__ = true;
|
|
20
|
+
Logger.initPrint("PromiseObserver");
|
|
21
|
+
aop.both(mod.prototype, 'then'
|
|
22
|
+
, function (obj, args, lctx) {
|
|
23
|
+
var ctx = TraceContextManager.getCurrentContext();
|
|
24
|
+
aop.functionHook(args, -1, function (obj, args) {
|
|
25
|
+
TraceContextManager.resume(ctx);
|
|
26
|
+
})
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
exports.PromiseObserver = PromiseObserver;
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
var TraceContextManager = require('../trace/trace-context-manager'),
|
|
2
|
+
DataTextAgent = require('../data/datatext-agent'),
|
|
3
|
+
SqlStepX = require('../step/sql-stepx'),
|
|
4
|
+
DBCStep = require('../step/dbc-step'),
|
|
2
5
|
HashUtil = require('../util/hashutil'),
|
|
3
|
-
Long = require('long'),
|
|
4
6
|
Logger = require('../logger'),
|
|
5
7
|
conf = require('../conf/configure'),
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
shimmer = require('../core/shimmer');
|
|
10
|
-
const { AsyncResource } = require('async_hooks');
|
|
8
|
+
ParamSecurity = require('../util/paramsecurity');
|
|
9
|
+
const shimmer = require('../core/shimmer');
|
|
10
|
+
const {Buffer} = require("buffer");
|
|
11
11
|
|
|
12
12
|
var RedisObserver = function (agent) {
|
|
13
13
|
this.agent = agent;
|
|
14
|
-
this.
|
|
15
|
-
this.packages = ['redis'];
|
|
14
|
+
this.packages = ['redis', 'ioredis'];
|
|
16
15
|
};
|
|
17
16
|
|
|
18
17
|
RedisObserver.prototype.inject = function (mod, modName) {
|
|
@@ -22,361 +21,197 @@ RedisObserver.prototype.inject = function (mod, modName) {
|
|
|
22
21
|
mod.__whatap_observe__ = true;
|
|
23
22
|
Logger.initPrint("RedisObserver");
|
|
24
23
|
|
|
25
|
-
if (
|
|
26
|
-
|
|
24
|
+
if (modName === 'redis') {
|
|
25
|
+
this._injectRedis(mod);
|
|
26
|
+
} else if (modName === 'ioredis') {
|
|
27
|
+
this._injectIORedis(mod);
|
|
27
28
|
}
|
|
29
|
+
};
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
RedisObserver.prototype._injectRedis = function (mod) {
|
|
30
32
|
var dbc_hash = 0;
|
|
31
|
-
var dbc = '
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// Set 명령어들
|
|
51
|
-
'sAdd': 'SADD', 'sadd': 'SADD', 'sMembers': 'SMEMBERS', 'smembers': 'SMEMBERS', 'sRem': 'SREM', 'srem': 'SREM',
|
|
52
|
-
'sCard': 'SCARD', 'scard': 'SCARD',
|
|
53
|
-
|
|
54
|
-
// Sorted Set 명령어들
|
|
55
|
-
'zAdd': 'ZADD', 'zadd': 'ZADD', 'zRange': 'ZRANGE', 'zrange': 'ZRANGE', 'zRem': 'ZREM', 'zrem': 'ZREM'
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// DBC 정보 설정
|
|
59
|
-
function setupDbcInfo(connectionOptions) {
|
|
60
|
-
if (dbc_hash === 0 && connectionOptions) {
|
|
61
|
-
dbc = 'redis://';
|
|
62
|
-
dbc += connectionOptions.host || 'localhost';
|
|
63
|
-
dbc += ':';
|
|
64
|
-
dbc += connectionOptions.port || 6379;
|
|
65
|
-
dbc += '/';
|
|
66
|
-
dbc += connectionOptions.db || 0;
|
|
67
|
-
dbc_hash = HashUtil.hashFromString(dbc);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// 에러 처리 함수
|
|
72
|
-
function handleRedisError(ctx, err) {
|
|
73
|
-
if (!err) return;
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
var errorClass = err.code || err.name || 'RedisError';
|
|
77
|
-
var errorMessage = err.message || 'redis error';
|
|
78
|
-
|
|
79
|
-
if (!ctx.error) ctx.error = 1;
|
|
80
|
-
ctx.status = 500;
|
|
81
|
-
var errors = [errorClass, errorMessage];
|
|
82
|
-
|
|
83
|
-
AsyncSender.send_packet(PacketTypeEnum.TX_ERROR, ctx, errors);
|
|
84
|
-
} catch (e) {
|
|
85
|
-
Logger.printError('WHATAP-216', 'Error handling Redis error', e, false);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// 통합 모니터링 함수 (한 번만 정의, 모든 명령어에서 재사용)
|
|
90
|
-
function createRedisWrapper(originalFunction, commandName) {
|
|
91
|
-
return function wrappedMethod() {
|
|
92
|
-
var ctx = TraceContextManager.getCurrentContext();
|
|
93
|
-
if (!ctx) {
|
|
94
|
-
return originalFunction.apply(this, arguments);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
var args = Array.prototype.slice.call(arguments);
|
|
98
|
-
var callback = null;
|
|
99
|
-
var hasCallback = false;
|
|
100
|
-
|
|
101
|
-
// 콜백 함수 찾기
|
|
102
|
-
if (args.length > 0 && typeof args[args.length - 1] === 'function') {
|
|
103
|
-
callback = args[args.length - 1];
|
|
104
|
-
hasCallback = true;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const asyncResource = new AsyncResource('redis-command');
|
|
108
|
-
|
|
109
|
-
return asyncResource.runInAsyncScope(() => {
|
|
110
|
-
// DB 연결 패킷 전송
|
|
111
|
-
ctx.start_time = Date.now();
|
|
112
|
-
ctx.elapsed = 0;
|
|
113
|
-
ctx.active_sqlhash = true;
|
|
114
|
-
AsyncSender.send_packet(PacketTypeEnum.TX_DB_CONN, ctx, [dbc]);
|
|
115
|
-
|
|
116
|
-
// Redis 명령 시작
|
|
117
|
-
var command_start_time = Date.now();
|
|
118
|
-
ctx.footprint(`Redis ${commandName} Start`);
|
|
119
|
-
|
|
120
|
-
// Redis에서는 args에서 쿼리 조합 (Python APM 방식 참고)
|
|
121
|
-
var queryParts = [commandName];
|
|
122
|
-
if (args && args.length > 0) {
|
|
123
|
-
// 콜백 함수 제외하고 실제 Redis 인자들만 처리
|
|
124
|
-
var redisArgs = hasCallback ? args.slice(0, -1) : args;
|
|
125
|
-
// 각 인자를 문자열로 변환하고 20자로 제한
|
|
126
|
-
var argStrings = redisArgs.map(function(arg) {
|
|
127
|
-
var argStr = String(arg);
|
|
128
|
-
return argStr.length > 20 ? argStr.substring(0, 20) + '...' : argStr;
|
|
129
|
-
});
|
|
130
|
-
queryParts = queryParts.concat(argStrings);
|
|
33
|
+
var dbc = '';
|
|
34
|
+
|
|
35
|
+
const selectCommand = new Set(['get', 'hGet', 'hmGet']);
|
|
36
|
+
const insertCommand = new Set(['set', 'hSet', 'hset', 'hmSet', 'hmset', 'zAdd', 'zadd', 'lSet', 'lset']);
|
|
37
|
+
const updateCommand = new Set(['set', 'lSet', 'lset', 'hSet', 'hset', 'zAdd', 'zadd']);
|
|
38
|
+
const deleteCommand = new Set(['del', 'lRem', 'sRem', 'srem', 'hDel', 'hdel', 'zRem', 'zrem']);
|
|
39
|
+
const commands = new Set([...selectCommand, ...insertCommand, ...updateCommand, ...deleteCommand]);
|
|
40
|
+
|
|
41
|
+
shimmer.wrap(mod, 'createClient', function (original) {
|
|
42
|
+
return function wrappedCreateClient() {
|
|
43
|
+
if (dbc_hash === 0) {
|
|
44
|
+
if (arguments.length > 0) {
|
|
45
|
+
var info = (arguments[0] || {});
|
|
46
|
+
dbc = info.url || '';
|
|
47
|
+
dbc_hash = HashUtil.hashFromString(dbc);
|
|
48
|
+
|
|
49
|
+
DataTextAgent.DBC.add(dbc_hash, dbc);
|
|
50
|
+
DataTextAgent.METHOD.add(dbc_hash, dbc);
|
|
51
|
+
DataTextAgent.ERROR.add(dbc_hash, dbc);
|
|
131
52
|
}
|
|
132
|
-
|
|
53
|
+
}
|
|
133
54
|
|
|
134
|
-
|
|
135
|
-
// 비동기 콜백 처리
|
|
136
|
-
const callbackResource = new AsyncResource('redis-callback');
|
|
137
|
-
args[args.length - 1] = asyncResource.bind(function(err, result) {
|
|
138
|
-
var command_elapsed = Date.now() - command_start_time;
|
|
139
|
-
var resultCount = 0;
|
|
55
|
+
var client = original.apply(this, arguments);
|
|
140
56
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
57
|
+
const commandsArray = Array.from(commands);
|
|
58
|
+
commandsArray.forEach(cmdName => {
|
|
59
|
+
shimmer.wrap(client, cmdName, function (originalMethod) {
|
|
60
|
+
const wrappedFunction = function wrappedSendCommand() {
|
|
61
|
+
try{
|
|
62
|
+
var ctx = TraceContextManager.getCurrentContext();
|
|
63
|
+
if (!ctx) {
|
|
64
|
+
return originalMethod.apply(this, arguments);
|
|
148
65
|
}
|
|
149
|
-
}
|
|
150
66
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
var result = originalFunction.apply(this, args);
|
|
171
|
-
|
|
172
|
-
// Promise 결과 처리
|
|
173
|
-
if (result && typeof result.then === 'function') {
|
|
174
|
-
return result.then(
|
|
175
|
-
function(res) {
|
|
176
|
-
var command_elapsed = Date.now() - command_start_time;
|
|
177
|
-
var resultCount = 0;
|
|
178
|
-
|
|
179
|
-
if (res !== undefined) {
|
|
180
|
-
if (Array.isArray(res)) {
|
|
181
|
-
resultCount = res.length;
|
|
182
|
-
} else if (typeof res === 'string' || typeof res === 'number') {
|
|
183
|
-
resultCount = 1;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
ctx.elapsed = command_elapsed;
|
|
188
|
-
ctx.active_sqlhash = false;
|
|
189
|
-
AsyncSender.send_packet(PacketTypeEnum.TX_SQL, ctx, [dbc, commandText, String(resultCount)]);
|
|
190
|
-
ctx.footprint(`Redis ${commandName} Done`);
|
|
191
|
-
return res;
|
|
192
|
-
},
|
|
193
|
-
function(err) {
|
|
194
|
-
handleRedisError(ctx, err);
|
|
195
|
-
var command_elapsed = Date.now() - command_start_time;
|
|
196
|
-
ctx.elapsed = command_elapsed;
|
|
197
|
-
ctx.active_sqlhash = false;
|
|
198
|
-
AsyncSender.send_packet(PacketTypeEnum.TX_SQL, ctx, [dbc, commandText, '0']);
|
|
199
|
-
ctx.footprint(`Redis ${commandName} Done`);
|
|
200
|
-
throw err;
|
|
67
|
+
var dbc_step = new DBCStep();
|
|
68
|
+
dbc_step.hash = dbc_hash;
|
|
69
|
+
ctx.profile.push(dbc_step);
|
|
70
|
+
|
|
71
|
+
ctx.footprint('Redis Command Start');
|
|
72
|
+
|
|
73
|
+
var command = wrappedFunction._commandName || 'unknown';
|
|
74
|
+
var sql = `${command.toUpperCase()}`;
|
|
75
|
+
var sql_step = new SqlStepX();
|
|
76
|
+
sql_step.start_time = ctx.getElapsedTime();
|
|
77
|
+
sql_step.dbc = dbc_hash;
|
|
78
|
+
|
|
79
|
+
if(conf.getProperty('profile_redis_param_enabled', false)){
|
|
80
|
+
if (arguments[0] && typeof arguments[0] === 'string')
|
|
81
|
+
sql += ' ' + arguments[0];
|
|
82
|
+
else if (arguments[0] && Array.isArray(arguments[0]))
|
|
83
|
+
sql += ' ' + JSON.stringify(arguments[0]);
|
|
84
|
+
else if (arguments[0] && typeof arguments[0] === 'object'){
|
|
85
|
+
sql += ' ' + JSON.stringify(Object.keys(arguments[0]))
|
|
201
86
|
}
|
|
202
|
-
);
|
|
203
|
-
} else {
|
|
204
|
-
// 동기 결과 처리
|
|
205
|
-
var command_elapsed = Date.now() - command_start_time;
|
|
206
|
-
var resultCount = 0;
|
|
207
87
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
88
|
+
if(arguments[1] && arguments[1].length > 0){
|
|
89
|
+
var args = Array.isArray(arguments[1]) ? arguments[1] : [arguments[1]];
|
|
90
|
+
sql_step.setTrue(1);
|
|
91
|
+
var crc = {value: 0};
|
|
92
|
+
const result = args.map((arg) => {
|
|
93
|
+
if (typeof arg === 'string') {
|
|
94
|
+
return `'${arg}'`
|
|
95
|
+
}
|
|
96
|
+
return arg
|
|
97
|
+
}).toString()
|
|
98
|
+
sql_step.p2 = toParamBytes(result, crc);
|
|
99
|
+
sql_step.pcrc = crc.value;
|
|
213
100
|
}
|
|
214
101
|
}
|
|
102
|
+
sql_step.hash = HashUtil.hashFromString(sql);
|
|
103
|
+
ctx.profile.push(sql_step);
|
|
104
|
+
|
|
105
|
+
DataTextAgent.SQL.add(sql_step.hash, sql);
|
|
215
106
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
107
|
+
var result = originalMethod.apply(this, arguments);
|
|
108
|
+
sql_step.elapsed = ctx.getElapsedTime();
|
|
109
|
+
|
|
110
|
+
ctx.footprint('Redis Command Done');
|
|
219
111
|
return result;
|
|
112
|
+
}catch (e) {
|
|
113
|
+
Logger.printError("WHATAP-605", "Redis CRUD error", e, false);
|
|
114
|
+
return originalMethod.apply(this, arguments);
|
|
220
115
|
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
AsyncSender.send_packet(PacketTypeEnum.TX_SQL, ctx, [dbc, commandText, '0']);
|
|
226
|
-
ctx.footprint(`Redis ${commandName} Done`);
|
|
227
|
-
throw commandError;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
116
|
+
};
|
|
117
|
+
wrappedFunction._commandName = cmdName;
|
|
118
|
+
return wrappedFunction;
|
|
119
|
+
});
|
|
230
120
|
});
|
|
121
|
+
return client;
|
|
231
122
|
};
|
|
232
|
-
}
|
|
123
|
+
});
|
|
233
124
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
var skippedCount = 0;
|
|
237
|
-
var notFoundCount = 0;
|
|
238
|
-
var alreadyWrappedCount = 0;
|
|
125
|
+
return this;
|
|
126
|
+
};
|
|
239
127
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
.filter(name => typeof client[name] === 'function' && !name.startsWith('_'))
|
|
244
|
-
.sort();
|
|
128
|
+
RedisObserver.prototype._injectIORedis = function (mod) {
|
|
129
|
+
var ioredis_dbc_hash = 0;
|
|
130
|
+
var ioredis_dbc = '';
|
|
245
131
|
|
|
246
|
-
|
|
247
|
-
|
|
132
|
+
const selectCommand = new Set(['get', 'hget', 'hmget', 'zrange', 'smembers', 'lrange']);
|
|
133
|
+
const insertCommand = new Set(['set', 'hset', 'hmset', 'zadd', 'lset', 'sadd', 'lpush', 'rpush', 'evalsha']);
|
|
134
|
+
const updateCommand = new Set(['set', 'lset', 'hset', 'zadd']);
|
|
135
|
+
const deleteCommand = new Set(['del', 'lrem', 'srem', 'hdel', 'zrem']);
|
|
136
|
+
const commands = new Set([...selectCommand, ...insertCommand, ...updateCommand, ...deleteCommand]);
|
|
248
137
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
alreadyWrappedCount++;
|
|
256
|
-
skippedCount++;
|
|
257
|
-
return;
|
|
138
|
+
shimmer.wrap(mod.prototype, 'sendCommand', function (original) {
|
|
139
|
+
return function wrappedSendCommand(command) {
|
|
140
|
+
// Get trace context
|
|
141
|
+
var ctx = TraceContextManager.getCurrentContext();
|
|
142
|
+
if (!ctx) {
|
|
143
|
+
return original.apply(this, arguments);
|
|
258
144
|
}
|
|
259
145
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
skippedCount++;
|
|
268
|
-
Logger.printError('WHATAP-217', `Error wrapping ${methodName}`, e, false);
|
|
146
|
+
if (ioredis_dbc_hash === 0 && this.options) {
|
|
147
|
+
ioredis_dbc = 'redis://';
|
|
148
|
+
ioredis_dbc += this.options.host || '';
|
|
149
|
+
ioredis_dbc += ':';
|
|
150
|
+
ioredis_dbc += this.options.port || '';
|
|
151
|
+
ioredis_dbc_hash = HashUtil.hashFromString(ioredis_dbc);
|
|
152
|
+
DataTextAgent.DBC.add(ioredis_dbc_hash, ioredis_dbc);
|
|
269
153
|
}
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
return wrappedCount > 0;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// createClient 래핑
|
|
276
|
-
if (mod.createClient && !mod.createClient.__whatap_wrapped__) {
|
|
277
|
-
shimmer.wrap(mod, 'createClient', function(original) {
|
|
278
|
-
return function wrappedCreateClient() {
|
|
279
|
-
var args = Array.prototype.slice.call(arguments);
|
|
280
|
-
var ctx = TraceContextManager.getCurrentContext();
|
|
281
|
-
|
|
282
|
-
if (ctx) {
|
|
283
|
-
ctx.start_time = Date.now();
|
|
284
|
-
ctx.footprint('IORedis Client Created');
|
|
285
|
-
ctx.db_opening = true;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (args.length > 0) {
|
|
289
|
-
var options = args[0] || {};
|
|
290
|
-
// URL에서 연결 정보 추출
|
|
291
|
-
if (typeof options === 'string') {
|
|
292
|
-
try {
|
|
293
|
-
var url = new URL(options);
|
|
294
|
-
setupDbcInfo({
|
|
295
|
-
host: url.hostname,
|
|
296
|
-
port: parseInt(url.port) || 6379,
|
|
297
|
-
db: url.pathname.slice(1) || 0
|
|
298
|
-
});
|
|
299
|
-
} catch (e) {
|
|
300
|
-
setupDbcInfo({ host: 'localhost', port: 6379, db: 0 });
|
|
301
|
-
}
|
|
302
|
-
} else if (options.url) {
|
|
303
|
-
try {
|
|
304
|
-
var url = new URL(options.url);
|
|
305
|
-
setupDbcInfo({
|
|
306
|
-
host: url.hostname,
|
|
307
|
-
port: parseInt(url.port) || 6379,
|
|
308
|
-
db: options.database || url.pathname.slice(1) || 0
|
|
309
|
-
});
|
|
310
|
-
} catch (e) {
|
|
311
|
-
setupDbcInfo(options);
|
|
312
|
-
}
|
|
313
|
-
} else {
|
|
314
|
-
setupDbcInfo(options);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
var client = original.apply(this, args);
|
|
319
154
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
155
|
+
if (command && command.name && commands.has(command.name.toLowerCase())) {
|
|
156
|
+
var dbc_step = new DBCStep();
|
|
157
|
+
dbc_step.hash = ioredis_dbc_hash;
|
|
158
|
+
dbc_step.start_time = ctx.getElapsedTime();
|
|
159
|
+
ctx.profile.push(dbc_step);
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
var sql_step = new SqlStepX();
|
|
163
|
+
var sql = command.name.toUpperCase();
|
|
164
|
+
if(conf.getProperty('profile_redis_param_enabled', false)){
|
|
165
|
+
var args = command.args;
|
|
166
|
+
var key = args.shift();
|
|
167
|
+
if (key && typeof key === 'string')
|
|
168
|
+
sql += ' ' + key;
|
|
169
|
+
|
|
170
|
+
if(args && args.length > 0){
|
|
171
|
+
sql_step.setTrue(1);
|
|
172
|
+
var crc = {value: 0};
|
|
173
|
+
const result = args.map((arg) => {
|
|
174
|
+
if (typeof arg === 'string') {
|
|
175
|
+
return `'${arg}'`
|
|
176
|
+
}
|
|
177
|
+
return arg;
|
|
178
|
+
}).toString()
|
|
179
|
+
sql_step.p2 = toParamBytes(result, crc);
|
|
180
|
+
sql_step.pcrc = crc.value;
|
|
340
181
|
}
|
|
341
|
-
|
|
342
|
-
return false;
|
|
343
182
|
}
|
|
344
183
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
client.on('ready', function() {
|
|
352
|
-
attemptBatchWrap('Redis ready event');
|
|
353
|
-
});
|
|
354
|
-
}
|
|
184
|
+
sql_step.hash = HashUtil.hashFromString(sql);
|
|
185
|
+
sql_step.start_time = ctx.getElapsedTime();
|
|
186
|
+
DataTextAgent.SQL.add(sql_step.hash, sql);
|
|
187
|
+
ctx.profile.push(sql_step);
|
|
355
188
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
}, 1000);
|
|
365
|
-
}
|
|
366
|
-
});
|
|
367
|
-
}
|
|
189
|
+
var originalPromise = original.apply(this, arguments);
|
|
190
|
+
return originalPromise.finally(function () {
|
|
191
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
192
|
+
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
193
|
+
});
|
|
194
|
+
} catch (e) {
|
|
195
|
+
Logger.printError("WHATAP-605", "ioredis CRUD error", e, false);
|
|
196
|
+
return original.apply(this, arguments);
|
|
368
197
|
}
|
|
198
|
+
}
|
|
369
199
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
200
|
+
return original.apply(this, arguments);
|
|
201
|
+
};
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
return this;
|
|
205
|
+
};
|
|
375
206
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
207
|
+
var toParamBytes = function (p, crc) {
|
|
208
|
+
if (p == null || p.length === 0) {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
return ParamSecurity.encrypt(Buffer.from(p, 'utf8'), crc);
|
|
213
|
+
} catch (e) {
|
|
214
|
+
return null;
|
|
380
215
|
}
|
|
381
216
|
};
|
|
382
217
|
|
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
var TraceContextManager = require('../trace/trace-context-manager'),
|
|
8
|
+
conf = require('../conf/configure'),
|
|
9
|
+
DataTextAgent = require('../data/datatext-agent'),
|
|
10
|
+
DataProfileAgent = require('../data/dataprofile-agent'),
|
|
11
|
+
EventLevel = require('../data/event-level'),
|
|
12
|
+
TxRecord = require('../service/tx-record'),
|
|
13
|
+
ProfilePack = require('../pack/profile-pack'),
|
|
14
|
+
SecurityMaster = require('../net/security-master'),
|
|
15
|
+
HashUtil = require('../util/hashutil'),
|
|
16
|
+
DateUtil = require('../util/dateutil'),
|
|
17
|
+
ResourceProfile = require('../util/resourceprofile'),
|
|
18
|
+
MessageStep = require('../step/message-step'),
|
|
19
|
+
Logger = require('../logger');
|
|
20
|
+
|
|
21
|
+
var ScheduleObserver = function(agent){
|
|
22
|
+
this.agent = agent;
|
|
23
|
+
this.packages = ['node-schedule'];
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
ScheduleObserver.prototype.inject = function (mod, moduleName) {
|
|
27
|
+
if(mod.__whatap_observe__) { return; }
|
|
28
|
+
mod.__whatap_observe__ = true;
|
|
29
|
+
Logger.initPrint("ScheduleObserver");
|
|
30
|
+
var self = this;
|
|
31
|
+
var aop = self.agent.aop;
|
|
32
|
+
|
|
33
|
+
aop.after(mod, 'scheduleJob',
|
|
34
|
+
function (obj, args, ret) {
|
|
35
|
+
var orig = ret.job;
|
|
36
|
+
if(!orig) return;
|
|
37
|
+
ret.job = async () => {
|
|
38
|
+
var ctx = null;
|
|
39
|
+
if(conf['trace_node_schedule_enabled']) {
|
|
40
|
+
ctx = TraceContextManager.startTrace('ScheduleJob');
|
|
41
|
+
}
|
|
42
|
+
var result = null;
|
|
43
|
+
try {
|
|
44
|
+
result = await orig.apply(this, arguments);
|
|
45
|
+
} catch(err) {
|
|
46
|
+
Logger.printError('WHATAP-607', 'End batch error..', err, false);
|
|
47
|
+
}
|
|
48
|
+
if(conf['trace_node_schedule_enabled'] && ctx != null) {
|
|
49
|
+
try {
|
|
50
|
+
var step = new MessageStep();
|
|
51
|
+
step.msg = 'Node ScheduleJob finished!!!!!'
|
|
52
|
+
step.hash = HashUtil.hashFromString(step.msg);;
|
|
53
|
+
step.start_time = ctx.getElapsedTime();
|
|
54
|
+
step.desc = '';
|
|
55
|
+
DataTextAgent.MESSAGE.add(step.hash, step.msg);
|
|
56
|
+
ctx.profile.add(step);
|
|
57
|
+
TraceContextManager.endTrace(ctx);
|
|
58
|
+
if(ctx != null) ctx = null;
|
|
59
|
+
} catch(err) {}
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
exports.ScheduleObserver = ScheduleObserver;
|