whatap 0.5.26 → 1.0.0
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/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 +4 -0
- package/lib/conf/config-default.js +3 -10
- package/lib/conf/configure.js +349 -369
- package/lib/conf/license.js +1 -1
- package/lib/control/packagectr-helper.js +3 -34
- package/lib/core/agent.js +882 -176
- package/lib/core/interceptor.js +6 -6
- package/lib/core/shimmer.js +36 -82
- package/lib/counter/counter-manager.js +8 -79
- package/lib/counter/task/activetransaction.js +17 -68
- package/lib/io/data-inputx.js +3 -13
- package/lib/io/data-outputx.js +206 -268
- package/lib/logger.js +6 -6
- package/lib/net/security-master.js +20 -139
- package/lib/observers/apollo-server-observer.js +27 -33
- package/lib/observers/global-observer.js +80 -155
- package/lib/observers/http-observer.js +236 -666
- package/lib/observers/ioredis-observer.js +294 -0
- package/lib/observers/maria-observer.js +362 -204
- package/lib/observers/mongodb-observer.js +226 -169
- package/lib/observers/mongoose-observer.js +323 -518
- package/lib/observers/mssql-observer.js +418 -177
- package/lib/observers/mysql-observer.js +449 -342
- package/lib/observers/mysql2-observer.js +358 -396
- package/lib/observers/oracle-observer.js +384 -559
- package/lib/observers/pgsql-observer.js +489 -231
- package/lib/observers/prisma-observer.js +92 -303
- package/lib/observers/process-observer.js +35 -79
- package/lib/observers/redis-observer.js +331 -166
- package/lib/observers/socket.io-observer.js +187 -226
- package/lib/observers/websocket-observer.js +301 -175
- package/lib/pack/counter-pack.js +0 -3
- package/lib/pack/log-sink-pack.js +52 -14
- package/lib/pack/tagcount-pack.js +4 -4
- package/lib/{counter/task → system}/gc-action.js +74 -27
- package/lib/trace/trace-context-manager.js +25 -113
- package/lib/trace/trace-context.js +7 -21
- package/lib/trace/trace-httpc.js +11 -17
- package/lib/trace/trace-sql.js +21 -29
- package/lib/udp/async_sender.js +119 -0
- package/lib/udp/index.js +17 -0
- package/lib/udp/packet_enum.js +52 -0
- package/lib/udp/packet_queue.js +69 -0
- package/lib/udp/packet_type_enum.js +33 -0
- package/lib/udp/param_def.js +72 -0
- package/lib/udp/udp_session.js +336 -0
- package/lib/util/escape-literal-sql.js +5 -5
- package/lib/util/hashutil.js +18 -18
- package/lib/util/keygen.js +3 -0
- package/lib/util/linkedset.js +2 -1
- package/lib/util/nodeutil.js +1 -2
- package/lib/util/sql-util.js +178 -0
- package/lib/util/trace-helper.js +91 -0
- package/lib/util/transfer.js +58 -0
- package/lib/value/map-value.js +2 -3
- package/package.json +5 -10
- package/lib/conf/conf-sys-mon.js +0 -101
- package/lib/control/cmd-config.js +0 -24
- package/lib/control/control-handler.js +0 -367
- package/lib/core/request-agent.js +0 -27
- package/lib/counter/meter/meter-activex.js +0 -67
- package/lib/counter/meter/meter-httpc.js +0 -57
- package/lib/counter/meter/meter-resource.js +0 -9
- package/lib/counter/meter/meter-service.js +0 -168
- package/lib/counter/meter/meter-socket.io.js +0 -51
- package/lib/counter/meter/meter-sql.js +0 -71
- package/lib/counter/meter/meter-users.js +0 -58
- package/lib/counter/meter.js +0 -183
- package/lib/counter/task/agentinfo.js +0 -107
- package/lib/counter/task/gcstat.js +0 -34
- package/lib/counter/task/heapmem.js +0 -25
- package/lib/counter/task/httpc.js +0 -76
- package/lib/counter/task/metering-info.js +0 -125
- package/lib/counter/task/proc-cpu.js +0 -29
- package/lib/counter/task/realtimeuser.js +0 -31
- package/lib/counter/task/res/systemECSTask.js +0 -39
- package/lib/counter/task/res/systemKubeTask.js +0 -53
- package/lib/counter/task/res/util/awsEcsClientThread.js +0 -218
- package/lib/counter/task/res/util/linuxProcStatUtil.js +0 -14
- package/lib/counter/task/res-sys-cpu.js +0 -62
- package/lib/counter/task/service.js +0 -202
- package/lib/counter/task/socketio.js +0 -30
- package/lib/counter/task/sql.js +0 -105
- package/lib/counter/task/systemperf.js +0 -43
- package/lib/data/datapack-sender.js +0 -289
- package/lib/data/dataprofile-agent.js +0 -162
- package/lib/data/datatext-agent.js +0 -135
- package/lib/data/event-level.js +0 -15
- package/lib/data/test.js +0 -49
- package/lib/data/zipprofile.js +0 -197
- package/lib/env/constants.js +0 -21
- package/lib/error/error-handler.js +0 -437
- package/lib/kube/kube-client.js +0 -144
- package/lib/lang/text-types.js +0 -58
- package/lib/logsink/line-log-util.js +0 -87
- package/lib/logsink/line-log.js +0 -12
- package/lib/logsink/log-sender.js +0 -78
- package/lib/logsink/log-tracer.js +0 -40
- package/lib/logsink/sender-util.js +0 -56
- package/lib/logsink/zip/zip-send.js +0 -177
- package/lib/net/netflag.js +0 -55
- package/lib/net/receiver.js +0 -66
- package/lib/net/sender.js +0 -141
- package/lib/net/tcp-return.js +0 -18
- package/lib/net/tcp-session.js +0 -286
- package/lib/net/tcpreq-client-proxy.js +0 -70
- package/lib/net/tcprequest-mgr.js +0 -58
- package/lib/observers/cluster-observer.js +0 -22
- package/lib/observers/express-observer.js +0 -215
- package/lib/observers/file-observer.js +0 -184
- package/lib/observers/grpc-observer.js +0 -336
- package/lib/observers/memcached-observer.js +0 -56
- package/lib/observers/mongo-observer.js +0 -317
- package/lib/observers/net-observer.js +0 -77
- package/lib/observers/promise-observer.js +0 -31
- package/lib/observers/schedule-observer.js +0 -67
- package/lib/observers/stream-observer.js +0 -19
- package/lib/observers/thrift-observer.js +0 -197
- package/lib/pack/activestack-pack.js +0 -55
- package/lib/pack/apenum.js +0 -8
- package/lib/pack/errorsnap-pack.js +0 -69
- package/lib/pack/event-pack.js +0 -54
- package/lib/pack/hitmap-pack.js +0 -63
- package/lib/pack/hitmap-pack1.js +0 -152
- package/lib/pack/netstat.js +0 -15
- package/lib/pack/otype.js +0 -7
- package/lib/pack/profile-pack.js +0 -49
- package/lib/pack/realtimeuser-pack.js +0 -41
- package/lib/pack/stat-general-pack.js +0 -96
- package/lib/pack/staterror-pack.js +0 -120
- package/lib/pack/stathttpc-pack.js +0 -66
- package/lib/pack/stathttpc-rec.js +0 -78
- package/lib/pack/statremote-pack.js +0 -46
- package/lib/pack/statservice-pack.js +0 -63
- package/lib/pack/statservice-pack1.js +0 -88
- package/lib/pack/statservice-rec.js +0 -292
- package/lib/pack/statservice-rec_dep.js +0 -151
- package/lib/pack/statsql-pack.js +0 -69
- package/lib/pack/statsql-rec.js +0 -100
- package/lib/pack/statuseragent-pack.js +0 -44
- package/lib/pack/tagctr.js +0 -15
- package/lib/pack/text-pack.js +0 -50
- package/lib/pack/time-count.js +0 -25
- package/lib/pack/websocket.js +0 -15
- package/lib/pack/zip-pack.js +0 -70
- package/lib/pii/pii-item.js +0 -31
- package/lib/pii/pii-mask.js +0 -174
- package/lib/plugin/plugin-loadermanager.js +0 -57
- package/lib/plugin/plugin.js +0 -75
- package/lib/service/tx-record.js +0 -332
- package/lib/stat/stat-error.js +0 -116
- package/lib/stat/stat-httpc.js +0 -98
- package/lib/stat/stat-remote-ip.js +0 -46
- package/lib/stat/stat-remote-ipurl.js +0 -88
- package/lib/stat/stat-sql.js +0 -113
- package/lib/stat/stat-tranx.js +0 -58
- package/lib/stat/stat-tx-caller.js +0 -160
- package/lib/stat/stat-tx-domain.js +0 -111
- package/lib/stat/stat-tx-referer.js +0 -112
- package/lib/stat/stat-useragent.js +0 -48
- package/lib/stat/timingsender.js +0 -76
- package/lib/step/activestack-step.js +0 -38
- package/lib/step/dbc-step.js +0 -36
- package/lib/step/http-stepx.js +0 -67
- package/lib/step/message-step.js +0 -40
- package/lib/step/method-stepx.js +0 -45
- package/lib/step/resultset-step.js +0 -40
- package/lib/step/securemsg-step.js +0 -44
- package/lib/step/socket-step.js +0 -46
- package/lib/step/sql-stepx.js +0 -68
- package/lib/step/sqlxtype.js +0 -16
- package/lib/step/step.js +0 -66
- package/lib/step/stepenum.js +0 -54
- package/lib/topology/link.js +0 -63
- package/lib/topology/nodeinfo.js +0 -123
- package/lib/topology/status-detector.js +0 -111
- package/lib/util/anylist.js +0 -103
- package/lib/util/cardinality/hyperloglog.js +0 -106
- package/lib/util/cardinality/murmurhash.js +0 -31
- package/lib/util/cardinality/registerset.js +0 -75
- package/lib/util/errordata.js +0 -21
- package/lib/util/iputil_x.js +0 -527
- package/lib/util/kube-util.js +0 -73
- package/lib/util/paramsecurity.js +0 -80
- package/lib/util/pre-process.js +0 -13
- package/lib/util/process-seq.js +0 -166
- package/lib/util/property-util.js +0 -36
- package/lib/util/request-queue.js +0 -70
- package/lib/util/requestdouble-queue.js +0 -72
- package/lib/util/resourceprofile.js +0 -157
- package/lib/util/stop-watch.js +0 -30
- package/lib/util/system-util.js +0 -10
- package/lib/util/userid-util.js +0 -57
|
@@ -1,17 +1,18 @@
|
|
|
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'),
|
|
5
2
|
HashUtil = require('../util/hashutil'),
|
|
3
|
+
Long = require('long'),
|
|
6
4
|
Logger = require('../logger'),
|
|
7
5
|
conf = require('../conf/configure'),
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
DateUtil = require('../util/dateutil'),
|
|
7
|
+
AsyncSender = require('../udp/async_sender'),
|
|
8
|
+
PacketTypeEnum = require('../udp/packet_type_enum'),
|
|
9
|
+
shimmer = require('../core/shimmer');
|
|
10
|
+
const { AsyncResource } = require('async_hooks');
|
|
11
11
|
|
|
12
12
|
var RedisObserver = function (agent) {
|
|
13
13
|
this.agent = agent;
|
|
14
|
-
this.
|
|
14
|
+
this.aop = agent.aop;
|
|
15
|
+
this.packages = ['redis'];
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
RedisObserver.prototype.inject = function (mod, modName) {
|
|
@@ -21,197 +22,361 @@ RedisObserver.prototype.inject = function (mod, modName) {
|
|
|
21
22
|
mod.__whatap_observe__ = true;
|
|
22
23
|
Logger.initPrint("RedisObserver");
|
|
23
24
|
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
} else if (modName === 'ioredis') {
|
|
27
|
-
this._injectIORedis(mod);
|
|
25
|
+
if (conf.sql_enabled === false) {
|
|
26
|
+
return;
|
|
28
27
|
}
|
|
29
|
-
};
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
var self = this;
|
|
32
30
|
var dbc_hash = 0;
|
|
33
|
-
var dbc = '';
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
31
|
+
var dbc = 'redis://';
|
|
32
|
+
|
|
33
|
+
// Redis 명령어 매핑 (한 번만 정의)
|
|
34
|
+
var REDIS_COMMANDS = {
|
|
35
|
+
// 기본 명령어들
|
|
36
|
+
'ping': 'PING', 'get': 'GET', 'set': 'SET', 'del': 'DEL', 'exists': 'EXISTS', 'keys': 'KEYS',
|
|
37
|
+
'setex': 'SETEX', 'setEx': 'SETEX', 'expire': 'EXPIRE', 'expireAt': 'EXPIREAT', 'expireat': 'EXPIREAT',
|
|
38
|
+
'ttl': 'TTL', 'incr': 'INCR', 'decr': 'DECR', 'incrBy': 'INCRBY', 'incrby': 'INCRBY',
|
|
39
|
+
'decrBy': 'DECRBY', 'decrby': 'DECRBY', 'mGet': 'MGET', 'mget': 'MGET', 'mSet': 'MSET', 'mset': 'MSET',
|
|
40
|
+
|
|
41
|
+
// Hash 명령어들
|
|
42
|
+
'hSet': 'HSET', 'hset': 'HSET', 'hGet': 'HGET', 'hget': 'HGET', 'hGetAll': 'HGETALL', 'hgetall': 'HGETALL',
|
|
43
|
+
'hMGet': 'HMGET', 'hmget': 'HMGET', 'hMSet': 'HMSET', 'hmset': 'HMSET', 'hDel': 'HDEL', 'hdel': 'HDEL',
|
|
44
|
+
|
|
45
|
+
// List 명령어들
|
|
46
|
+
'lPush': 'LPUSH', 'lpush': 'LPUSH', 'rPush': 'RPUSH', 'rpush': 'RPUSH', 'lPop': 'LPOP', 'lpop': 'LPOP',
|
|
47
|
+
'rPop': 'RPOP', 'rpop': 'RPOP', 'lRange': 'LRANGE', 'lrange': 'LRANGE', 'lLen': 'LLEN', 'llen': 'LLEN',
|
|
48
|
+
'lSet': 'LSET', 'lset': 'LSET', 'lRem': 'LREM', 'lrem': 'LREM',
|
|
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);
|
|
53
95
|
}
|
|
54
96
|
|
|
55
|
-
var
|
|
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
|
+
}
|
|
56
106
|
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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);
|
|
131
|
+
}
|
|
132
|
+
var commandText = `Redis ` + queryParts.join(' ');
|
|
133
|
+
|
|
134
|
+
if (hasCallback) {
|
|
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;
|
|
140
|
+
|
|
141
|
+
if (err) {
|
|
142
|
+
handleRedisError(ctx, err);
|
|
143
|
+
} else if (result !== undefined) {
|
|
144
|
+
if (Array.isArray(result)) {
|
|
145
|
+
resultCount = result.length;
|
|
146
|
+
} else if (typeof result === 'string' || typeof result === 'number') {
|
|
147
|
+
resultCount = 1;
|
|
65
148
|
}
|
|
149
|
+
}
|
|
66
150
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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]))
|
|
86
|
-
}
|
|
151
|
+
ctx.elapsed = command_elapsed;
|
|
152
|
+
ctx.active_sqlhash = false;
|
|
153
|
+
AsyncSender.send_packet(PacketTypeEnum.TX_SQL, ctx, [dbc, commandText, String(resultCount)]);
|
|
154
|
+
ctx.footprint(`Redis ${commandName} Done`);
|
|
87
155
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
156
|
+
if (callback && typeof callback === 'function') {
|
|
157
|
+
return callbackResource.bind(callback).apply(this, arguments);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
return originalFunction.apply(this, args);
|
|
163
|
+
} catch (err) {
|
|
164
|
+
handleRedisError(ctx, err);
|
|
165
|
+
throw err;
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
// Promise 또는 동기 처리
|
|
169
|
+
try {
|
|
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;
|
|
95
184
|
}
|
|
96
|
-
|
|
97
|
-
}).toString()
|
|
98
|
-
sql_step.p2 = toParamBytes(result, crc);
|
|
99
|
-
sql_step.pcrc = crc.value;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
sql_step.hash = HashUtil.hashFromString(sql);
|
|
103
|
-
ctx.profile.push(sql_step);
|
|
185
|
+
}
|
|
104
186
|
|
|
105
|
-
|
|
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;
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
} else {
|
|
204
|
+
// 동기 결과 처리
|
|
205
|
+
var command_elapsed = Date.now() - command_start_time;
|
|
206
|
+
var resultCount = 0;
|
|
106
207
|
|
|
107
|
-
|
|
108
|
-
|
|
208
|
+
if (result !== undefined) {
|
|
209
|
+
if (Array.isArray(result)) {
|
|
210
|
+
resultCount = result.length;
|
|
211
|
+
} else if (typeof result === 'string' || typeof result === 'number') {
|
|
212
|
+
resultCount = 1;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
109
215
|
|
|
110
|
-
ctx.
|
|
216
|
+
ctx.elapsed = command_elapsed;
|
|
217
|
+
AsyncSender.send_packet(PacketTypeEnum.TX_SQL, ctx, [dbc, commandText, String(resultCount)]);
|
|
218
|
+
ctx.footprint(`Redis ${commandName} Done`);
|
|
111
219
|
return result;
|
|
112
|
-
}catch (e) {
|
|
113
|
-
Logger.printError("WHATAP-605", "Redis CRUD error", e, false);
|
|
114
|
-
return originalMethod.apply(this, arguments);
|
|
115
220
|
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
221
|
+
} catch (commandError) {
|
|
222
|
+
handleRedisError(ctx, commandError);
|
|
223
|
+
var command_elapsed = Date.now() - command_start_time;
|
|
224
|
+
ctx.elapsed = command_elapsed;
|
|
225
|
+
AsyncSender.send_packet(PacketTypeEnum.TX_SQL, ctx, [dbc, commandText, '0']);
|
|
226
|
+
ctx.footprint(`Redis ${commandName} Done`);
|
|
227
|
+
throw commandError;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
120
230
|
});
|
|
121
|
-
return client;
|
|
122
231
|
};
|
|
123
|
-
}
|
|
232
|
+
}
|
|
124
233
|
|
|
125
|
-
|
|
126
|
-
|
|
234
|
+
function wrapRedisMethods(client) {
|
|
235
|
+
var wrappedCount = 0;
|
|
236
|
+
var skippedCount = 0;
|
|
237
|
+
var notFoundCount = 0;
|
|
238
|
+
var alreadyWrappedCount = 0;
|
|
127
239
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
240
|
+
// 클라이언트에 실제로 존재하는 메서드들 확인
|
|
241
|
+
var availableMethods = Object.getOwnPropertyNames(client)
|
|
242
|
+
.concat(Object.getOwnPropertyNames(Object.getPrototypeOf(client)))
|
|
243
|
+
.filter(name => typeof client[name] === 'function' && !name.startsWith('_'))
|
|
244
|
+
.sort();
|
|
131
245
|
|
|
132
|
-
|
|
133
|
-
|
|
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]);
|
|
246
|
+
// 한 번의 루프로 모든 메서드 처리
|
|
247
|
+
Object.keys(REDIS_COMMANDS).forEach(function(methodName) {
|
|
137
248
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
249
|
+
if (!client[methodName]) {
|
|
250
|
+
notFoundCount++;
|
|
251
|
+
skippedCount++;
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (client[methodName].__whatap_wrapped__) {
|
|
255
|
+
alreadyWrappedCount++;
|
|
256
|
+
skippedCount++;
|
|
257
|
+
return;
|
|
144
258
|
}
|
|
145
259
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
260
|
+
try {
|
|
261
|
+
// 원본 함수 참조 저장
|
|
262
|
+
var originalFunction = client[methodName];
|
|
263
|
+
client[methodName] = createRedisWrapper(originalFunction, REDIS_COMMANDS[methodName]);
|
|
264
|
+
client[methodName].__whatap_wrapped__ = true;
|
|
265
|
+
wrappedCount++;
|
|
266
|
+
} catch (e) {
|
|
267
|
+
skippedCount++;
|
|
268
|
+
Logger.printError('WHATAP-217', `Error wrapping ${methodName}`, e, false);
|
|
153
269
|
}
|
|
270
|
+
});
|
|
154
271
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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);
|
|
181
312
|
}
|
|
313
|
+
} else {
|
|
314
|
+
setupDbcInfo(options);
|
|
182
315
|
}
|
|
316
|
+
}
|
|
183
317
|
|
|
184
|
-
|
|
185
|
-
sql_step.start_time = ctx.getElapsedTime();
|
|
186
|
-
DataTextAgent.SQL.add(sql_step.hash, sql);
|
|
187
|
-
ctx.profile.push(sql_step);
|
|
318
|
+
var client = original.apply(this, args);
|
|
188
319
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
} catch (e) {
|
|
195
|
-
Logger.printError("WHATAP-605", "ioredis CRUD error", e, false);
|
|
196
|
-
return original.apply(this, arguments);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
320
|
+
// Redis 클라이언트 후킹
|
|
321
|
+
if (client) {
|
|
322
|
+
var wrapAttempts = 0;
|
|
323
|
+
var maxAttempts = 3;
|
|
324
|
+
var wrapCompleted = false; // 완료 플래그 추가
|
|
199
325
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
326
|
+
function attemptBatchWrap(reason) {
|
|
327
|
+
if (wrapCompleted) {
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
203
330
|
|
|
204
|
-
|
|
205
|
-
};
|
|
331
|
+
wrapAttempts++;
|
|
206
332
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
333
|
+
if (wrapRedisMethods(client)) {
|
|
334
|
+
wrapCompleted = true; // 완료 마킹
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (wrapAttempts >= maxAttempts) {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// 이벤트 기반 래핑
|
|
346
|
+
if (client.on && typeof client.on === 'function') {
|
|
347
|
+
client.on('connect', function() {
|
|
348
|
+
attemptBatchWrap('Redis connect event');
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
client.on('ready', function() {
|
|
352
|
+
attemptBatchWrap('Redis ready event');
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// 즉시 시도
|
|
357
|
+
if (!attemptBatchWrap('Immediate attempt')) {
|
|
358
|
+
// 지연 시도
|
|
359
|
+
setImmediate(function() {
|
|
360
|
+
if (!attemptBatchWrap('setImmediate attempt')) {
|
|
361
|
+
// 1초 후 마지막 시도
|
|
362
|
+
setTimeout(function() {
|
|
363
|
+
attemptBatchWrap('Final timeout attempt');
|
|
364
|
+
}, 1000);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (ctx) {
|
|
371
|
+
ctx.elapsed = Date.now() - ctx.start_time;
|
|
372
|
+
ctx.footprint('Redis Connecting Done');
|
|
373
|
+
ctx.db_opening = false;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return client;
|
|
377
|
+
};
|
|
378
|
+
});
|
|
379
|
+
mod.createClient.__whatap_wrapped__ = true;
|
|
215
380
|
}
|
|
216
381
|
};
|
|
217
382
|
|