Skip to content

Commit 42419cd

Browse files
alexk-blackopsalexk-blackops
authored andcommitted
scheduled delay changed
1 parent a7ed9cc commit 42419cd

File tree

8 files changed

+125
-135
lines changed

8 files changed

+125
-135
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
node_modules
22
npm-debug.log
33
proxy.js
4-
proxy2.js
4+
proxy2.js
5+
new.js

config/config.js

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
module.exports = {
2-
'PROTOCOL' : 'https',
3-
'HOST': 'dev.stackify.com',
4-
'PORT': 443,
5-
'IDENTIFY_PATH': '/API/Metrics/IdentifyApp',
6-
'LOG_SAVE_PATH': '/API/Log/Save',
7-
'MSG_LIMIT': 100, // number of messages per batch
8-
'MSG_CAP': 10000, // overall messages cap in the queue
9-
'SCAN_TIMER': 30 * 1000,
10-
'REQUEST_TIMER': 5 * 1000,
11-
'REQUEST_ATTEMPTS': 5, // number of attempts if API call isn't succesful
12-
/**
13-
* Number of instances of a unique error that are allowed to be sent in one minute
14-
*/
15-
'MAX_DUP_ERROR_PER_MINUTE': 5,
2+
PROTOCOL : 'https',
3+
HOST : 'dev.stackify.com',
4+
PORT : 443,
5+
IDENTIFY_PATH : '/API/Metrics/IdentifyApp',
6+
LOG_SAVE_PATH : '/API/Log/Save',
7+
// possible delay values in millis
8+
DELAY: {
9+
ONE_SECOND_DELAY : 1000,
10+
FIVE_SECONDS_DELAY : 5000,
11+
ONE_MINUTE_DELAY : 60000,
12+
FIVE_MINUTES_DELAY : 300000,
13+
},
14+
MSG: {
15+
QUEUE_CAP : 10000, // overall messages cap in the queue
16+
// minimum and maximum batch sizes
17+
MIN_BATCH_SIZE : 10,
18+
MAX_BATCH_SIZE : 100,
19+
// Number of instances of a unique error that are allowed to be sent in one minute
20+
MAX_DUP_ERROR_PER_MINUTE: 5,
21+
},
22+
IDENTIFY_DELAY: 300000, // 5 minutes delay if identifyApp call failed
1623
/**
1724
* Cookie value
1825
*/
19-
'COOKIE_MASK': 'X-MASKED-X'
26+
COOKIE_MASK: 'X-MASKED-X'
2027
};

index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ module.exports = {
1010

1111
start: function(options) {
1212
api.methods.identifyApp(options);
13-
exc.exc();
14-
},
13+
/* exc.exc();
14+
*/ },
1515

1616
log: logger.methods.log,
1717
trace: logger.methods.trace,

lib/api.js

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ var os = require('os'),
88

99
pkginfo = require('pkginfo')(module, 'name'),
1010

11-
appname = module.exports.name, //name of the app from package.json
11+
appname = module.exports.name, // name of the app from package.json
12+
fail_delay = 0, // scheduled delay when postLogs call failed
13+
last_api_error,
1214

