whatap 0.4.97 → 0.5.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.
Files changed (39) hide show
  1. package/lib/conf/config-default.js +11 -3
  2. package/lib/conf/configure.js +32 -19
  3. package/lib/conf/log-config-default.js +37 -0
  4. package/lib/control/control-handler.js +19 -6
  5. package/lib/core/agent.js +12 -9
  6. package/lib/core/shimmer.js +98 -0
  7. package/lib/counter/task/agentinfo.js +1 -1
  8. package/lib/data/datapack-sender.js +22 -0
  9. package/lib/data/dataprofile-agent.js +17 -1
  10. package/lib/data/zipprofile.js +2 -2
  11. package/lib/logger.js +25 -1
  12. package/lib/logsink/line-log-util.js +87 -0
  13. package/lib/logsink/line-log.js +12 -0
  14. package/lib/logsink/log-sender.js +78 -0
  15. package/lib/logsink/log-tracer.js +40 -0
  16. package/lib/logsink/sender-util.js +51 -0
  17. package/lib/logsink/zip/zip-send.js +177 -0
  18. package/lib/net/paramdef.js +1 -0
  19. package/lib/net/security-master.js +10 -5
  20. package/lib/observers/global-observer.js +140 -0
  21. package/lib/observers/grpc-observer.js +339 -0
  22. package/lib/observers/http-observer.js +7 -7
  23. package/lib/observers/process-observer.js +57 -8
  24. package/lib/observers/redis-observer.js +69 -11
  25. package/lib/observers/websocket-observer.js +1 -1
  26. package/lib/pack/event-pack.js +1 -1
  27. package/lib/pack/log-sink-pack.js +139 -0
  28. package/lib/pack/packenum.js +3 -1
  29. package/lib/pack/zip-pack.js +0 -1
  30. package/lib/stat/{stat-remoteip.js → stat-remote-ip.js} +8 -8
  31. package/lib/stat/stat-remote-ipurl.js +88 -0
  32. package/lib/stat/timingsender.js +4 -1
  33. package/lib/topology/link.js +63 -0
  34. package/lib/topology/nodeinfo.js +123 -0
  35. package/lib/topology/status-detector.js +111 -0
  36. package/lib/util/compare-util.js +131 -0
  37. package/lib/util/kube-util.js +3 -3
  38. package/lib/util/linkedset.js +278 -0
  39. package/package.json +2 -2
