Skip to content

Commit bfbc804

Browse files
alexk-blackopsalexk-blackops
authored andcommitted
different fixes + first version of readme
1 parent 315f16d commit bfbc804

File tree

9 files changed

+188
-102
lines changed

9 files changed

+188
-102
lines changed

README.md

Lines changed: 93 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
##Stackify Log API for Node.js
1+
#Stackify Log API for Node.js
22

33
Errors and Logs Overview:
44

@@ -8,13 +8,102 @@ Sign Up for a Trial:
88

99
http://www.stackify.com/sign-up/
1010

11+
## Installation
12+
```bash
13+
$ npm install stackify-logger
14+
```
15+
1116
## Usage
1217

18+
```js
19+
var stackify = require(‘stackify-logger’);
20+
```
21+
Start sending the logs:
22+
```js
23+
// this should be executed only once in the app
24+
stackify.start(options);
25+
```
26+
The following options could be passed. 'apiKey' is the only one that required:
27+
* __apiKey:__ client license key.
28+
* __env:__ environment name.
29+
* __proxy:__ proxy server if you want to send requests via proxy.
30+
* __exitOnError:__ Boolean flag indicating whether to shutdown the server after logging an uncaughtException.
1331

14-
## Installation
32+
#### Using with Winston
33+
34+
```bash
35+
$ npm install stackify-logger
36+
```
37+
38+
If you are already using Winston you should add the stackify transport module to your instance of Winston:
39+
```js
40+
require('winston-stackify');
41+
winston.add(winston.transports.Stackify(options));
42+
```
43+
44+
All the details could be found here - [Winston Transport for Stackify](https://github.com/stackify/stackify-log-winston)
45+
46+
#### Using direct logger
47+
48+
If you are not using Winston logger you can use default Stackify logger. It has 5 levels of messages: trace, debug, info, warn and error. To send the message to Stackify API you should run one of the following methods in any place of your code where you want to track some information:
49+
```js
50+
stackify.log(level, message, meta)
51+
stackify.trace(message, meta)
52+
stackify.debug(message, meta)
53+
stackify.info(message, meta)
54+
stackify.warn(message, meta)
55+
stackify.error(message, meta)
56+
```
57+
The timestamp will be added to every message by default.
58+
59+
Meta parameter should be a valid JSON object.
60+
61+
Examples of usage:
62+
```js
63+
// Add the module to all the script files where you want to log any messages.
64+
var stackify = require('stackify-logger');
65+
66+
stackify.log('info', 'hey!');
67+
stackify.debug('any message');
68+
stackify.info('any message', {anything: 'this is metadata'});
69+
stackify.warn('attention');
70+
stackify.log('error', {error : new Error()});
71+
```
72+
When logging an error message you could pass an Error object in metadata like in the last case so the exception details would be available.
73+
74+
#### Exception handling
75+
Supported frameworks
76+
Express (ver 4.x) and all express-based frameworks only (e.g. SailsJS, Connect, LocomotiveJS) will be supported. This means all of the frameworks that support the format of the middleware functions used in Express.JS.
77+
function (req, res, next) {
78+
//some code
79+
next();
80+
}
81+
82+
Using with pure NodeJS app
83+
If you are not using any of the frameworks and all requests are handled inside native createServer method you should run stackify.stats() first line inside of this method :
84+
85+
var http = require('http')
86+
var stackify = require('stackify-logger')
87+
http.createServer(function (req, res) {
88+
stackify.stats(req, res);
89+
res.setHeader('content-type', 'text/plain')
90+
res.end('hello')
91+
})
92+
})
93+
You can use it also with any framework that doesn’t modify native createServer method.
94+
95+
96+
Using with express
97+
It acts as middleware when running on express-based apps. A middleware is a function which has access to request object (req) and response object (res), and the next middleware in line in the request-response cycle of an Express application (next). Each middleware can execute any code, make changes to request and response object, finish request-response cycle, and call the next middleware in the stack. Since middleware are execute serially, their order of inclusion is important.
98+
99+
You can activate it with the app.use() command in the appropriate place of your code, e.g.:
100+
var express = require('express');
101+
var app = express();
102+
app.use(stackify.stats);
15103

104+
To handle exceptions correctly put this right after all route handlers and before all the other app.use() commands.
16105