1315
//getting all the headers for requests
1416
options = function options(path, body, proxy) {
@@ -32,7 +34,7 @@ var os = require('os'),
3234
return result;
3335

3436
};
35-
37+
module.exports.last_api_error = last_api_error;
3638
module.exports.methods = {
3739

3840
identifyApp: function identifyApp(settings) {
@@ -43,23 +45,19 @@ module.exports.methods = {
4345
AppLocaton: process.env.PWD
4446
},
4547
opt = options(CONFIG.IDENTIFY_PATH, body, settings ? settings.proxy : undefined),
46-
fail_counter = 0,
4748
callback = function (data) {
4849
console.log('successfully identified');
4950

5051
CONFIG.APP_DETAILS = data;
5152
CONFIG.APIKEY = settings.apiKey;
5253

53-
logger.methods.init();
54+
logger.methods.send();
5455

5556
},
5657
fail = function () {
57-
fail_counter += 1;
58-
if (fail_counter <= CONFIG.REQUEST_ATTEMPTS) {
59-
setTimeout(function () {
60-
send(opt, callback, fail);
61-
}, CONFIG.REQUEST_TIMER);
62-
}
58+
setTimeout(function () {
59+
send(opt, callback, fail);
60+
}, CONFIG.IDENTIFY_DELAY);
6361
};
6462

6563
console.log('Identifying...');
@@ -80,7 +78,7 @@ module.exports.methods = {
8078

8179
},
8280

83-
postLogs: function postLogs(messages, cb, fail) {
81+
postLogs: function postLogs(messages, cb) {
8482
var body = {
8583
CDID: CONFIG.APP_DETAILS.DeviceID,
8684
CDAppID: CONFIG.APP_DETAILS.DeviceAppID,
@@ -95,7 +93,26 @@ module.exports.methods = {
9593
Platform: 'Node.js',
9694
Msgs : messages
9795
},
98-
opt = options(CONFIG.LOG_SAVE_PATH, body, CONFIG.PROXY);
96+
opt = options(CONFIG.LOG_SAVE_PATH, body, CONFIG.PROXY),
97+
98+
//retry the request if it failed
99+
fail = function(code) {
100+
var sinceFirstError;
101+
102+
if (code === 401) {
103+
fail_delay = CONFIG.DELAY.FIVE_MINUTES;
104+
last_api_error = new Date().getTime();
105+
} else {
106+
last_api_error = last_api_error || new Date().getTime();
107+
sinceFirstError = new Date().getTime() - last_api_error;
108+
fail_delay = Math.min(Math.max(sinceFirstError, CONFIG.DELAY.ONE_SECOND), CONFIG.DELAY.ONE_MINUTE);
109+
}
110+
111+
setTimeout(function () {
112+
send(opt, cb, fail);
113+
}, fail_delay);
114+
115+
};
99116

100117
send(opt, cb, fail);
101118
}

lib/exception.js

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,11 @@ var qs = require('querystring'),
99

1010
// function that sends all the messages in the queue to Stackify when exception is caught
1111
handler = function handler(err, req, cb) {
12-
var rec = {
13-
Msg: err.name + ': ' + err.message,
14-
Level: 'ERROR',
15-
EpochMs: Date.now(),
16-
Ex: error.formatEx(err, req)
17-
},
18-
fail_counter = 0,
19-
20-
cb = function () {
21-
console.log('sent', util.inspect(logger.storage, {depth: null}));
22-
}
23-
24-
//retry the request if it failed
25-
fail = function () {
26-
fail_counter += 1;
27-
if (fail_counter < CONFIG.REQUEST_ATTEMPTS) {
28-
setTimeout(function () {
29-
api.methods.postLogs(logger.storage, null, fail);
30-
}, CONFIG.REQUEST_TIMER);
31-
}
32-
};
33-
34-
if (CONFIG.APP_DETAILS) {
35-
console.log('handled');
36-
logger.storage.push(rec);
37-
api.methods.postLogs(logger.storage, cb, fail);
38-
} else {
39-
console.log('not identified yet');
40-
}
12+
logger.methods.push('error', err.message, {error: error}, req);
13+
api.methods.postLogs(logger.storage, cb);
4114
};
4215

43-
// flag used for not catching the same exception twice (inside and outside of the createServer method)
16+
// flag used to prevent catching the same exception twice (inside and outside of the createServer method)
4417
module.exports.excCaught = excCaught = false;
4518

4619
module.exports = {

lib/logger.js

Lines changed: 44 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -7,71 +7,60 @@ var util = require('util'),
77

88
storage = [],
99

10-
// flag that indicates if logs are being sent right now. if false then new batches of messages won't be sent.
11-
flag = false,
12-
// deferred checking of logs
13-
timeout = 0,
14-
//number of failed attempts of sending logs
15-
fail_counter = 0,
10+
// current delay
11+
delay = CONFIG.DELAY.ONE_SECOND_DELAY,
12+
1613
// hash that contains all the errors and their number logged during the current minute
1714
error_storage = {},
1815

19-
// automatically send all the messages from the queue after some timeout
20-
checkLogs = function () {
21-
var length = Math.min(storage.length, CONFIG.MSG_LIMIT);
22-
if (flag && length) {
23-
sendLogs(length);
24-
}
25-
console.log('logs checked');
26-
},
2716
// handler for sending logs
28-
sendLogs = function (length) {
29-
var self = this,
30-
data = storage.slice(0, length || CONFIG.MSG_LIMIT),
17+
sendLogs = function () {
18+
var length = storage.length,
19+
chunk = Math.min(length, CONFIG.MSG.MAX_BATCH_SIZE),
20+
data = storage.slice(0, chunk),
3121

32-
/* if request is succesful remove messages from the queue, change the timeout for the next checkLogs call,
33-
switch the flag, send another batch (if there are enough messages in the queue)
22+
/* if request is succesful remove messages from the queue,
23+
send another batch (if there are enough messages in the queue)
3424
*/
3525
success = function (response) {
36-
fail_counter = 0;
26+
storage = storage.slice(chunk); // remove this chunk from the queue
27+
length -= chunk;
28+
api.last_api_error = 0; // reset the last HTTP error
3729

38-
storage = storage.slice(length);
39-
console.log('logs sent');
30+
console.log(chunk, ' sent');
31+
console.log(length, ' last');
4032

41-
// if there are enough messages for the batch, send another request
33+
if (length) {
34+
chunk = Math.min(length, CONFIG.MSG.MAX_BATCH_SIZE);
35+
data = storage.slice(0, chunk);
4236

43-
if (storage.length >= CONFIG.MSG_LIMIT) {
44-
sendLogs();
37+
api.methods.postLogs(data, success);
4538
} else {
46-
flag = true;
47-
48-
// reset previous timeout, define the new one
49-
if (timeout) {
50-
clearTimeout(timeout);
51-
}
52-
53-
timeout = setTimeout(checkLogs, CONFIG.SCAN_TIMER);
39+
console.log('all sent');
40+
// full batch is sent, set timeout for the next request
41+
setTimeout(sendLogs, delay);
5442
}
55-
},
56-
57-
// retry the attempt after some timeout
58-
fail = function () {
59-
flag = false;
60-
fail_counter += 1;
61-
62-
setTimeout(function () {
63-
api.methods.postLogs(data, success, fail);
64-
}, CONFIG.REQUEST_TIMER);
6543
};
6644

67-
if (fail_counter <= CONFIG.REQUEST_ATTEMPTS) {
68-
api.methods.postLogs(data, success, fail);
69-
flag = false;
45+
// count the delay
46+
if (length >= CONFIG.MSG.MAX_BATCH_SIZE) {
47+
delay = Math.max(Math.round(delay / 2.0), CONFIG.DELAY.ONE_SECOND_DELAY);
48+
} else {
49+
delay = Math.min(Math.round(1.25 * delay), CONFIG.DELAY.FIVE_SECONDS_DELAY);
50+
}
51+
52+
if (data.length && CONFIG.APIKEY) {
53+
api.methods.postLogs(data, success);
54+
} else {
55+
console.log('no messages');
56+
console.log('delay ', delay);
57+
// queue is empty, set timeout for the next request
58+
setTimeout(sendLogs, delay);
7059
}
7160
},
7261
/**
73-
Check for duplicate error messages. If the same error message logged more than configurated limit in one minute
74-
don't push it to the queue
62+
* Check for duplicate error messages. If the same error message logged more than configurated limit in one minute
63+
* don't push it to the queue
7564
*/
7665
checkErrorLimitMessage = function checkErrorLimitMessage(ex) {
7766
var min = new Date().getMinutes(),
@@ -93,14 +82,14 @@ var util = require('util'),
9382
error_storage[min][key] = 1;
9483
}
9584

96-
return (error_storage[min][key] < CONFIG.MAX_DUP_ERROR_PER_MINUTE) ? true : false;
85+
return (error_storage[min][key] < CONFIG.MSG.MAX_DUP_ERROR_PER_MINUTE) ? true : false;
9786
};
9887

9988
module.exports.storage = storage;
10089

10190
module.exports.methods = {
10291
// create the message object, push it to the queue and execute sendLogs call if messages cap is exceeded
103-
push : function push(level, msg, meta) {
92+
push : function push(level, msg, meta, req) {
10493
var err = new Error(),
10594
getStack = error.getStackTraceItem(err),
10695
rec = {
@@ -117,7 +106,7 @@ module.exports.methods = {
117106
if (level.toLowerCase() === 'error') {
118107
data = helpers.parseMeta(meta, true);
119108
if (data.ex) {
120-
rec.Ex = error.formatEx(data.ex);
109+
rec.Ex = error.formatEx(data.ex, req);
121110
}
122111
} else {
123112
data = helpers.parseMeta(meta);
@@ -137,27 +126,16 @@ module.exports.methods = {
137126
console.log('logged', storage.length);
138127

139128
// remove the earliest message from the queue if message cap is exceeded
140-
if (storage.length === CONFIG.MSG_CAP) {
129+
if (storage.length === CONFIG.MSG.QUEUE_CAP) {
141130
storage.shift();
142131
}
143132
}
144-
145-
if (flag && storage.length >= CONFIG.MSG_LIMIT && CONFIG.APIKEY) {
146-
sendLogs();
147-
}
148133
},
149134

150-
/* check the queue after IdentifyApp call is done, switch the flag, set the timeout for the next checking the queue,
151-
set environment details for already logged messages
135+
/* check the queue after IdentifyApp call is done
152136
*/
153-
init: function init() {
154-
flag = true;
155-
156-
timeout = setTimeout(checkLogs, CONFIG.SCAN_TIMER);
157-
158-
if (storage.length >= CONFIG.MSG_LIMIT) {
159-
sendLogs(exc.excCaught ? storage.length : null);
160-
}
137+
send: function send() {
138+
setTimeout(sendLogs, delay);
161139
},
162140

163141
log: function log(level, msg, meta) {

lib/sender.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,25 @@ Low level function for sending http/https requests
77
var http = require('http'),
88
util = require('util'),
99

10-
request = require('request');
10+
request = require('request'),
11+
12+
logger = require('./logger');
1113

1214
module.exports = function sender(options, cb, fail) {
1315

1416
var callback = function (error, response, body) {
1517
if (!error) {
1618
if (response.statusCode === 200) {
1719
if (cb) {
18-
cb(body); }
20+
cb(body);
21+
}
1922
} else {
2023
if (fail) {
21-
fail();
24+
fail(response.statusCode);
2225
}
2326
}
2427
} else {
25-
console.log(error);
28+
logger.methods.push('error', error.message, {error: error});
2629
}
2730
};
2831

0 commit comments

Comments
 (0)