@@ -0,0 +1,339 @@
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
+ Logger = require('../logger');
10
+ const { Detector: URLPatternDetector } = require("../trace/serviceurl-pattern-detector");
11
+ const HashUtil = require("../util/hashutil");
12
+ const DataTextAgent = require("../data/datatext-agent");
13
+ const ResourceProfile = require("../util/resourceprofile");
14
+ const ProfilePack = require('../pack/profile-pack');
15
+ const TxRecord = require('../service/tx-record');
16
+ const DateUtil = require('../util/dateutil');
17
+ const SecurityMaster = require('../net/security-master');
18
+ const DataProfileAgent = require("../data/dataprofile-agent");
19
+ const MessageStep = require("../step/message-step");
20
+ const MeterService = require('../counter/meter/meter-service').MeterService;
21
+
22
+ const shimmer = require('../core/shimmer');
23
+
24
+ var grpc_profile_enabled = conf.getProperty('grpc_profile_enabled', true);
25
+ var grpc_profile_stream_client_enabled = conf.getProperty('grpc_profile_stream_client_enabled', true);
26
+ var grpc_profile_stream_server_enabled = conf.getProperty('grpc_profile_stream_server_enabled', true);
27
+ var grpc_profile_ignore_method = conf.getProperty('grpc_profile_ignore_method', '');
28
+ var ignore_method_set = null;
29
+ conf.on('grpc_profile_enabled', function(newProperty) {
30
+ grpc_profile_enabled = newProperty;
31
+ });
32
+ conf.on('grpc_profile_stream_client_enabled', function(newProperty) {
33
+ grpc_profile_stream_client_enabled = newProperty;
34
+ });
35
+ conf.on('grpc_profile_stream_server_enabled', function(newProperty) {
36
+ grpc_profile_stream_server_enabled = newProperty;
37
+ });
38
+ conf.on('grpc_profile_ignore_method', function(newProperty) {
39
+ grpc_profile_ignore_method = newProperty;
40
+ });
41
+
42
+ var GRpcObserver = function(agent) {
43
+ this.agent = agent;
44
+ this.packages = ['@grpc/grpc-js'];
45
+ };
46
+
47
+ const types = {
48
+ unary: 'unary',
49
+ client_stream: 'clientStream',
50
+ server_stream: 'serverStream',
51
+ bidi: 'bidi'
52
+ };
53
+
54
+ var _module;
55
+
56
+ GRpcObserver.prototype.inject = function(mod, moduleName) {
57
+ if (mod.__whatap_observe__) {
58
+ return;
59
+ }
60
+ _module = mod;
61
+ mod.__whatap_observe__ = true;
62
+ Logger.initPrint("GRpcObserver");
63
+
64
+ if (grpc_profile_enabled) {
65
+ shimmer.wrap(mod.Server.prototype, 'register', wrapRegister);
66
+ shimmer.wrap(mod.Client.prototype, 'register', wrapRegister);
67
+ }
68
+ };
69
+
70
+ function checkIgnoreMethod(ignore_method, method_name){
71
+ try{
72
+ if (ignore_method) {
73
+ ignore_method_set = new Set(ignore_method.split(','));
74
+ } else {
75
+ ignore_method_set = null;
76
+ }
77
+ if (ignore_method_set && ignore_method_set.has(method_name)) {
78
+ return true;
79
+ }
80
+ }catch (e) {
81
+ Logger.printError('WHATAP-703', 'gRPC checkIgnoreMethod error: ' + e, false);
82
+ }
83
+ return false;
84
+ }
85
+
86
+ function wrapHandler(handler, methodName, type) {
87
+ return function(call, callback) {
88
+ var method_name = methodName.includes('/') ? methodName.substring(methodName.lastIndexOf('/')+1, methodName.length) : methodName
89
+ if (!grpc_profile_enabled || checkIgnoreMethod(conf.getProperty('grpc_profile_ignore_method', ''), method_name)) {
90
+ return handler.call(this, call, callback);
91
+ }
92
+
93
+ TraceContextManager._asyncLocalStorage.run(initCtx(), () => {
94
+ try {
95
+ var ctx = TraceContextManager._asyncLocalStorage.getStore();
96
+ if (!ctx) {
97
+ return handler.call(this, call, callback);
98
+ }
99
+
100
+ ctx.service_name = methodName;
101
+ ctx.service_hash = HashUtil.hashFromString(methodName);
102
+
103
+ var step_type = new MessageStep();
104
+ step_type.hash = HashUtil.hashFromString('Type');
105
+ step_type.start_time = ctx.getElapsedTime();
106
+ step_type.desc = type;
107
+ DataTextAgent.MESSAGE.add(step_type.hash, "Type");
108
+ ctx.profile.push(step_type);
109
+
110
+ var step_method = new MessageStep();
111
+ step_method.hash = HashUtil.hashFromString('Method');
112
+ step_method.start_time = ctx.getElapsedTime();
113
+ step_method.desc = method_name;
114
+ DataTextAgent.MESSAGE.add(step_method.hash, "Method");
115
+ ctx.profile.push(step_method);
116
+
117
+ if(call.request && Object.keys(call.request).length > 0){
118
+ var step_param = new MessageStep();
119
+ step_param.hash = HashUtil.hashFromString('Parameter');
120
+ step_param.start_time = ctx.getElapsedTime();
121
+ step_param.desc = JSON.stringify(Object.keys(call.request));
122
+ DataTextAgent.MESSAGE.add(step_param.hash, "Parameter");
123
+ ctx.profile.push(step_param);
124
+ }
125
+
126
+ console.log(call.pendingStatus)
127
+
128
+ ctx.grpc_method = method_name;
129
+
130
+ function wrappedCallback(err, response, ctx) {
131
+
132
+ if (err) {
133
+ ctx.error = err.stack;
134
+ ctx.statusCode = 500;
135
+
136
+ var step_error = new MessageStep();
137
+ step_error.hash = HashUtil.hashFromString("EXCEPTION");
138
+ step_error.start_time = ctx.getElapsedTime();
139
+ step_error.desc = err.stack;
140
+ DataTextAgent.MESSAGE.add(step_error.hash, "EXCEPTION");
141
+ ctx.profile.push(step_error);
142
+ }
143
+
144
+ endTransaction(ctx);
145
+
146
+ if (typeof callback === 'function') {
147
+ return callback(err, response);
148
+ }
149
+ }
150
+
151
+ return handler.call(this, call, (err, response) => wrappedCallback(err, response, ctx));
152
+ // return handler.call(this, call, (err, response) => {
153
+ // if (!err) {
154
+ // err = new Error('Exception error occured');
155
+ // }
156
+ // wrappedCallback(err, response, ctx);
157
+ } catch (err) {
158
+ Logger.printError('WHATAP-701', 'gRPC wrapHandler error: ' + err, false);
159
+
160
+ ctx.error = err.stack;
161
+
162
+ var step_error = new MessageStep();
163
+ step_error.hash = HashUtil.hashFromString("EXCEPTION");
164
+ step_error.start_time = ctx.getElapsedTime();
165
+ step_error.desc = err.stack;
166
+ DataTextAgent.MESSAGE.add(step_error.hash, "EXCEPTION");
167
+ ctx.profile.push(step_error);
168
+
169
+ endTransaction(ctx);
170
+
171
+ return handler.call(this, call, callback);
172
+ }
173
+ });
174
+ };
175
+ }
176
+
177
+ function wrapStreamHandler(handler, methodName, type) {
178
+ return function(call, callback) {
179
+ var method_name = methodName.includes('/') ? methodName.substring(methodName.lastIndexOf('/')+1, methodName.length) : methodName
180
+ if (!grpc_profile_enabled || checkIgnoreMethod(conf.getProperty('grpc_profile_ignore_method', ''), method_name)) {
181
+ return handler.call(this, call, callback);
182
+ }
183
+
184
+ switch (type) {
185
+ case 'server_stream':
186
+ if (!grpc_profile_stream_server_enabled) {
187
+ return handler.call(this, call, callback);
188
+ }
189
+ break;
190
+ case 'client_stream':
191
+ if (!grpc_profile_stream_client_enabled) {
192
+ return handler.call(this, call, callback);
193
+ }
194
+ break;
195
+ case 'bidi':
196
+ if (!grpc_profile_stream_server_enabled || !grpc_profile_stream_client_enabled) {
197
+ return handler.call(this, call, callback);
198
+ }
199
+ break;
200
+ }
201
+
202
+ TraceContextManager._asyncLocalStorage.run(initCtx(), () => {
203
+ try {
204
+ var ctx = TraceContextManager._asyncLocalStorage.getStore();
205
+ if (!ctx) {
206
+ return handler.call(this, call, callback);
207
+ }
208
+
209
+ ctx.service_name = methodName;
210
+ ctx.service_hash = HashUtil.hashFromString(methodName);
211
+
212
+ var step_type = new MessageStep();
213
+ step_type.hash = HashUtil.hashFromString('Type');
214
+ step_type.start_time = ctx.getElapsedTime();
215
+ step_type.desc = type;
216
+ DataTextAgent.MESSAGE.add(step_type.hash, "Type");
217
+ ctx.profile.push(step_type);
218
+
219
+ var step_method = new MessageStep();
220
+ step_method.hash = HashUtil.hashFromString('Method');
221
+ step_method.start_time = ctx.getElapsedTime();
222
+ step_method.desc = method_name;
223
+ DataTextAgent.MESSAGE.add(step_method.hash, "Method");
224
+ ctx.profile.push(step_method);
225
+
226
+ ctx.grpc_method = method_name;
227
+
228
+ const startTime = Date.now();
229
+
230
+ call.on('end', () => {
231
+ const duration = Date.now() - startTime;
232
+ endTransaction(ctx);
233
+ });
234
+
235
+ call.once('cancelled', () => {
236
+ ctx.cancelled = true;
237
+ var step_cancel = new MessageStep();
238
+ step_cancel.hash = HashUtil.hashFromString("CANCELLED");
239
+ step_cancel.start_time = ctx.getElapsedTime();
240
+ step_cancel.desc = "Request cancelled";
241
+ DataTextAgent.MESSAGE.add(step_cancel.hash, "CANCELLED");
242
+ ctx.profile.push(step_cancel);
243
+ endTransaction(ctx);
244
+ });
245
+
246
+ call.on('error', (err) => {
247
+ ctx.error = err.stack;
248
+ ctx.statusCode = err.code || grpc.status.INTERNAL;
249
+
250
+ var step_error = new MessageStep();
251
+ step_error.hash = HashUtil.hashFromString("EXCEPTION");
252
+ step_error.start_time = ctx.getElapsedTime();
253
+ step_error.desc = err.stack;
254
+ DataTextAgent.MESSAGE.add(step_error.hash, "EXCEPTION");
255
+ ctx.profile.push(step_error);
256
+
257
+ endTransaction(ctx);
258
+ });
259
+
260
+ return handler.call(this, call);
261
+ } catch (e) {
262
+ Logger.printError('WHATAP-702', 'gRPC wrapStreamHandler error: ' + e, false);
263
+ return handler.call(this, call);
264
+ }
265
+ });
266
+ };
267
+ }
268
+
269
+ function wrapRegister(register) {
270
+ return function(name, handler, serialize, deserialize, type) {
271
+ if (typeof handler === 'function') {
272
+ switch (type) {
273
+ case types.client_stream:
274
+ handler = wrapStreamHandler(handler, name, 'clientStream');
275
+ break;
276
+ case types.server_stream:
277
+ handler = wrapStreamHandler(handler, name, 'serverStream');
278
+ break;
279
+ case types.bidi:
280
+ handler = wrapStreamHandler(handler, name, 'bidi');
281
+ break;
282
+ case types.unary:
283
+ default:
284
+ handler = wrapHandler(handler, name, 'unary');
285
+ }
286
+ }
287
+ return register.call(this, name, handler, serialize, deserialize, type);
288
+ };
289
+ }
290
+
291
+ function endTransaction(ctx) {
292
+ try {
293
+ var profile = new ProfilePack();
294
+ var wtx = new TxRecord();
295
+ wtx.endTime = DateUtil.currentTime();
296
+ profile.time = wtx.endTime;
297
+ wtx.elapsed = ctx.getElapsedTime();
298
+
299
+ DataTextAgent.SERVICE.add(ctx.service_hash, ctx.service_name);
300
+
301
+ wtx.seq = ctx.txid;
302
+ wtx.service = ctx.service_hash;
303
+ wtx.cpuTime = ResourceProfile.getCPUTime() - ctx.start_cpu;
304
+ wtx.malloc = ResourceProfile.getUsedHeapSize() - ctx.start_malloc;
305
+ if (wtx.malloc < 0) { wtx.malloc = 0; }
306
+ wtx.status = 2;
307
+ wtx.http_method = ctx.grpc_method;
308
+
309
+ wtx.ipaddr = ctx.remoteIp;
310
+
311
+ MeterService.add(wtx.service, wtx.elapsed,
312
+ wtx.errorLevel, ctx.mcaller_pcode, ctx.mcaller_okind, ctx.mcaller_oid);
313
+
314
+ profile.oid = SecurityMaster.OID;
315
+ profile.service = wtx;
316
+
317
+ TraceContextManager.end(ctx._id);
318
+
319
+ setTimeout(function() {
320
+ DataProfileAgent.sendProfile(ctx, profile, false);
321
+ ctx = null;
322
+ }, 100);
323
+ } catch (e) {
324
+ Logger.printError('WHATAP-615', 'Websocket end transaction error..', e, false);
325
+ TraceContextManager.end(ctx._id);
326
+ ctx = null;
327
+ }
328
+ };
329
+
330
+ function initCtx() {
331
+ const ctx = TraceContextManager.start();
332
+ if (!ctx) { return; }
333
+
334
+ ctx.start_malloc = ResourceProfile.getUsedHeapSize();
335
+ ctx.start_cpu = ResourceProfile.getCPUTime();
336
+ return ctx;
337
+ }
338
+
339
+ exports.GRpcObserver = GRpcObserver;
@@ -59,8 +59,8 @@ var httpc_not_found_ignore_time = conf.getProperty('httpc_not_found_ignore_time'
59
59
  var profile_http_header_ignore_keys = conf.getProperty('profile_http_header_ignore_keys', 'Cookie,cookie,accept,user-agent,referer');
60
60
  var profile_http_parameter_enabled = conf.getProperty('profile_http_parameter_enabled', true);
61
61
  var profile_http_parameter_keys = conf.getProperty('profile_http_parameter_keys', '');
62
- var ignore_nextjs_build_file_enabled = conf.getProperty('ignore_nextjs_build_file_enabled', true);
63
- var ignore_nextjs_build_file_path = conf.getProperty('ignore_nextjs_build_file_path', '/_next/');
62
+ var ignore_build_file_enabled = conf.getProperty('ignore_build_file_enabled', true);
63
+ var ignore_build_file_path = conf.getProperty('ignore_build_file_path', '/_next/');
64
64
  conf.on('trace_http_client_ip_header_key', function(newProperty) {
65
65
  configIpHeaderKey = newProperty;
66
66
  });
@@ -118,11 +118,11 @@ conf.on('profile_http_parameter_enabled', function (newProps) {
118
118
  conf.on('profile_http_parameter_keys', function (newProps) {
119
119
  profile_http_parameter_keys = newProps;
120
120
  })
121
- conf.on('ignore_nextjs_build_file_enabled', function (newProps) {
122
- ignore_nextjs_build_file_enabled = newProps;
121
+ conf.on('ignore_build_file_enabled', function (newProps) {
122
+ ignore_build_file_enabled = newProps;
123
123
  })
124
- conf.on('ignore_nextjs_build_file_path', function (newProps) {
125
- ignore_nextjs_build_file_path = newProps;
124
+ conf.on('ignore_build_file_path', function (newProps) {
125
+ ignore_build_file_path = newProps;
126
126
  })
127
127
  var staticConents = function (newProps) {
128
128
  var x=new Set();
@@ -241,7 +241,7 @@ function initCtx(req, res) {
241
241
  /*url이 없으면 추적하지 않는다*/
242
242
  if(!req.url) { return null; }
243
243
  if(ignore_http_method && ignore_http_method.toUpperCase().split(',').includes(req.method)) { return null; }
244
- if (ignore_nextjs_build_file_enabled && ignore_nextjs_build_file_path && ignore_nextjs_build_file_path.split(',').some(path => req.url.startsWith(path))) {
244
+ if (ignore_build_file_enabled && ignore_build_file_path && ignore_build_file_path.split(',').some(path => req.url.startsWith(path))) {
245
245
  return null;
246
246
  }
247
247
 
@@ -4,23 +4,72 @@
4
4
  * can be found in the LICENSE file.
5
5
  */
6
6
 
7
- var TraceContextManager = require('../trace/trace-context-manager');
7
+ const TraceContextManager = require('../trace/trace-context-manager');
8
+ const conf = require('../conf/configure');
9
+ const LogTracer = require('../logsink/log-tracer');
8
10
 
9
- var ProcessObserver = function (agent) {
11
+ let logsink_enabled = conf.getProperty('logsink_enabled', false);
12
+ let logTracer = logsink_enabled ? new LogTracer() : null;
13
+
14
+ conf.on('logsink_enabled', function(newProperty) {
15
+ logsink_enabled = newProperty;
16
+ logTracer = logsink_enabled ? new LogTracer() : null;
17
+ });
18
+
19
+ const ProcessObserver = function (agent) {
10
20
  this.agent = agent;
11
21
  this.packages = ['process'];
12
22
  };
23
+
13
24
  ProcessObserver.prototype.inject = function (mod, moduleName) {
14
- var self = this;
15
- self.agent.aop.before(mod, 'nextTick', function (obj, args) {
16
- var cached_id = TraceContextManager.getCurrentId();
17
- self.agent.aop.functionHook(args, -1, function (obj, args) {
18
- if(cached_id != null) {
25
+ this._hookNextTick(mod);
26
+ this._hookStdOutWrite();
27
+ this._hookStdErrWrite();
28
+ };
29
+
30
+ ProcessObserver.prototype._hookNextTick = function (mod) {
31
+ this.agent.aop.before(mod, 'nextTick', (obj, args) => {
32
+ const cached_id = TraceContextManager.getCurrentId();
33
+ this.agent.aop.functionHook(args, -1, (obj, args) => {
34
+ if (cached_id != null) {
19
35
  TraceContextManager.resume(cached_id);
20
- cached_id = null;
21
36
  }
22
37
  });
23
38
  });
24
39
  };
25
40
 
41
+ ProcessObserver.prototype._hookStdOutWrite = function () {
42
+ this.agent.aop.after(process.stdout, 'write', (obj, args) => {
43
+ if (conf.getProperty('logsink_enabled', false) && args[0]) {
44
+ return;
45
+ let content = typeof args[0] === 'string' ? args[0] : (args[0].message || '');
46
+ try {
47
+ const parsedContent = JSON.parse(content);
48
+ content = parsedContent.message ? parsedContent.message : JSON.stringify(parsedContent);
49
+ } catch (e) {
50
+ }
51
+ if (logTracer && content) {
52
+ logTracer.addStdWrite(content, conf.logsink_category_stdout);
53
+ }
54
+ }
55
+ });
56
+ };
57
+
58
+ ProcessObserver.prototype._hookStdErrWrite = function () {
59
+ this.agent.aop.after(process.stderr, 'write', (obj, args) => {
60
+ if (conf.getProperty('logsink_enabled', false) && args[0]) {
61
+ return;
62
+ let content = typeof args[0] === 'string' ? args[0] : (args[0].message || '');
63
+ try {
64
+ const parsedContent = JSON.parse(content);
65
+ content = parsedContent.message ? parsedContent.message : JSON.stringify(parsedContent);
66
+ } catch (e) {
67
+ }
68
+ if (logTracer && content) {
69
+ logTracer.addStdWrite(content, conf.logsink_category_stderr);
70
+ }
71
+ }
72
+ });
73
+ };
74
+
26
75
  module.exports.ProcessObserver = ProcessObserver;
@@ -6,12 +6,12 @@ var TraceContextManager = require('../trace/trace-context-manager'),
6
6
  HashUtil = require('../util/hashutil'),
7
7
  Long = require('long'),
8
8
  Logger = require('../logger');
9
-
9
+ const shimmer = require('../core/shimmer');
10
10
 
11
11
  var RedisObserver = function (agent) {
12
12
  this.agent = agent;
13
13
  this.aop = agent.aop;
14
- this.packages = ['redis'];
14
+ this.packages = ['redis', 'ioredis'];
15
15
  };
16
16
 
17
17
  RedisObserver.prototype.inject = function (mod, modName) {
@@ -23,13 +23,13 @@ RedisObserver.prototype.inject = function (mod, modName) {
23
23
  Logger.initPrint("RedisObserver");
24
24
  var self = this;
25
25
 
26
- var dbc_hash= 0;
26
+ var dbc_hash = 0;
27
27
  var dbc;
28
28
  var dbc_time;
29
29
  self.aop.both(mod, 'createClient',
30
30
  function (obj, args, lctx) {
31
- if(dbc_hash === 0){
32
- if(args.length > 0) {
31
+ if (dbc_hash === 0) {
32
+ if (args.length > 0) {
33
33
  var info = (args[0] || {});
34
34
  dbc = 'redis://';
35
35
  dbc += info.host || '';
@@ -43,13 +43,15 @@ RedisObserver.prototype.inject = function (mod, modName) {
43
43
  var selectCommand = new Set(['get', 'hGet', 'hmGet']);
44
44
  var insertCommand = new Set(['set', 'hSet', 'hset', 'hmSet', 'hmset', 'zAdd', 'zadd', 'lSet', 'lset']);
45
45
  var updateCommand = new Set(['set', 'lSet', 'lset', 'hSet', 'hset', 'zAdd', 'zadd']);
46
- var deleteCommand = new Set(['del', 'lRem', 'sRem', 'srem', 'hDel', 'hdel', 'zRem', 'zrem']);
46
+ var deleteCommand = new Set(['del', 'lRem', 'sRem', 'srem', 'hDel', 'hdel', 'zRem', 'zrem']);
47
47
  var commands = new Set([...selectCommand, ...insertCommand, ...updateCommand, ...deleteCommand]);
48
48
  commands.forEach(function (command) {
49
49
  self.aop.after(ret, command,
50
50
  function (obj, args, ret, lctx) {
51
51
  var ctx = TraceContextManager.getCurrentContext();
52
- if(ctx == null) {return;}
52
+ if (ctx == null) {
53
+ return;
54
+ }
53
55
 
54
56
  var dbc_step = new DBCStep();
55
57
  dbc_step.hash = dbc_hash;
@@ -62,18 +64,18 @@ RedisObserver.prototype.inject = function (mod, modName) {
62
64
  sql_step = new SqlStepX();
63
65
  const key = args[0];
64
66
  const values = [];
65
- for(let i = 1; i < args.length; i++)
67
+ for (let i = 1; i < args.length; i++)
66
68
  values.push(args[i]);
67
69
 
68
70
  var sql = 'Redis ' + command + ': ' + JSON.stringify([key]);
69
- if(values.length > 0)
70
- sql += ' ' + JSON.stringify(values);
71
+ // if (values.length > 0)
72
+ // sql += ' ' + JSON.stringify(values);
71
73
  sql_step.hash = HashUtil.hashFromString(sql);
72
74
  sql_step.start_time = ctx.getElapsedTime();
73
75
  //sql_step.crud = 'I'.charCodeAt(0);
74
76
  // DataTextAgent.SQL.add(sql_step.hash, sql);
75
77
  ctx.profile.push(sql_step);
76
- } catch(e) {
78
+ } catch (e) {
77
79
  Logger.printError("WHATAP-605", "Redis CRUD error", e, false);
78
80
  sql_step = null;
79
81
  }
@@ -152,6 +154,62 @@ RedisObserver.prototype.inject = function (mod, modName) {
152
154
  // }
153
155
  });
154
156
  });
157
+
158
+ var ioredis_dbc_hash = 0;
159
+ var ioredis_dbc;
160
+ self.aop.both(mod.prototype, 'sendCommand', function (obj, args, lctx) {
161
+ if (ioredis_dbc_hash === 0) {
162
+ if (obj && Object.keys(obj.options).length > 0) {
163
+ var info = obj.options
164
+ ioredis_dbc = 'redis://';
165
+ ioredis_dbc += info.host || '';
166
+ ioredis_dbc += ':';
167
+ ioredis_dbc += info.port || '';
168
+ ioredis_dbc_hash = HashUtil.hashFromString(ioredis_dbc);
169
+ }
170
+ }
171
+ }, function (obj, args, ret, lctx) {
172
+ var selectCommand = new Set(['get', 'hget', 'hmget', 'zrange', 'smembers', 'lrange']);
173
+ var insertCommand = new Set(['set', 'hset', 'hmset', 'zadd', 'lset', 'sadd', 'lpush', 'rpush']);
174
+ var updateCommand = new Set(['set', 'lset', 'hset', 'zadd']);
175
+ var deleteCommand = new Set(['del', 'lrem', 'srem', 'hdel', 'zrem']);
176
+ var commands = new Set([...selectCommand, ...insertCommand, ...updateCommand, ...deleteCommand]);
177
+
178
+ if(!args[0] || (args[0] && !args[0].name)){
179
+ return;
180
+ }
181
+ var command = args[0].name;
182
+ if(commands.has(command.toLowerCase())){
183
+ var ctx = TraceContextManager.getCurrentContext();
184
+ if (ctx == null) {
185
+ return;
186
+ }
187
+
188
+ var dbc_step = new DBCStep();
189
+ dbc_step.hash = ioredis_dbc_hash;
190
+ dbc_step.start_time = ctx.getElapsedTime();
191
+ DataTextAgent.DBC.add(ioredis_dbc_hash, ioredis_dbc);
192
+ ctx.profile.push(dbc_step);
193
+
194
+ var sql_step;
195
+ var args = args[0].args;
196
+ try {
197
+ sql_step = new SqlStepX();
198
+ let key = args[0];
199
+ if(typeof key === 'string')
200
+ key = [key];
201
+
202
+ var sql = 'Redis ' + command + ': ' + JSON.stringify(key);
203
+ sql_step.hash = HashUtil.hashFromString(sql);
204
+ sql_step.start_time = ctx.getElapsedTime();
205
+ DataTextAgent.SQL.add(sql_step.hash, sql);
206
+ ctx.profile.push(sql_step);
207
+ } catch (e) {
208
+ Logger.printError("WHATAP-605", "Redis CRUD error", e, false);
209
+ sql_step = null;
210
+ }
211
+ }
212
+ })
155
213
  };
156
214
 
157
215
  exports.RedisObserver = RedisObserver;
@@ -24,7 +24,7 @@ const MeterUsers = require("whatap/lib/counter/meter/meter-users");
24
24
  const DataPackSender = require("whatap/lib/data/datapack-sender");
25
25
  const MeterService = require('../counter/meter/meter-service').MeterService;
26
26
 
27
- var trace_background_socket_enabled = conf.getProperty('trace_background_socket_enabled', false);
27
+ var trace_background_socket_enabled = conf.getProperty('trace_background_socket_enabled', true);
28
28
  conf.on('trace_background_socket_enabled', function (newProps) {
29
29
  trace_background_socket_enabled = newProps;
30
30
  })
@@ -27,7 +27,7 @@ EventPack.prototype.write = function(dout) {
27
27
  dout.writeText(this.message);
28
28
  dout.writeByte(Object.keys(this.attr).length);
29
29
 
30
- for(key in this.attr) {
30
+ for(var key in this.attr) {
31
31
  dout.writeText(key);
32
32
  dout.writeText(this.attr[key]);
33
33
  }