17-
Note: *We are dependent on the Guava project from Google. We require version 15.0 (or beyond) for the background thread that sends data back to Stackify.*
106+
To use it with the frameworks that have a wrapper around app.use() method or have different ways to use middleware plugins you should check the exact way of using middleware in it. For example, to add stackify.stats in SailsJS you should do this
18107

19108
## License
20109

@@ -30,4 +119,4 @@ Unless required by applicable law or agreed to in writing, software
30119
distributed under the License is distributed on an "AS IS" BASIS,
31120
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32121
See the License for the specific language governing permissions and
33-
limitations under the License.
122+
limitations under the License.

index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ var api = require('./lib/api'), // wrappers for API calls
88

99
module.exports = {
1010
// start sending logs
11-
start: function(options) {
11+
start: function (options) {
1212
api.methods.identifyApp(options);
13-
exception.exceptionHandler();
13+
exception.exceptionHandler(options.exitOnError);
1414
},
1515

1616
log: logger.methods.log,

lib/api.js

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var os = require('os'),
55
send = require('./sender'),
66
logger = require('./logger'),
77
CONFIG = require('../config/config'),
8+
exc = require('./exception'),
89

910
pkginfo = require('pkginfo')(module, 'name'),
1011

@@ -26,7 +27,7 @@ var os = require('os'),
2627
};
2728

2829
if (proxy) {
29-
result.proxy = proxy;
30+
result.proxy = (proxy.slice(0,4) === 'http') ? proxy : 'http://' + proxy;
3031
CONFIG.PROXY = CONFIG.PROXY || proxy;
3132
}
3233

@@ -51,7 +52,13 @@ module.exports.methods = {
5152
CONFIG.APP_DETAILS = data;
5253
CONFIG.APIKEY = settings.apiKey;
5354

54-
logger.methods.send();
55+
//start sending logs unless it's not already being sent because of exception
56+
57+
if (!exc.excCaught) {
58+
logger.methods.send();
59+
} else {
60+
console.log('exc caught not sending');
61+
}
5562

5663
},
5764
fail = function () {
@@ -60,8 +67,6 @@ module.exports.methods = {
6067
}, CONFIG.IDENTIFY_DELAY);
6168
};
6269

