hmpo-logger
Advanced tools
| var _ = require('underscore'), | ||
| sortObject = require('sort-object-keys'); | ||
| var keys = [ | ||
| '@timestamp', | ||
| 'level', | ||
| '@message', | ||
| 'message', | ||
| 'clientip', | ||
| 'sessionID', | ||
| 'hostname', | ||
| 'port', | ||
| 'method', | ||
| 'path', | ||
| 'httpversion', | ||
| 'response', | ||
| 'responseTime', | ||
| 'bytes', | ||
| 'clientip', | ||
| 'sessionID', | ||
| 'uniqueID', | ||
| 'host', | ||
| 'pm', | ||
| 'label', | ||
| '@fields', | ||
| 'error', | ||
| 'stack', | ||
| 'type' | ||
| ]; | ||
| var serialize = function (data) { | ||
| var seen = []; | ||
| data = sortObject(data, keys); | ||
| return JSON.stringify(data, function (k, v) { | ||
| if (typeof v === 'function') { | ||
| return '[func]'; | ||
| } | ||
| if (typeof v === 'object' && v) { | ||
| if (seen.indexOf(v) >=0) { return '[circular]'; } | ||
| seen.push(v); | ||
| return _.isArray(v) ? v : sortObject(v, keys); | ||
| } | ||
| return v; | ||
| }); | ||
| }; | ||
| module.exports = function (options) { | ||
| if (typeof options.meta !== 'object' && options.meta != null) { | ||
| options.meta = { meta: options.meta }; | ||
| } | ||
| if (options.meta && typeof options.meta.message === 'string' && typeof options.meta.stack === 'string') { | ||
| var error = {}; | ||
| error.message = options.meta.message; | ||
| delete options.meta.message; | ||
| error.stack = options.meta.stack.split(/\n\s+/).slice(1); | ||
| delete options.meta.stack; | ||
| if (options.meta.type) { | ||
| error.type = options.meta.type; | ||
| delete options.meta.type; | ||
| } | ||
| options.meta = _.extend({ | ||
| error: error | ||
| }, options.meta); | ||
| } | ||
| var timestamp = typeof options.timestamp === 'function' ? options.timestamp() : new Date().toISOString(); | ||
| var output = _.extend({}, options.meta, { | ||
| '@timestamp': timestamp, | ||
| 'level': (options.level || 'DEBUG').toUpperCase(), | ||
| 'message': options.message || '' | ||
| }); | ||
| if (typeof options.stringify === 'function') { | ||
| return options.stringify(output); | ||
| } | ||
| return serialize(output); | ||
| }; | ||
| var logstash = require('../../lib/logstash'); | ||
| describe('logstash', function () { | ||
| var options, clock, fakeTimestamp; | ||
| beforeEach(function () { | ||
| options = { | ||
| level: 'test', | ||
| message: 'test message', | ||
| stringify: function (v) { return v; } | ||
| }; | ||
| clock = sinon.useFakeTimers(0); | ||
| fakeTimestamp = '1970-01-01T00:00:00.000Z'; | ||
| }); | ||
| afterEach(function () { | ||
| clock.restore(); | ||
| }); | ||
| it('should export a function that takes one argument', function () { | ||
| logstash.should.be.a('function'); | ||
| logstash.should.have.length(1); | ||
| }); | ||
| it('should set timestamp, level, and message', function () { | ||
| var output = logstash(options); | ||
| output.should.deep.equal({ | ||
| '@timestamp': fakeTimestamp, | ||
| level: 'TEST', | ||
| message: 'test message' | ||
| }); | ||
| }); | ||
| it('should use empty message and default level if none set', function () { | ||
| delete options.level; | ||
| delete options.message; | ||
| var output = logstash(options); | ||
| output.should.deep.equal({ | ||
| '@timestamp': fakeTimestamp, | ||
| level: 'DEBUG', | ||
| message: '' | ||
| }); | ||
| }); | ||
| it('should timestamp function if given', function () { | ||
| options.timestamp = function () { return 'test timestamp'; }; | ||
| var output = logstash(options); | ||
| output.should.deep.equal({ | ||
| '@timestamp': 'test timestamp', | ||
| level: 'TEST', | ||
| message: 'test message' | ||
| }); | ||
| }); | ||
| it('should set meta value if it is not an object', function () { | ||
| options.meta = 'meta string'; | ||
| var output = logstash(options); | ||
| output.should.deep.equal({ | ||
| '@timestamp': fakeTimestamp, | ||
| level: 'TEST', | ||
| message: 'test message', | ||
| meta: 'meta string' | ||
| }); | ||
| }); | ||
| it('should add meta values to output if it is an object', function () { | ||
| options.meta = { | ||
| key1: 'value1', | ||
| key2: 2 | ||
| }; | ||
| var output = logstash(options); | ||
| output.should.deep.equal({ | ||
| '@timestamp': fakeTimestamp, | ||
| level: 'TEST', | ||
| message: 'test message', | ||
| key1: 'value1', | ||
| key2: 2 | ||
| }); | ||
| }); | ||
| it('should add meta values to output if it is an error', function () { | ||
| options.meta = new Error('Error message'); | ||
| options.meta.stack = 'Error\n 1\n 2\n 3'; | ||
| options.meta.type = 'my_error'; | ||
| var output = logstash(options); | ||
| output.should.deep.equal({ | ||
| '@timestamp': fakeTimestamp, | ||
| level: 'TEST', | ||
| message: 'test message', | ||
| error: { | ||
| message: 'Error message', | ||
| stack: ['1', '2', '3'], | ||
| type: 'my_error' | ||
| } | ||
| }); | ||
| }); | ||
| it('should use the internal serialize function if no stringify is given', function () { | ||
| delete options.stringify; | ||
| options.meta = new Error('Error message'); | ||
| options.meta.stack = 'Error\n 1\n 2\n 3'; | ||
| var output = logstash(options); | ||
| output.should.equal( | ||
| '{' + | ||
| '"@timestamp":"1970-01-01T00:00:00.000Z",' + | ||
| '"level":"TEST",' + | ||
| '"message":"test message",' + | ||
| '"error":{"message":"Error message","stack":["1","2","3"]}' + | ||
| '}'); | ||
| }); | ||
| it('should handle functions and circular references when stringifying', function () { | ||
| delete options.stringify; | ||
| options.meta = { | ||
| string: 'string', | ||
| number: 12345, | ||
| float: 1.23456, | ||
| object: { foo: 'bar' }, | ||
| array: [ 1, 2, 3 ], | ||
| func: function () {}, | ||
| circular: {} | ||
| }; | ||
| options.meta.circular.content = options.meta.circular; | ||
| var output = logstash(options); | ||
| output.should.equal( | ||
| '{' + | ||
| '"@timestamp":"1970-01-01T00:00:00.000Z",' + | ||
| '"level":"TEST",' + | ||
| '"message":"test message",' + | ||
| '"array":[1,2,3],' + | ||
| '"circular":{"content":"[circular]"},' + | ||
| '"float":1.23456,' + | ||
| '"func":"[func]",' + | ||
| '"number":12345,' + | ||
| '"object":{"foo":"bar"},' + | ||
| '"string":"string"' + | ||
| '}' | ||
| ); | ||
| }); | ||
| }); | ||
+8
-5
@@ -5,2 +5,3 @@ var winston = require('winston'), | ||
| moduleName = require('./module-name'), | ||
| logstash = require('./logstash'), | ||
| onFinished = require('on-finished'), | ||
@@ -33,3 +34,3 @@ onHeaders = require('on-headers'); | ||
| sessionID: 'sessionID', | ||
| verb: 'method', | ||
| method: 'method', | ||
| request: 'request' | ||
@@ -134,4 +135,5 @@ }, | ||
| filename: this._options.app, | ||
| json: this._options.appJSON, | ||
| logstash: this._options.appJSON, | ||
| json: false, | ||
| logstash: false, | ||
| formatter: this._options.appJSON ? logstash : undefined, | ||
| level: this._options.appLevel | ||
@@ -149,4 +151,5 @@ }) | ||
| filename: this._options.error, | ||
| json: this._options.errorJSON, | ||
| logstash: this._options.errorJSON, | ||
| json: false, | ||
| logstash: false, | ||
| formatter: this._options.appJSON ? logstash : undefined, | ||
| level: this._options.errorLevel | ||
@@ -153,0 +156,0 @@ }) |
+2
-1
| { | ||
| "name": "hmpo-logger", | ||
| "version": "0.0.6", | ||
| "version": "1.0.0", | ||
| "description": "Consistent logging for hmpo apps", | ||
@@ -27,2 +27,3 @@ "main": "index.js", | ||
| "on-headers": "^1.0.1", | ||
| "sort-object-keys": "^1.1.2", | ||
| "underscore": "^1.8.3", | ||
@@ -29,0 +30,0 @@ "winston": "^2.2.0" |
+1
-1
@@ -80,3 +80,3 @@ # hmpo-logger | ||
| sessionID: 'sessionID', | ||
| verb: 'method', | ||
| method: 'method', | ||
| request: 'request' | ||
@@ -83,0 +83,0 @@ }, |
@@ -249,5 +249,5 @@ | ||
| sessionID: 'abc123', | ||
| method: 'GET', | ||
| request: '/abc/123', | ||
| responseTime: 5000, | ||
| verb: 'GET' | ||
| responseTime: 5000 | ||
| })); | ||
@@ -254,0 +254,0 @@ }); |
@@ -93,2 +93,15 @@ | ||
| it('should use non-logstash logging if JSON is false', function () { | ||
| manager.config({ | ||
| appJSON: false, | ||
| errorJSON: false | ||
| }); | ||
| var t = winston.loggers.options.transports; | ||
| t.length.should.equal(3); | ||
| expect(t[1].formatter).to.be.undefined; | ||
| expect(t[2].formatter).to.be.undefined; | ||
| }); | ||
| it('should disable transports that are specified as falsey', function () { | ||
@@ -111,3 +124,3 @@ manager.config({ | ||
| extra: 'extravalue', | ||
| verb: false | ||
| method: false | ||
| } | ||
@@ -114,0 +127,0 @@ }); |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
56625
13.99%21
10.53%1339
18.92%0
-100%5
25%+ Added
+ Added