whatap 0.4.89 → 0.4.91

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.
@@ -137,6 +137,8 @@ var ConfigDefault = {
137
137
  "status_ignore_set": str('status_ignore_set', ''),
138
138
  "httpc_status_ignore_set": str('httpc_status_ignore_set', ''),
139
139
  "trace_sql_normalize_enabled" : true,
140
+ "httpc_not_found_ignore": bool('httpc_not_found_ignore', false),
141
+ "httpc_not_found_ignore_time": num('httpc_not_found_ignore', 300000),
140
142
 
141
143
  //2017.05.02 AUTO ONAME
142
144
  "auto_oname_enabled" : bool('auto_oname_enabled',false),
@@ -35,7 +35,8 @@ var TraceContextManager = require('../trace/trace-context-manager'),
35
35
  PluginLoaderManager = require('../plugin/plugin-loadermanager'),
36
36
  Long = require('long'),
37
37
  KeyGen = require('../util/keygen'),
38
- Logger = require('../logger');
38
+ Logger = require('../logger'),
39
+ IntKeyLinkedMap = require("../util/intkey-linkedmap");
39
40
 
40
41
  var _exts=new Set([".css",".js",".png", ".htm", ".html", ".gif", ".jpg", ".css", ".txt", ".ico"]);
41
42
 
@@ -50,6 +51,8 @@ var httpc_status_ignore = conf.getProperty('httpc_status_ignore', '');
50
51
  var status_ignore_set = conf.getProperty('status_ignore_set', '');
51
52
  var httpc_status_ignore_set = conf.getProperty('httpc_status_ignore_set', '');
52
53
  var profile_error_step_enabled = conf.getProperty('profile_error_step_enabled', '');
54
+ var httpc_not_found_ignore = conf.getProperty('httpc_not_found_ignore', false);
55
+ var httpc_not_found_ignore_time = conf.getProperty('httpc_not_found_ignore_time', 300000);
53
56
  conf.on('trace_http_client_ip_header_key', function(newProperty) {
54
57
  configIpHeaderKey = newProperty;
55
58
  });
@@ -92,6 +95,12 @@ conf.on('httpc_status_ignore_set', function (newProps) {
92
95
  conf.on('profile_error_step_enabled', function (newProps) {
93
96
  profile_error_step_enabled = newProps;
94
97
  })
98
+ conf.on('httpc_not_found_ignore', function (newProps) {
99
+ httpc_not_found_ignore = newProps;
100
+ })
101
+ conf.on('httpc_not_found_ignore_time', function (newProps) {
102
+ httpc_not_found_ignore_time = newProps;
103
+ })
95
104
  var staticConents = function (newProps) {
96
105
  var x=new Set();
97
106
  var words = !newProps?[]:newProps.split(',');
@@ -111,6 +120,9 @@ var staticConents = function (newProps) {
111
120
  conf.on('web_static_content_extensions', staticConents);
112
121
  staticConents(conf["web_static_content_extensions"]);
113
122
 
123
+ var httpc_not_found_ignore_map = null;
124
+ var httpc_not_found_ignore_url = [];
125
+
114
126
  var HttpObserver = function(agent){
115
127
  this.agent = agent;
116
128
  this.packages = ['http','https'];
@@ -144,6 +156,17 @@ HttpObserver.prototype.__createTransactionObserver = function(callback, isHttps,
144
156
  if(ctx == null) { return; }
145
157
  PluginLoaderManager.do('httpserviceend', ctx, req, res);
146
158
 
159
+ var not_found_ignore = httpc_not_found_ignore_url.includes(req.url);
160
+ if (httpc_not_found_ignore && !not_found_ignore && obj.statusCode === 404) {
161
+ const url_hash = HashUtil.hashFromString(req.url);
162
+ const currentTime = new Date().getTime();
163
+
164
+ if (!httpc_not_found_ignore_map) {
165
+ httpc_not_found_ignore_map = new IntKeyLinkedMap(500, 1).setMax(500);
166
+ }
167
+ updateNotFoundIgnoreMap(req.url, url_hash, currentTime);
168
+ }
169
+
147
170
  ctx.isStaticContents = isStatic(req.url);
148
171
  ctx.http_method = req.method;
149
172
  if(conf.profile_http_querystring_enabled){
@@ -163,16 +186,11 @@ HttpObserver.prototype.__createTransactionObserver = function(callback, isHttps,
163
186
  var requestPath = '';
164
187
  if(req.route && req.route.path)
165
188
  requestPath = req.route.path;
166
- var is_ignore;
167
- if(ctx.is_httpc_error){
168
- is_ignore = shouldIgnoreError(res.statusCode, requestPath, httpc_status_ignore, httpc_status_ignore_set);
169
- } else {
170
- is_ignore = shouldIgnoreError(res.statusCode, requestPath, status_ignore, status_ignore_set);
171
- }
172
189
 
173
- if(!is_ignore)
190
+ var shouldEndTransaction = shouldEndCurrentTransaction(not_found_ignore, ctx, res, req.route ? req.route.path : '');
191
+ if (shouldEndTransaction) {
174
192
  self.__endTransaction(null, ctx, req, res);
175
- else{
193
+ } else {
176
194
  TraceContextManager.end(ctx._id);
177
195
  ctx = null;
178
196
  }
@@ -792,4 +810,33 @@ function shouldIgnoreError(statusCode, url, statusCodeIgnore, statusIgnoreSet) {
792
810
  return false;
793
811
  }
794
812
 
813
+ function updateNotFoundIgnoreMap(url, url_hash, currentTime) {
814
+ var ignore_value = httpc_not_found_ignore_map.get(url_hash) || {
815
+ count: 0, start_time: currentTime, last_time: currentTime, url: url
816
+ };
817
+
818
+ ignore_value.count++;
819
+ ignore_value.last_time = currentTime;
820
+
821
+ if ((ignore_value.last_time - ignore_value.start_time) > httpc_not_found_ignore_time) {
822
+ ignore_value = { count: 1, start_time: currentTime, last_time: currentTime, url: url };
823
+ }
824
+
825
+ if (ignore_value.count >= 50) {
826
+ httpc_not_found_ignore_url.push(url);
827
+ httpc_not_found_ignore_map.remove(url_hash);
828
+ Logger.print('WHATAP-610', "The ignore option for URL " + url + " is applied.", false);
829
+ }
830
+
831
+ httpc_not_found_ignore_map.put(url_hash, ignore_value);
832
+ }
833
+
834
+ function shouldEndCurrentTransaction(not_found_ignore, ctx, res, requestPath) {
835
+ if (not_found_ignore) return false;
836
+ var is_ignore = ctx.is_httpc_error ?
837
+ shouldIgnoreError(res.statusCode, requestPath, httpc_status_ignore, httpc_status_ignore_set) :
838
+ shouldIgnoreError(res.statusCode, requestPath, status_ignore, status_ignore_set);
839
+ return !is_ignore;
840
+ }
841
+
795
842
  exports.HttpObserver = HttpObserver;
@@ -3,81 +3,157 @@ var TraceContextManager = require('../trace/trace-context-manager'),
3
3
  SqlStepX = require('../step/sql-stepx'),
4
4
  DataTextAgent = require('../data/datatext-agent'),
5
5
  HashUtil = require('../util/hashutil');
6
+ const DBCStep = require("whatap/lib/step/dbc-step");
7
+ const Logger = require("whatap/lib/logger");
6
8
 
7
9
  var MongooseObserver = function (agent) {
8
10
  this.agent = agent;
9
11
  this.packages = ['mongoose'];
10
12
  };
11
13
 
14
+ var dbc_step, dbc, conn_dbc_hash;
12
15
  MongooseObserver.prototype.inject = function (mod, modName) {
13
16
 
14
17
  var self = this;
15
-
16
18
  var hookCommand = [
17
- 'find',
18
- 'remove',
19
- 'findById',
20
- 'findOne',
21
- 'count',
22
- 'distinct',
23
- 'findOneAndUpdate',
24
- 'findByIdAndUpdate',
25
- 'findOneAndRemove',
26
- 'findByIdAndRemove',
27
- 'create',
28
- 'insertMany',
29
- 'update',
30
- 'updateMany',
31
- 'updateOne',
32
- 'mapReduce',
33
- 'geoNear',
34
- 'geoSearch',
35
- 'populate'
19
+ "create", // Create: Create a new document
20
+ "insertMany", // Create: Create multiple documents at once
21
+ "find", // Read: Find documents that match criteria
22
+ "findById", // Read: Find a document by its ID
23
+ "findOne", // Read: Find the first document that matches criteria
24
+ "countDocuments", // Read: Count the number of documents that match criteria
25
+ "distinct", // Read: Find distinct values for a given field
26
+ "updateMany", // Update: Update multiple documents that match criteria
27
+ "updateOne", // Update: Update a single document that matches criteria
28
+ "replaceOne", // Update: Replace one document with another
29
+ "findOneAndUpdate", // Update: Find the first document that matches criteria and update it
30
+ "findByIdAndUpdate", // Update: Find a document by its ID and update it
31
+ "deleteOne", // Delete: Delete a single document that matches criteria
32
+ "deleteMany", // Delete: Delete multiple documents that match criteria
33
+ "findOneAndDelete", // Delete: Find the first document that matches criteria and delete it
34
+ "findByIdAndDelete" // Delete: Find a document by its ID and delete it
36
35
  ];
37
36
 
38
- self.agent.aop.before(mod.Model, 'aggregate', function (obj, args) {
39
- var ctx = TraceContextManager.getCurrentContext();
40
- if(ctx == null) {return;}
37
+ self.agent.aop.after(mod, ['connect'] ,function (obj, args, ret) {
38
+ if(!args[0]) { return; }
39
+ if(dbc) { return; }
40
+ dbc = args[0];
41
+ conn_dbc_hash = HashUtil.hashFromString(dbc);
42
+
43
+ ret.then(data => {
44
+ self.agent.aop.both(data.Model, 'aggregate', function (_obj, _args, _lctx) {
45
+ var ctx = TraceContextManager.getCurrentContext();
46
+ if(!ctx) {return;}
47
+
48
+ if(dbc && conn_dbc_hash){
49
+ DataTextAgent.DBC.add(conn_dbc_hash, dbc);
50
+ DataTextAgent.METHOD.add(conn_dbc_hash, dbc);
51
+ DataTextAgent.ERROR.add(conn_dbc_hash, dbc);
52
+ }
53
+
54
+ var dbc_step = new DBCStep();
55
+ dbc_step.hash = conn_dbc_hash;
56
+ dbc_step.start_time = ctx.getElapsedTime();
57
+
58
+ _lctx.dbc_step = dbc_step;
59
+
60
+ var sql_step = new SqlStepX();
61
+ sql_step.start_time = ctx.getElapsedTime();
62
+ _lctx.sql_step = sql_step;
63
+ }, function (_obj, _args, _ret, _lctx) {
64
+ var ctx = _lctx.context;
65
+ var dbc_step = _lctx.dbc_step;
66
+ var sql_step = _lctx.sql_step;
67
+ if(!ctx || !dbc_step || !sql_step) {return null;}
68
+
69
+ dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
70
+ ctx.profile.push(dbc_step);
71
+
72
+ ctx.footprint('Mongodb Command Start: ' + _ret.op );
41
73
 
42
- var param = "";
43
- if(Array.isArray(args[0])) {
44
- args[0].forEach(function (val, i) {
45
- if(i > 0 && param.length > 0) {
46
- param += ",";
74
+ const mongooseCollection = _ret._model;
75
+ try {
76
+ var sql = mongooseCollection.modelName + ' aggregate';
77
+ var param = "";
78
+ if(Array.isArray(_args[0])) {
79
+ _args[0].forEach(function (val, i) {
80
+ if(i > 0 && param.length > 0) {
81
+ param += ",";
82
+ }
83
+ if(val.hasOwnProperty('$match')) {
84
+ var keys = Object.keys(val['$match']);
85
+ param += keys;
86
+ }
87
+
88
+ if(val.hasOwnProperty('$group')) {
89
+ var keys = Object.keys(val['$group']);
90
+ param += keys;
91
+ }
92
+ })
93
+ }
94
+ sql += ' field=['+param+']';
95
+
96
+ sql_step.hash = HashUtil.hashFromString(sql);
97
+ sql_step.start_time = ctx.getElapsedTime();
98
+ sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
99
+ DataTextAgent.SQL.add(sql_step.hash, sql);
100
+ ctx.profile.push(sql_step);
101
+ } catch(e) {
102
+ Logger.printError("WHATAP-611", "Mongodb query error", e, false);
103
+ sql_step = null;
47
104
  }
48
- if(val.hasOwnProperty('$match')) {
49
- var keys = Object.keys(val['$match']);
50
- param += keys;
105
+ });
106
+
107
+ self.agent.aop.both(data.Model, hookCommand, function (_obj, _args, _lctx) {
108
+ if(_args[0] && typeof _args[0] !== "object") { return; }
109
+ const ctx = TraceContextManager.getCurrentContext();
110
+ if(!ctx) { return; }
111
+ if(dbc && conn_dbc_hash){
112
+ DataTextAgent.DBC.add(conn_dbc_hash, dbc);
113
+ DataTextAgent.METHOD.add(conn_dbc_hash, dbc);
114
+ DataTextAgent.ERROR.add(conn_dbc_hash, dbc);
51
115
  }
52
116
 
53
- if(val.hasOwnProperty('$group')) {
54
- var keys = Object.keys(val['$group']);
55
- param += keys;
117
+ var dbc_step = new DBCStep();
118
+ dbc_step.hash = conn_dbc_hash;
119
+ dbc_step.start_time = ctx.getElapsedTime();
120
+
121
+ _lctx.dbc_step = dbc_step;
122
+
123
+ var sql_step = new SqlStepX();
124
+ sql_step.start_time = ctx.getElapsedTime();
125
+ _lctx.sql_step = sql_step;
126
+ }, function (_obj, _args, _ret, _lctx) {
127
+ var ctx = _lctx.context;
128
+ var dbc_step = _lctx.dbc_step;
129
+ var sql_step = _lctx.sql_step;
130
+ if(!ctx || !dbc_step || !sql_step) {return null;}
131
+
132
+ dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
133
+ ctx.profile.push(dbc_step);
134
+
135
+ ctx.footprint('Mongodb Command Start: ' + _ret.op );
136
+
137
+ const mongooseCollection = _ret.mongooseCollection;
138
+ try {
139
+ var sql = mongooseCollection.modelName + ' ' + _ret.op ;//+ ': ' + JSON.stringify(Object.keys(args[0]));
140
+ if(_args[0]) { sql += ' field=' + JSON.stringify(Object.keys(_args[0])); }
141
+ if(_args[1]) { sql += ' value=' + JSON.stringify(Object.keys(_args[1])); }
142
+
143
+ sql_step.hash = HashUtil.hashFromString(sql);
144
+ sql_step.start_time = ctx.getElapsedTime();
145
+ sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
146
+ DataTextAgent.SQL.add(sql_step.hash, sql);
147
+ ctx.profile.push(sql_step);
148
+ } catch(e) {
149
+ Logger.printError("WHATAP-611", "Mongodb query error", e, false);
150
+ sql_step = null;
56
151
  }
57
152
  })
58
- }
59
-
60
- var sql_step = new SqlStepX();
61
- var sql = 'mongodb aggregate (' + param + ')';
62
- sql_step.hash = HashUtil.hashFromString(sql);
63
- sql_step.start_time = ctx.getElapsedTime();
64
- sql_step.dbc = 0;
65
-
66
- DataTextAgent.SQL.add(sql_step.hash, sql);
67
- ctx.profile.push(sql_step);
68
-
69
- self.agent.aop.functionHook(args, -1, function () {
70
- TraceContextManager.resume(ctx);
71
- sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
72
- });
73
- });
74
-
75
- self.agent.aop.before(mod.Model, hookCommand, function (obj, args) {
76
- var ctx_id = TraceContextManager.getCurrentId();
77
- self.agent.aop.functionHook(args, -1, function () {
78
- TraceContextManager.resume(ctx_id);
79
- });
80
- });
153
+ }).catch(e => {
154
+ Logger.printError("WHATAP-612", "Mongodb connection error", e, false);
155
+ })
156
+ })
81
157
 
82
158
  };
83
159
 
@@ -10,7 +10,6 @@ var TraceContextManager = require('../trace/trace-context-manager'),
10
10
  IPUtil = require('../util/iputil'),
11
11
  Logger = require('../logger');
12
12
 
13
-
14
13
  var NetObserver = function (agent) {
15
14
  this.agent = agent;
16
15
  this.packages = ['net', 'dgram'];
@@ -5,51 +5,136 @@
5
5
  */
6
6
 
7
7
  var MeterSocketio = require('../counter/meter/meter-socket.io'),
8
- Logger = require('../logger');
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;
9
23
 
10
24
  var SocketIOObserver = function(agent){
11
25
  this.agent = agent;
12
26
  this.packages = ['socket.io'];
13
27
  };
14
28
 
15
- SocketIOObserver.prototype.inject = function( mod ){
29
+ SocketIOObserver.prototype.inject = function (mod, moduleName) {
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
+
16
39
  var self = this;
17
40
  var aop = self.agent.aop;
18
41
 
19
- if(mod.__whatap_observe__) { return; }
20
- mod.__whatap_observe__ = true;
21
- Logger.initPrint("SocketIOObserver");
22
- aop.after(mod.prototype, ['listen','attach'], function(obj, args, ret) {
23
- if (!ret.sockets) return;
42
+ aop.before(mod.Server?.prototype, 'on', function (obj, args, ret, lctx) {
43
+ args[args.length-1] = self.__createTransactionObserver(args[args.length-1]);
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);
24
69
 
25
- aop.before(ret.sockets, ['on', 'addListener'], function(obj, args) {
26
- if (args[0] !== 'connection') return;
70
+ var step = new SocketStep();
71
+ step.start_time = ctx.getElapsedTime();
72
+ step.ipaddr = Buffer.from(IPUtil.stringToBytes(host));
73
+ // step.port = port;
27
74
 
28
- aop.functionHook(args, -1, function(obj, args) {
29
- if (!args[0]) return; //no client socket
75
+ ctx.socket_connecting = false;
76
+ step.elapsed = ctx.getElapsedTime() - step.start_time;
77
+ ctx.profile.push(step);
30
78
 
31
- var socket = args[0];
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);
107
+
108
+ profile.oid = SecurityMaster.OID;
109
+ profile.service = wtx;
110
+
111
+ TraceContextManager.end(ctx._id);
112
+ setTimeout(function () {
113
+ DataProfileAgent.sendProfile(ctx, profile, false);
114
+ ctx = null;
115
+ }, 100);
116
+
117
+ } catch (e) {
118
+ Logger.printError('WHATAP-607', 'End transaction error..', e, false);
119
+ TraceContextManager.end(ctx._id);
120
+ ctx = null;
121
+ }
122
+
123
+ };
32
124
 
33
- MeterSocketio.connected(1);
125
+ function initCtx() {
126
+ const ctx = TraceContextManager.start();
127
+ if (!ctx) {
128
+ return;
129
+ }
34
130
 
35
- socket.on('disconnect', function() {
36
- MeterSocketio.disconnected();
37
- });
131
+ ctx.start_malloc = ResourceProfile.getUsedHeapSize();
132
+ ctx.start_cpu = ResourceProfile.getCPUTime();
38
133
 
39
- aop.before(socket, ['emit', 'send'], function(obj, args) {
40
- if (args[0] === 'newListener') return;
41
- MeterSocketio.send(null, args);
42
- });
134
+ var remote_addr = IPUtil.checkIp4("0.0.0.0");
135
+ ctx.remoteIp = IPUtil.stringToInt(remote_addr);
43
136
 
44
- aop.before(socket, ['on', 'addListener'], function(obj, args) {
45
- if (args[0] === 'disconnect') return;
46
- aop.functionHook(args, -1, function (obj, args) {
47
- MeterSocketio.receive(null, args[0]);
48
- });
49
- });
50
- });
51
- });
52
- });
137
+ return ctx;
53
138
  }
54
139
 
55
140
  exports.SocketIOObserver = SocketIOObserver;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "whatap",
3
3
  "homepage": "http://www.whatap.io",
4
- "version": "0.4.89",
5
- "releaseDate": "20240122",
4
+ "version": "0.4.91",
5
+ "releaseDate": "20240205",
6
6
  "description": "Monitoring and Profiling Service",
7
7
  "main": "index.js",
8
8
  "scripts": {},