63-
console.log('Identifying...');
64-
6570
// check that settings object is correct
6671
if (!settings) {
6772
throw new TypeError('Settings are not provided');
@@ -78,7 +83,7 @@ module.exports.methods = {
7883

7984
},
8085

81-
postLogs: function postLogs(messages, cb) {
86+
postLogs: function postLogs(messages, cb, shutdown) {
8287
var delay = 0, // scheduled delay when postLogs call failed
8388
body = {
8489
CDID: CONFIG.APP_DETAILS.DeviceID,
@@ -98,21 +103,22 @@ module.exports.methods = {
98103

99104
//retry the request if it failed
100105
fail = function (code) {
101-
var sinceFirstError;
102-
103-
if (code === 401) {
104-
delay = CONFIG.DELAY.FIVE_MINUTES;
105-
lastApiError = new Date().getTime();
106-
} else {
107-
lastApiError = lastApiError || new Date().getTime();
108-
sinceFirstError = new Date().getTime() - lastApiError;
109-
delay = Math.min(Math.max(sinceFirstError, CONFIG.DELAY.ONE_SECOND), CONFIG.DELAY.ONE_MINUTE);
110-
}
111-
112-
setTimeout(function () {
113-
send(opt, cb, fail);
114-
}, delay);
115-
106+
if (!shutdown) {
107+
var sinceFirstError;
108+
109+
if (code === 401) {
110+
delay = CONFIG.DELAY.FIVE_MINUTES;
111+
lastApiError = new Date().getTime();
112+
} else {
113+
lastApiError = lastApiError || new Date().getTime();
114+
sinceFirstError = new Date().getTime() - lastApiError;
115+
delay = Math.min(Math.max(sinceFirstError, CONFIG.DELAY.ONE_SECOND), CONFIG.DELAY.ONE_MINUTE);
116+
}
117+
118+
setTimeout(function () {
119+
send(opt, cb, fail);
120+
}, delay);
121+
}
116122
};
117123
send(opt, cb, fail);
118124
}

lib/error.js

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,10 @@ module.exports = {
3737
},
3838
ServerVariables: process.env
3939
},
40-
headers = req ? req.headers : {},
41-
href,
42-
key;
40+
href;
4341

4442
if (req) {
4543
href = url.parse(helpers.getURL(req), true);
46-
47-
if (req.headers.cookie) {
48-
headers = {};
49-
for (key in req.headers) {
50-
if (req.headers.hasOwnProperty(key)) {
51-
headers[key] = req.headers[key];
52-
}
53-
}
54-
headers.cookie = CONFIG.COOKIE_MASK;
55-
}
5644
ex.WebRequestDetail = {
5745
UserIPAddress : req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress ||
5846
req.connection.socket.remoteAddress,
@@ -61,11 +49,15 @@ module.exports = {
6149
RequestUrl: (req.connection.encrypted ? 'https://' : 'http://') + href.hostname + href.pathname,
6250
RequestUrlRoot: href.hostname,
6351
ReferralUrl: req.headers.referer,
64-
Headers: headers,
52+
Headers: req.headers,
6553
Cookies: helpers.getCookies(req),
6654
QueryString: href.query,
6755
PostData: helpers.getPostData(req)
6856
};
57+
58+
if (req.headers.cookie) {
59+
ex.WebRequestDetail.Headers.cookie = CONFIG.COOKIE_MASK;
60+
}
6961
}
7062

7163
return ex;

lib/exception.js

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ var qs = require('querystring'),
77
CONFIG = require('../config/config');
88

99
module.exports = {
10-
// flag used to prevent catching the same exception twice (inside and outside of the createServer method)
10+
// flag used to prevent catching the same exception twice (inside and outside of the createServer method)
1111
excCaught : false,
1212
// Pure Node apps exception catching
13-
exceptionHandler : function exceptionHandler(req, res) {
13+
exceptionHandler : function exceptionHandler(req, exit) {
14+
var self = this;
1415
return (function () {
1516
var body = '';
1617
if (req) {
1718
req.on('data', function (chunk) {
18-
console.log('here');
1919
body += chunk;
2020
});
2121
req.on('end', function () {
@@ -25,28 +25,37 @@ module.exports = {
2525
}
2626

2727
process.on('uncaughtException', function (err) {
28-
console.log('exc');
29-
if (!this.excCaught) {
30-
this.excCaught = true;
28+
if (!self.excCaught) {
29+
self.excCaught = true;
3130
logger.methods.stop(err, req, function () {return true; });
31+
if (exit === true) {
32+
process.exit(1);
33+
}
3234
}
3335
});
3436
}());
3537
},
3638
// Express error handling middleware
37-
expressExceptionHandler : function expressExceptionHandler(err, req, res, next) {
38-
var cb = function () {
39-
next(err);
40-
};
39+
expressExceptionHandler : function expressExceptionHandler(options) {
40+
var self = this;
41+
return function expressExceptionHandler(err, req, res, next) {
42+
var cb = function () {
43+
if (options.exitOnError === true) {
44+
process.exit(1);
45+
} else {
46+
next(err);
47+
}
48+
};
4149

42-
if (!err) {
43-
return next();
44-
}
50+
if (!err) {
51+
return next();
52+
}
4553

46-
if (!this.excCaught) {
47-
this.excCaught = true;
48-
logger.methods.stop(err, req, cb);
49-
}
54+
if (!self.excCaught) {
55+
self.excCaught = true;
56+
logger.methods.stop(err, req, cb);
57+
}
5058

59+
};
5160
}
5261
};

lib/helpers.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
/* ### function parseMeta (meta, [err])
2-
###### @meta {Object} any meta data added to the message.
3-
###### @err {Boolean} **Optional** if true we should look for an error object and exclude it to separate parameter
4-
Function for parsing meta objects attached to the message
1+
var stackTrace = require('stack-trace');
2+
util = require('util');
3+
/*
4+
*** Function for parsing meta objects attached to the message
55
*/
66

7-
var stackTrace = require('stack-trace');
87

98
module.exports.parseMeta = function parseMeta(meta, err) {
109
var result,
@@ -83,7 +82,7 @@ module.exports.getTrace = function getTrace(err) {
8382
trace.forEach(function (val, index, arr) {
8483
var method = val.methodName || (val.functionName || val.typeName) + '.<anonymous>';
8584

86-
if (val.fileName.search('lib/logger.js') < 0 || val.fileName.search('stackify') < 0) {
85+
if (val.fileName ? (val.fileName.search('lib/logger.js') < 0 || val.fileName.search('stackify') < 0) : true) {
8786
result.push({
8887
CodeFileName: val.fileName,
8988
LineNum: val.lineNumber,

0 commit comments

Comments
 (0)