loggj 1.0.10 → 2.0.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.
package/README.md CHANGED
@@ -1,7 +1,22 @@
1
1
  # loggj
2
2
 
3
3
  This is a fork of [rufus](https://github.com/btd/rufus). Added file rotation handler with multiprocess/node cluster support. Rotation by size or time is not exact for better performance.
4
- ES6 support required, tested with Node 4.
4
+ Requires Node.js >= 22.12. Tested with Node 22, 24, 26.
5
+
6
+ ## Upgrading from 1.x
7
+
8
+ 2.0.0 brings support of Node 23+ and removes most of dependencies. Breaking changes:
9
+
10
+ - Node.js >= 22.12 is required.
11
+ - `chalk` is not a dependency anymore, ConsoleHandler colorizes messages with built-in `util.styleText`.
12
+ Colored output is the same, but loggj no longer sets `chalk.enabled = true` on a shared `chalk@1` instance,
13
+ so if your app relied on that side effect, enable colors in chalk by yourself.
14
+ - An object passed to a log method as last argument which is `instanceof Error` but not a native error
15
+ (e.g. `Object.create(Error.prototype)`) goes to `record.err` again on every Node version.
16
+ In 1.0.11 on Node 23+ such objects stayed in `record.args`.
17
+
18
+ Custom handlers written with `loggj.Handler.call(this, options)` and `util.inherits` work as before.
19
+ See [CHANGELOG](CHANGELOG.md) for the full list of changes.
5
20
 
6
21
  ## Getting started
7
22
 
@@ -267,7 +282,7 @@ The power of logger hierarchies can seen more when using [loggj.config](#config)
267
282
 
268
283
  ### Logging Exceptions
269
284
 
270
- Any time you pass an exception (an `Error`!) to a log method as last argument, the stack
285
+ Any time you pass an exception (an `Error` or anything that is `instanceof Error`) to a log method as last argument, the stack
271
286
  will be included in the output (if in format presented `%err` or `%error`).
272
287
 
273
288
  ```js
@@ -315,7 +330,7 @@ Just like Loggers, if a message's level is not equal to or greater than the Hand
315
330
  new 'console'(options);
316
331
  ```
317
332
 
318
- The Console handler outputs messages to the `stdio` or `stderr` (if level >= `WARN`), just like `console.log()` would. By default it colorize messages.
333
+ The Console handler outputs messages to the `stdio` or `stderr` (if level >= `WARN`), just like `console.log()` would. By default it colorize messages (with built-in `util.styleText`, even if output is not a TTY or `NO_COLOR` is set), pass `colorize: false` to disable it.
319
334
 
320
335
  ### StreamHandler
321
336
 
package/lib/config.js CHANGED
@@ -71,8 +71,9 @@ function configureLogger(name, loggerOptions, options) {
71
71
  }
72
72
  if (loggerOptions.filters) {
73
73
  loggerOptions.filters.forEach(function eachHandler(fname) {
74
- if(!options[fname]) throw new Error('There is no filter with name: ' + fname);
75
- logger.addFilter(options.filters[fname]);
74
+ var filter = options.filters && options.filters[fname];
75
+ if(!filter) throw new Error('There is no filter with name: ' + fname);
76
+ logger.addFilter(filter);
76
77
  });
77
78
  }
78
79
 
package/lib/console.js CHANGED
@@ -5,15 +5,34 @@
5
5
  var path = require('path');
6
6
  var util = require('util');
7
7
 
8
- var stack = require('stack-trace');
9
-
10
8
  var rufus = require('./');
11
9
  var ORIGINAL_METHODS = {};
12
10
 
13
11
  var root;
14
12
 
13
+ /**
14
+ * Returns V8 call sites starting from the caller of this function
15
+ * @returns {Array} array of CallSite
16
+ */
17
+ function getCallSites() {
18
+ var oldLimit = Error.stackTraceLimit;
19
+ var oldPrepare = Error.prepareStackTrace;
20
+ Error.stackTraceLimit = Infinity;
21
+ Error.prepareStackTrace = function(obj, callSites) {
22
+ return callSites;
23
+ };
24
+
25
+ var obj = {};
26
+ Error.captureStackTrace(obj, getCallSites);
27
+ var callSites = obj.stack;
28
+
29
+ Error.prepareStackTrace = oldPrepare;
30
+ Error.stackTraceLimit = oldLimit;
31
+ return callSites;
32
+ }
33
+
15
34
  function getLogger() {
16
- var trace = stack.get();
35
+ var trace = getCallSites();
17
36
 
18
37
  var filename;
19
38
  for (var i = 0, len = trace.length; i < len; i++) {
@@ -42,7 +61,7 @@ function replaceConsoleMethodWith(consoleMethod, logMethod) {
42
61
 
43
62
  function overrideConsole(options) {
44
63
  options = options || {};
45
- root = options.root || path.dirname(stack.get()[1].getFileName());
64
+ root = options.root || path.dirname(getCallSites()[1].getFileName());
46
65
 
47
66
  console.log(root);
48
67
 
package/lib/filter.js CHANGED
@@ -19,7 +19,7 @@ function Filter(filter) {
19
19
  return record.name[filter.length] === '.';
20
20
  }
21
21
  };
22
- } else if (util.isRegExp(filter)) {
22
+ } else if (util.types.isRegExp(filter)) {
23
23
  return function(record) {
24
24
  return filter.test(record.message);
25
25
  };
@@ -3,21 +3,25 @@
3
3
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
4
 
5
5
  var util = require('util');
6
- var chalk = require('chalk');
7
6
 
8
7
  var Handler = require('./handler');
9
8
  var StreamHandler = require('./stream');
10
9
  var LEVELS = require('../levels');
11
10
 
12
- chalk.enabled = true;
11
+ // always colorize, even if stream is not a TTY or NO_COLOR is set
12
+ function color(name) {
13
+ return function(str) {
14
+ return str && util.styleText(name, str, { validateStream: false });
15
+ };
16
+ }
13
17
 
14
18
  var COLORS = {
15
- 'VERBOSE': chalk.cyan,
16
- 'DEBUG': chalk.blue,
17
- 'INFO': chalk.green,
18
- 'WARN': chalk.yellow,
19
- 'ERROR': chalk.red,
20
- 'CRITICAL': chalk.magenta
19
+ 'VERBOSE': color('cyan'),
20
+ 'DEBUG': color('blue'),
21
+ 'INFO': color('green'),
22
+ 'WARN': color('yellow'),
23
+ 'ERROR': color('red'),
24
+ 'CRITICAL': color('magenta')
21
25
  };
22
26
 
23
27
  for(var c in COLORS){
@@ -299,7 +299,23 @@ RotatingFileHandler.prototype.shouldRotate = function (force) {
299
299
  });
300
300
  };
301
301
 
302
- RotatingFileHandler.prototype._getData = function () {
302
+ // Resolves when stream opened its file or failed to do it (stream error is not handled here)
303
+ function whenOpened(stream) {
304
+ return new Promise((resolve) => {
305
+ if (!stream.pending) {
306
+ return resolve();
307
+ }
308
+ let done = () => {
309
+ stream.removeListener('ready', done);
310
+ stream.removeListener('close', done);
311
+ resolve();
312
+ };
313
+ stream.once('ready', done);
314
+ stream.once('close', done);
315
+ });
316
+ }
317
+
318
+ RotatingFileHandler.prototype._getData = function (retried) {
303
319
  let that = this;
304
320
  let size;
305
321
  debug('Get file stat data');
@@ -326,9 +342,9 @@ RotatingFileHandler.prototype._getData = function () {
326
342
  that._prevSize = stat.size;
327
343
  return Promise.resolve([stat.size]);
328
344
  }).catch((err) => {
329
- if (err.code == 'ENOENT') {
345
+ if (err.code == 'ENOENT' && !retried) {
330
346
  debug('No file, reopening..');
331
- return that.reopen().then(that._getData());
347
+ return that.reopen().then(() => whenOpened(that._stream)).then(() => that._getData(true));
332
348
  } else {
333
349
  error('_getData', err);
334
350
  return that.reopen();
package/lib/logger.js CHANGED
@@ -166,8 +166,9 @@ var proto = {
166
166
  */
167
167
  makeRecord: function makeRecord(name, level, msg, args) {
168
168
  var err;
169
- if(util.isError(args[args.length - 1])) {
170
- err = args[args.length - 1];
169
+ var last = args[args.length - 1];
170
+ if(util.types.isNativeError(last) || last instanceof Error) {
171
+ err = last;
171
172
  args.length = args.length - 1;
172
173
  }
173
174
 
package/package.json CHANGED
@@ -1,19 +1,20 @@
1
1
  {
2
2
  "name": "loggj",
3
- "version": "1.0.10",
3
+ "version": "2.0.0",
4
4
  "dependencies": {
5
- "chalk": "^1.1.1",
6
- "lockfile": "^1.0.1",
7
- "stack-trace": "0.0.9"
8
- },
9
- "devDependencies": {
10
- "mocha": "^10.2.0",
11
- "sinon": "^1.17.3"
5
+ "lockfile": "^1.0.4"
12
6
  },
13
7
  "description": "Fast hierarchical text logger",
14
8
  "main": "./lib/index.js",
9
+ "files": [
10
+ "lib"
11
+ ],
12
+ "engines": {
13
+ "node": ">=22.12"
14
+ },
15
15
  "scripts": {
16
- "test": "node_modules/.bin/mocha test --recursive"
16
+ "test": "node --test test/*.js",
17
+ "coverage": "node --test --experimental-test-coverage --test-coverage-include='lib/**' test/*.js"
17
18
  },
18
19
  "bugs": "https://github.com/glintik/loggj/issues",
19
20
  "repository": {
package/CHANGELOG.md DELETED
@@ -1,69 +0,0 @@
1
- # rufus ChangeLog
2
-
3
- ## 0.5.7 - 2014-12-18
4
-
5
- - Fix console handler and how used levels
6
-
7
- ## 0.5.6 - 2014-02-03
8
-
9
- - Bug in rotating handler
10
- - Stable and define log remover
11
-
12
- ## 0.5.5 - 2014-01-30
13
-
14
- - Typo in file handler .reopen
15
-
16
- ## 0.5.4 - 2014-01-30
17
-
18
- - Make rotating handler work now both with size based and time based rotations.
19
-
20
- ## 0.5.3 - 2014-01-28
21
-
22
- - Some fixes for formats
23
-
24
- ## 0.5.2 - 2014-01-27
25
-
26
- - Time based log rotation
27
-
28
- ## 0.5.1 - 2014-01-25
29
-
30
- - Fix last tests
31
- - Small cleanup for file handler
32
-
33
- ## 0.5.0 - 2013-11-13
34
-
35
- - General cleanup
36
- - Remove timeout for handlers
37
- - Improve perfomance
38
- - Use util.format instead of own printf
39
- - More accurate console replacement
40
-
41
- ## v0.3.0 - 2013-10-24
42
-
43
- - added intel.handlers.Rotating
44
- - added ignore options to intel.console()
45
- - added chalk.enabled when colorize is used
46
- - added padding and truncation to printf
47
- - added Logger#handleExceptions to catch uncaught exceptions
48
- - added stack traces when an exception is logged
49
- - fork intel to support it myself
50
- - changed Promises from Q to bluebird, significantly faster
51
- - fixed Console handler from using accepting format options
52
- - make format and dates compiled. Perfomance stability with any format
53
-
54
- # inter Changelog
55
-
56
- ## v0.2.0 - 2013-10-04
57
-
58
- - added Filters for Handlers and Loggers
59
- - added Handler timeout option
60
- - added pid to LogRecord
61
- - added configuration using JSON
62
- - changed Promises to LazyPromises
63
- - changed printf to faster, smaller printf
64
- - changed internal forEach to faster while loops
65
- - removed node v0.6 support (it didn't work anyways)
66
-
67
- ## v0.1.0 - 2013-09-30
68
-
69
- - Initial release.
package/Makefile DELETED
@@ -1,16 +0,0 @@
1
- REPORTER = spec
2
-
3
- test:
4
- @NODE_ENV=test ./node_modules/.bin/mocha \
5
- --check-leaks \
6
- --reporter $(REPORTER)
7
-
8
- test-cov:
9
- @NODE_ENV=test ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- \
10
- --check-leaks \
11
- --reporter $(REPORTER)
12
-
13
- jshint:
14
- ./node_modules/.bin/jshint --show-non-errors lib test
15
-
16
- .PHONY: test test-cov
package/TODO.md DELETED
@@ -1,13 +0,0 @@
1
- ## What need to fix
2
-
3
- 1. Correctly remove rotated files
4
- 2. Create folders for file handler
5
- 3. Move files not rename in rotating handler
6
-
7
- ## What need to add
8
-
9
- 1. socket handler (consist from 4 parts: server which push logs from connected clients and client which push logs to server which connected)
10
- 2. smtp handler (without grouping and filtering useless)
11
- 3. json formatter (why not just replace bunyan if i can)
12
-
13
- Both should collect messages in buffer maybe with support of grouping by specific thing
@@ -1,74 +0,0 @@
1
- /* This Source Code Form is subject to the terms of the Mozilla Public
2
- * License, v. 2.0. If a copy of the MPL was not distributed with this
3
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
-
5
- const Console = require('console').Console;
6
- const EE = require('events').EventEmitter;
7
-
8
- const winston = require('winston');
9
- const rufus = require('../');
10
- const intel = require('intel');
11
- const bunyan = require('bunyan');
12
- const log4js = require('log4js').getLogger();
13
-
14
- var stdout = new EE();
15
- stdout.write = function (out, encoding, cb) {
16
- if (typeof encoding === 'function') {
17
- cb = encoding;
18
- encoding = null;
19
- }
20
- cb && cb();
21
- return true;
22
- };
23
-
24
- var _console = new Console(stdout, stdout);
25
-
26
- rufus.addHandler(new rufus.handlers.Stream({ stream: stdout, formatter: new rufus.Formatter('[%date] %logger:: %message') }));
27
- intel.addHandler(new intel.handlers.Stream({ stream: stdout, formatter: new intel.Formatter('[%(date)s] %(name)s:: %(message)s') }));
28
-
29
- winston.add(winston.transports.File, { stream: stdout, timestamp: true });
30
- winston.remove(winston.transports.Console);
31
-
32
- var log = bunyan.createLogger({name: 'lr', level: 'debug'});
33
-
34
- process.stdout.write = function(msg, enc, callback) {
35
- if(typeof enc === 'function' && !callback) callback = enc;
36
-
37
- callback && callback();
38
- return true;
39
- }
40
-
41
- var Benchmark = require('benchmark');
42
-
43
- var suite = new Benchmark.Suite('logging.info()');
44
-
45
- suite
46
- .add('console.info', function() {
47
- _console.info('asdf');
48
- })
49
- .add('rufus.info', function() {
50
- rufus.info('asdf');
51
- })
52
- .add('winston.info', function() {
53
- winston.info('asdf');
54
- })
55
- .add('intel.info', function() {
56
- intel.info('asdf');
57
- })
58
- .add('bunyan.info', function() {
59
- log.info('asdf');
60
- })
61
- .add('log4js.info', function() {
62
- log4js.info('asdf');
63
- })
64
-
65
- suite
66
- // add listeners
67
- .on('cycle', function (event) {
68
- console.warn(String(event.target));
69
- })
70
- .on('complete', function () {
71
- console.warn('Fastest is ' + this.filter('fastest').pluck('name'));
72
- })
73
- // run async
74
- .run({ 'async': true });
package/test/config.js DELETED
@@ -1,179 +0,0 @@
1
- /* This Source Code Form is subject to the terms of the Mozilla Public
2
- * License, v. 2.0. If a copy of the MPL was not distributed with this
3
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
-
5
- var assert = require('assert');
6
- var os = require('os');
7
- var path = require('path');
8
- var util = require('util');
9
-
10
- var rufus = require('../');
11
-
12
- var NOW = Date.now();
13
- var counter = 1;
14
- function tmp() {
15
- return path.join(os.tmpdir(),
16
- 'rufus-' + NOW + '-' + process.pid + '-' + (counter++));
17
- }
18
-
19
- function spy() {
20
- var args = [];
21
- var fn = function () {
22
- args.push(arguments);
23
- };
24
- fn.getCallCount = function () {
25
- return args.length;
26
- };
27
- fn.getLastArgs = function () {
28
- return args[args.length - 1];
29
- };
30
- return fn;
31
- }
32
-
33
- function SpyHandler() {
34
- rufus.Handler.apply(this, arguments);
35
- this.spy = spy();
36
- }
37
- util.inherits(SpyHandler, rufus.Handler);
38
- SpyHandler.prototype.emit = function spyEmit(record, callback) {
39
- this.spy.apply(this, arguments);
40
- callback();
41
- };
42
-
43
- var oldBasic;
44
- var oldLevel;
45
- describe('basicConfig', function () {
46
- beforeEach(function () {
47
- oldBasic = rufus.basicConfig;
48
- oldLevel = rufus._level;
49
-
50
- rufus._handlers = [];
51
- });
52
-
53
- afterEach(function () {
54
- rufus.basicConfig = oldBasic;
55
- rufus._level = oldLevel;
56
- });
57
-
58
- it('root logger calls basicConfig', function (done) {
59
- var val;
60
- var stream = {
61
- write: function (out, cb) {
62
- val = out;
63
- cb();
64
- }
65
- };
66
-
67
- rufus.basicConfig = function () {
68
- oldBasic({ stream: stream, format: '%message' });
69
- };
70
-
71
- rufus.info('danger').then(function () {
72
- assert.strictEqual(val, 'danger');
73
- assert.strictEqual(rufus._level, oldLevel);
74
- done();
75
- });
76
- });
77
-
78
- it('only works once', function () {
79
- rufus.basicConfig();
80
- assert.strictEqual(rufus._level, oldLevel);
81
-
82
- rufus.basicConfig({ level: 'critical' });
83
- assert.strictEqual(rufus._handlers.length, 1);
84
- assert.strictEqual(rufus._level, oldLevel);
85
- });
86
-
87
- it('works with file option', function () {
88
- var name = tmp();
89
- rufus.basicConfig({ file: name });
90
- assert.strictEqual(rufus._handlers.length, 1);
91
- assert.strictEqual(rufus._handlers[0]._file, name);
92
- });
93
-
94
-
95
- it('works with level', function () {
96
- rufus.basicConfig({ level: 'error' });
97
- assert.strictEqual(rufus._level, rufus.ERROR);
98
- });
99
-
100
- it('works with format', function () {
101
- rufus.basicConfig({ format: '%msg'});
102
- assert.strictEqual(rufus._handlers[0]._formatter._format, '%msg');
103
- });
104
-
105
- afterEach(function () {
106
- rufus.basicConfig = oldBasic;
107
- rufus.setLevel(oldLevel);
108
- rufus._handlers = [];
109
- });
110
-
111
- });
112
-
113
- describe('config', function () {
114
- it('should be able to configure logging', function (done) {
115
- rufus.config({
116
- formatters: {
117
- 'basic': '%message',
118
- 'foo': 'foo! %level: %message'
119
- },
120
- filters: {
121
- 'user': /\buser\b/g
122
- },
123
- handlers: {
124
- 'null': {
125
- 'class': SpyHandler,
126
- 'formatter': 'foo',
127
- 'filters': ['user']
128
- }
129
- },
130
- loggers: {
131
- 'qqq.zzz': {
132
- 'level': 'INFO',
133
- 'propagate': false,
134
- 'handlers': ['null']
135
- },
136
- 'qqq.ww.zzz': {
137
- 'level': 'INFO',
138
- 'propagate': false,
139
- 'handleExceptions': true,
140
- 'exitOnError': false,
141
- 'handlers': ['null']
142
- }
143
- }
144
- });
145
-
146
- var excepts = rufus.getLogger('qqq.ww.zzz');
147
- assert(excepts._uncaughtException);
148
- assert(!excepts._exitOnError);
149
-
150
- var log = rufus.getLogger('qqq.zzz');
151
- var handler = log._handlers[0];
152
- assert.strictEqual(log._handlers.length, 1);
153
- assert(!log.propagate);
154
-
155
- var msg = handler.format({ message: 'hi', args: [ 'hi' ], levelname: 'BAR'});
156
- assert.strictEqual(msg, 'foo! BAR: hi');
157
-
158
- log.debug('user').then(function () {
159
- assert.strictEqual(handler.spy.getCallCount(), 0);
160
-
161
- return log.info('user foo');
162
- }).then(function () {
163
- assert.strictEqual(handler.spy.getCallCount(), 1);
164
- assert.strictEqual(handler.spy.getLastArgs()[0].message, 'user foo');
165
-
166
- return log.info('ignore me');
167
- }).then(function () {
168
- assert.strictEqual(handler.spy.getCallCount(), 1);
169
- done();
170
- });
171
- });
172
-
173
- it('should be able to config with just JSON', function () {
174
- rufus.config(require('./util/config.json'));
175
-
176
- var log = rufus.getLogger('test.config.json');
177
- assert.strictEqual(log._handlers.length, 2);
178
- });
179
- });
package/test/console.js DELETED
@@ -1,54 +0,0 @@
1
- /* This Source Code Form is subject to the terms of the Mozilla Public
2
- * License, v. 2.0. If a copy of the MPL was not distributed with this
3
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
- /*global describe: true, it:true, before: true, after: true*/
5
-
6
- var assert = require('assert');
7
-
8
- var rufus = require('../');
9
- var consoleUtil = require('./util/console');
10
-
11
- var spy = new rufus.handlers.Null();
12
- spy.handle = function(record) {
13
- this._lastRecord = record;
14
- return rufus.handlers.Null.prototype.handle.call(this, record);
15
- };
16
-
17
- var prevLog;
18
- var lastMock;
19
- function mockLog() {
20
- lastMock = arguments;
21
- }
22
-
23
- describe('Console replacement', function() {
24
- before(function() {
25
- rufus.addHandler(spy);
26
- prevLog = console.log;
27
- console.log = mockLog;
28
- // not passing root means this file becomes root.
29
- // which means dirname.basename, or test.console
30
- rufus.console();
31
- });
32
-
33
- after(function() {
34
- rufus.console.restore();
35
- assert.strictEqual(console.log, mockLog);
36
- console.log = prevLog;
37
- rufus._handlers = [];
38
- });
39
-
40
-
41
- it('can inject into global scope', function() {
42
- console.warn('test');
43
- assert(spy._lastRecord);
44
- assert.strictEqual(spy._lastRecord.message, 'test');
45
- });
46
-
47
- it('can generate a name', function() {
48
- console.log('foo');
49
- assert.strictEqual(spy._lastRecord.name, 'test.console');
50
-
51
- consoleUtil('bar');
52
- assert.strictEqual(spy._lastRecord.name, 'test.util.console');
53
- });
54
- });
package/test/filter.js DELETED
@@ -1,33 +0,0 @@
1
- /* This Source Code Form is subject to the terms of the Mozilla Public
2
- * License, v. 2.0. If a copy of the MPL was not distributed with this
3
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
- /*global describe: true, it:true*/
5
-
6
- var assert = require('assert');
7
-
8
- var rufus = require('../');
9
-
10
- describe('Filters', function() {
11
- it('should accept regexp', function() {// regex filter check message
12
- var f = rufus.makeFilter(/^foo/);
13
-
14
- assert.ok(!f({ message: 'not foobar' }));
15
- assert.ok(f({ message: 'foobar' }));
16
- });
17
-
18
- it('should accept string', function() {// string filter check name
19
- var f = rufus.makeFilter('foo.bar');
20
-
21
- assert(f({
22
- name: 'foo.bar'
23
- }));
24
-
25
- assert(f({
26
- name: 'foo.bar.baz'
27
- }));
28
-
29
- assert(!f({
30
- name: 'food.bar'
31
- }));
32
- });
33
- });
package/test/formatter.js DELETED
@@ -1,89 +0,0 @@
1
- /* This Source Code Form is subject to the terms of the Mozilla Public
2
- * License, v. 2.0. If a copy of the MPL was not distributed with this
3
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
- /*global describe: true, it:true*/
5
-
6
- var assert = require('assert');
7
-
8
- var EOL = require('os').EOL;
9
-
10
- var rufus = require('../');
11
-
12
- describe('Formatter', function() {
13
- it('should accept a format string', function() {
14
- var formatter = new rufus.Formatter('%level');
15
- assert.strictEqual(formatter._format, '%level');
16
- });
17
-
18
- it('should accept options', function() {
19
- var formatter = new rufus.Formatter({
20
- format: '%level'
21
- });
22
-
23
- assert.strictEqual(formatter._format, '%level');
24
- });
25
-
26
- it('should output an Error stack', function() {
27
- var formatter = new rufus.Formatter('%logger: %message%n%err');
28
- var e = new Error('boom');
29
- var msg = 'oh noes:';
30
- var name = 'foo';
31
-
32
- //similar produced with Logger.makeRecord
33
- var record = {
34
- name: name,
35
- message: msg,
36
- args: [msg],
37
- err: e
38
- };
39
-
40
- assert.strictEqual(formatter.format(record), name + ': ' + msg + EOL + e.stack + EOL);
41
- });
42
-
43
- it('should allow to set date format', function() {
44
- var formatter = new rufus.Formatter({
45
- format: '%date{%Y-%m}'
46
- });
47
-
48
- var d = new Date();
49
- var record = {
50
- timestamp: d
51
- };
52
-
53
- function pad(val) {
54
- if (val > 9) {
55
- return val;
56
- }
57
- return '0' + val;
58
- }
59
- var expected = d.getFullYear() + '-' + pad(d.getMonth() + 1);
60
- assert.strictEqual(formatter.format(record), expected);
61
- });
62
-
63
- it('should format as json', function() {
64
- var formatter = new rufus.Formatter({
65
- format: 'json'
66
- });
67
-
68
- var e = new Error('boom');
69
-
70
- let message = 'some message';
71
- var record = {
72
- timestamp: new Date(),
73
- levelname: 'INFO',
74
- name: 'some name',
75
- pid: 123,
76
- message,
77
- args: [message, 1, 'abc'],
78
- err: e,
79
- };
80
- // ['timestamp', 'levelname', 'name', 'pid', 'message'].forEach(k => {
81
- let recordExpected = Object.assign({}, record, {
82
- err: e.stack,
83
- message: `${message} 1 abc`
84
- });
85
- delete recordExpected.args;
86
-
87
- assert.strictEqual(formatter.format(record), JSON.stringify(recordExpected) + EOL);
88
- });
89
- });
package/test/handlers.js DELETED
@@ -1,335 +0,0 @@
1
- /* This Source Code Form is subject to the terms of the Mozilla Public
2
- * License, v. 2.0. If a copy of the MPL was not distributed with this
3
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
-
5
- var assert = require('assert');
6
- var EventEmitter = require('events').EventEmitter;
7
- var fs = require('fs');
8
- var os = require('os');
9
- var path = require('path');
10
-
11
- var rufus = require('../');
12
-
13
- var glob = require('../lib/utils/re-glob');
14
-
15
- var NOW = Date.now();
16
- var counter = 1;
17
- function tmp() {
18
- return path.join(os.tmpdir(),
19
- 'rufus-' + NOW + '-' + process.pid + '-' + (counter++));
20
- }
21
-
22
- function rec(msg, level) {
23
- return { message: msg, args: [msg], timestamp: new Date() };
24
- }
25
-
26
- function bytes(x) {
27
- var b = new Buffer(x);
28
- b[0] = '<'.charCodeAt(0);
29
- b[b.length - 1] = '>'.charCodeAt(0);
30
- b.fill('a', 1, b.length - 1);
31
- return b.toString();
32
- }
33
-
34
- describe('Handler', function () {
35
- describe('constructor', function () {
36
- it('should accept options', function () {
37
- var h = new rufus.Handler({ level: rufus.ERROR });
38
- assert.strictEqual(h.level, rufus.ERROR);
39
- });
40
-
41
- it('should accept a level', function () {
42
- var h = new rufus.Handler(rufus.WARN);
43
- assert.strictEqual(h.level, rufus.WARN);
44
- });
45
- });
46
-
47
- describe('handle', function () {
48
- it('requires emit to accept a callback argument', function () {
49
- var h = new rufus.Handler();
50
- h.emit = function () {
51
- };
52
-
53
- assert.throws(h.handle.bind(h), function (err) {
54
- return err.message === 'Handler.emit requires a callback argument';
55
- });
56
-
57
- h = new rufus.Handler();
58
- h.emit = function (record, callback) {
59
- record = callback;
60
- };
61
- assert.doesNotThrow(h.handle.bind(h));
62
- });
63
-
64
- it('should use filters on record', function (done) {
65
- var h = new rufus.Handler();
66
- var lastRecord;
67
- h.emit = function (record, callback) {
68
- lastRecord = record;
69
- callback();
70
- };
71
-
72
- h.addFilter(rufus.makeFilter('foo'));
73
- h.handle({ name: 'foo' }).then(function () {
74
- assert.strictEqual(lastRecord.name, 'foo');
75
-
76
- return h.handle({ name: 'foobar' });
77
- }).then(function () {
78
- assert.notEqual(lastRecord.name, 'foobar');
79
- done();
80
- });
81
- });
82
- });
83
-
84
- describe('emit', function () {
85
- it('must be overriden by subclasses', function () {
86
- var h = new rufus.Handler();
87
- assert.throws(h.emit);
88
- });
89
- });
90
- });
91
-
92
- describe('Stream', function () {
93
- describe('constructor', function () {
94
- it('should accept options', function () {
95
- var stream = {};
96
- var handler = new rufus.handlers.Stream({
97
- level: rufus.INFO,
98
- stream: stream
99
- });
100
-
101
- assert.strictEqual(handler.level, rufus.INFO);
102
- assert.strictEqual(handler._stream, stream);
103
- });
104
-
105
- it('should accept just a stream', function () {
106
- var stream = {};
107
- var handler = new rufus.handlers.Stream(stream);
108
-
109
- assert.strictEqual(handler.level, rufus.NOTSET);
110
- assert.strictEqual(handler._stream, stream);
111
- });
112
- });
113
-
114
- describe('emit', function () {
115
- it('should write message to stream', function (done) {
116
- var out;
117
- var stream = {
118
- write: function (msg, fn) {
119
- out = msg;
120
- fn();
121
- }
122
- };
123
-
124
- var handler = new rufus.handlers.Stream({
125
- stream: stream,
126
- formatter: new rufus.Formatter('%message%n')
127
- });
128
- handler.handle({ message: 'foo', args: ['foo'] }).then(function () {
129
- assert.strictEqual(out, 'foo\n');
130
- done();
131
- });
132
- });
133
-
134
- it('should wait for flush on slow streams', function (done) {
135
- var out;
136
- var stream = new EventEmitter();
137
- stream.write = function write(data, fn) {
138
- setTimeout(function () {
139
- out = data;
140
- fn();
141
- }, 1);
142
- };
143
- var handler = new rufus.handlers.Stream({
144
- stream: stream,
145
- formatter: new rufus.Formatter('%message%n')
146
- });
147
- handler.handle({ message: 'secret', args: ['secret'] }).then(function () {
148
- assert.strictEqual(out, 'secret\n');
149
- done();
150
- });
151
- });
152
- });
153
- });
154
-
155
- describe('File', function () {
156
- describe('constructor', function () {
157
- it('should accept options', function () {
158
- var filename = tmp();
159
- var handler = new rufus.handlers.File({
160
- level: rufus.WARN,
161
- file: filename
162
- });
163
-
164
- assert.strictEqual(handler.level, rufus.WARN);
165
- assert.strictEqual(handler._file, filename);
166
- });
167
-
168
- it('should accept a filename', function () {
169
- var filename = tmp();
170
- var handler = new rufus.handlers.File(filename);
171
-
172
- assert.strictEqual(handler._file, filename);
173
- });
174
- });
175
-
176
- describe('handle', function () {
177
- it('should write to the file', function (done) {
178
- var filename = tmp();
179
- var handler = new rufus.handlers.File({
180
- file: filename,
181
- formatter: new rufus.Formatter('%message%n')
182
- });
183
- handler.handle({ message: 'recon', args: ['recon'] }).then(function () {
184
- fs.readFile(filename, function (err, contents) {
185
- assert.ifError(err);
186
- assert.equal(contents.toString(), 'recon\n');
187
- done();
188
- });
189
- });
190
- });
191
- });
192
- });
193
-
194
- describe('Console', function () {
195
- describe('constructor', function () {
196
- it('should use stdout and stderr', function () {
197
- var h = new rufus.handlers.Console();
198
- assert.strictEqual(h._out._stream, process.stdout);
199
- assert.strictEqual(h._err._stream, process.stderr);
200
- });
201
- });
202
-
203
- describe('handle', function () {
204
- it('should send low priority messages to stdout', function (done) {
205
- var h = new rufus.handlers.Console({
206
- formatter: new rufus.Formatter('%message%n'),
207
- colorize: false
208
- });
209
- var val;
210
- h._out._stream = {
211
- write: function (out, callback) {
212
- val = out;
213
- callback();
214
- return true;
215
- }
216
- };
217
-
218
- h.handle({ level: rufus.INFO, message: 'oscar mike', args: ['oscar mike'] }).then(function () {
219
- assert.strictEqual(val, 'oscar mike\n');
220
- done();
221
- });
222
- });
223
-
224
- it('should send warn and higher messages to stderr', function (done) {
225
- var h = new rufus.handlers.Console({
226
- formatter: new rufus.Formatter('%message%n'),
227
- colorize: false
228
- });
229
- var val;
230
- h._err._stream = {
231
- write: function (out, callback) {
232
- val = out;
233
- callback();
234
- return true;
235
- }
236
- };
237
-
238
- h.handle({ level: rufus.WARN, message: 'mayday', args: ['mayday'] }).then(function () {
239
- assert.strictEqual(val, 'mayday\n');
240
- }).then(done);
241
- });
242
- });
243
- });
244
-
245
- /*describe('RotatingFileHandler', function () {
246
- describe('handle', function () {
247
- it('with maxSize should create new files', function (done) {
248
- this.timeout(5000);
249
-
250
- var filename = tmp();
251
- var handler = new rufus.handlers.Rotating({
252
- file: filename,
253
- maxSize: 64,
254
- formatter: new rufus.Formatter('%message%n')
255
- });
256
-
257
- assert.strictEqual(handler._file, filename);
258
- handler.handle(rec(bytes(60)));
259
- handler.handle(rec(bytes(50)));
260
- handler.handle(rec(bytes(45))).then(function () {
261
- assert.strictEqual(fs.statSync(filename).size, 46);
262
- assert.strictEqual(fs.statSync(filename + '.1').size, 51);
263
- assert.strictEqual(fs.statSync(filename + '.2').size, 61);
264
- }).done(done);
265
- });
266
-
267
- it('with maxSize should create new files date rated', function (done) {
268
- this.timeout(5000);
269
-
270
- var filename = tmp();
271
- var handler = new rufus.handlers.Rotating({
272
- file: filename,
273
- timeRate: 200,
274
- maxFiles: 2,
275
- formatter: new rufus.Formatter('%message%n')
276
- });
277
-
278
- var times = 0;
279
- var interval = setInterval(function() {
280
- handler.handle(rec(bytes(50)));
281
- times += 1;
282
- if(times > 3) {
283
- clearInterval(interval);
284
- handler.handle(rec(bytes(45))).then(function () {
285
- //glob(handler._remover.filesFormat, function(err, matches) {
286
- // console.log(matches);
287
- //});
288
- //should be 2 files, but i have no idea how correctly test it +1 current
289
- assert(true);
290
- }).done(done);
291
- }
292
- }, 250);
293
- });
294
-
295
- it('with maxFiles should not create more than max', function (done) {
296
- this.timeout(5000);
297
-
298
- var filename = tmp();
299
- var handler = new rufus.handlers.Rotating({
300
- file: filename,
301
- maxSize: 64,
302
- maxFiles: 3,
303
- formatter: new rufus.Formatter('%message%n')
304
- });
305
-
306
- handler.handle({ message: bytes(50), args: [bytes(50)] });
307
- handler.handle({ message: bytes(55), args: [bytes(55)] });
308
- handler.handle({ message: bytes(60), args: [bytes(60)] });
309
- handler.handle({ message: bytes(45), args: [bytes(45)] }).then(function () {
310
- assert.strictEqual(fs.statSync(filename).size, 46);
311
- assert.strictEqual(fs.statSync(filename + '.1').size, 61);
312
- assert.strictEqual(fs.statSync(filename + '.2').size, 56);
313
- assert(!fs.existsSync(filename + '.3'));
314
- }).done(done);
315
- });
316
-
317
- it('should continue to write after buffer is flushed', function (done) {
318
- this.timeout(5000);
319
-
320
- var filename = tmp();
321
- var handler = new rufus.handlers.Rotating({
322
- file: filename,
323
- maxSize: 64,
324
- formatter: new rufus.Formatter('%message%n')
325
- });
326
-
327
- handler.handle({ message: bytes(29), args: [bytes(29)] }).then(function () {
328
- return handler.handle({ message: bytes(31), args: [bytes(31)] });
329
- }).then(function () {
330
- assert.strictEqual(fs.statSync(filename).size, 62);
331
- }).done(done);
332
- });
333
- });
334
- });
335
- */
package/test/logger.js DELETED
@@ -1,201 +0,0 @@
1
- /* This Source Code Form is subject to the terms of the Mozilla Public
2
- * License, v. 2.0. If a copy of the MPL was not distributed with this
3
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
- /*global describe: true, it:true*/
5
-
6
- var assert = require('assert');
7
- var sinon = require('sinon');
8
-
9
- var rufus = require('../');
10
- var Logger = rufus.Logger;
11
-
12
- var __counter = 1;
13
- function unique() {
14
- return "u-" + __counter++;
15
- }
16
-
17
- function spyHandler(level, callback) {
18
- if(typeof level !== 'number') level = 0;
19
-
20
- var stub = sinon.spy(callback);
21
-
22
- return {
23
- handle: stub,
24
- level: level
25
- };
26
- }
27
-
28
- describe('Logger', function() {
29
- it('should return the same logger when created with the same name', function() {
30
- var name = unique();
31
-
32
- var logger1 = new Logger(name);
33
- var logger2 = new Logger(name);
34
-
35
- assert.strictEqual(logger1, logger2);
36
- });
37
-
38
- it('should allow add handlers and remove them', function() {
39
- var logger = new Logger(unique());
40
- var handler = new rufus.handlers.Null();
41
-
42
- logger.addHandler(handler);
43
- assert.strictEqual(logger.getHandlers().length, 1);
44
-
45
- logger.removeHandler(handler);
46
- assert.strictEqual(logger.getHandlers().length, 0);
47
- });
48
-
49
- it('should set by default for child logger log level of its direct parent', function() {
50
- var parentName = unique();
51
- var parent = new Logger(parentName);
52
- parent.setLevel('error');
53
-
54
- var childName = parentName + '.' + unique();
55
- var child = new Logger(childName);
56
-
57
- assert.strictEqual(child.getEffectiveLevel(), rufus.ERROR);
58
- });
59
-
60
- it('should make record', function() {
61
- var name = unique();
62
- var logger = new Logger(name);
63
-
64
- var msg = 'foo';
65
- var level = rufus.DEBUG;
66
- var err = new Error();
67
- var args = [ msg, err ];
68
- var record = logger.makeRecord(name, 'DEBUG', msg, args.slice());
69
-
70
- assert.strictEqual(record.name, name);
71
- assert.strictEqual(record.level, level);
72
- assert.strictEqual(record.message, msg);
73
- assert.strictEqual(record.levelname, 'DEBUG');
74
- assert.strictEqual(record.pid, process.pid);
75
- assert.strictEqual(record.args.length, args.length - 1); //it is because last arg is Error
76
- assert.strictEqual(record.args[0], msg);
77
- assert.strictEqual(record.err, err);
78
- });
79
-
80
- /*it('should call its handlers', function() {
81
- var logger = new Logger(unique());
82
- logger.propagate = false;
83
-
84
- var handler = spyHandler();
85
- logger.addHandler(handler);
86
-
87
- logger.log(rufus.INFO, 'foo');
88
- assert.ok(handler.handle.called);
89
-
90
- logger.info('foo');
91
- assert.ok(handler.handle.calledTwice);
92
- });*/
93
-
94
- it('should call parent handlers when propagate is true', function() {
95
- var parentName = unique();
96
- var parent = new Logger(parentName);
97
- parent.propagate = false; //stop there
98
-
99
- var childName = parentName + '.' + unique();
100
- var child = new Logger(childName);
101
-
102
- var parentHandler = spyHandler();
103
- var childHandler = spyHandler();
104
-
105
- parent.addHandler(parentHandler);
106
- child.addHandler(childHandler);
107
-
108
- child.info('foo');
109
-
110
- assert.ok(childHandler.handle.calledOnce);
111
- assert.ok(parentHandler.handle.calledOnce);
112
- });
113
-
114
- it('should call handlers which level is more then record level', function() {
115
- var logger = new Logger(unique());
116
- logger.propagate = false;
117
-
118
- var handlerError = spyHandler(rufus.ERROR);
119
- var handlerTrace = spyHandler(rufus.TRACE);
120
-
121
- logger.addHandler(handlerError).addHandler(handlerTrace);
122
-
123
- logger.info('foo');
124
-
125
- assert.ok(handlerTrace.handle.calledOnce);
126
- assert.ok(!handlerError.handle.called);
127
- });
128
-
129
- it('should call handlers when record level more or eql logger level', function() {
130
- var logger = new Logger(unique());
131
- logger.propagate = false;
132
- logger.setLevel(rufus.INFO);
133
-
134
- var handler = spyHandler();
135
- logger.addHandler(handler);
136
-
137
- logger.info('foo');
138
- logger.error('foo');
139
- logger.trace('foo');
140
-
141
- assert.ok(handler.handle.calledTwice);
142
- });
143
-
144
- it('should allow to filter log records', function() {
145
- var logger = new Logger(unique());
146
- logger.propagate = false;
147
-
148
- var handler = spyHandler();
149
- logger.addHandler(handler);
150
-
151
- logger.addFilter(rufus.makeFilter(/^foo/));
152
-
153
- // message not pass filter
154
- logger.info('bar');
155
- assert.ok(!handler.handle.called);
156
-
157
- logger.info('fooooo');
158
- assert.ok(handler.handle.calledOnce);
159
- });
160
-
161
- it('should return promise that rejects when one of handlers fail', function(done) {//TODO
162
- var logger = new Logger(unique());
163
- logger.propagate = false;
164
-
165
- var h = new rufus.handlers.Null();
166
- h.emit = function(record, callback) {
167
- throw new Error('foo');
168
- };
169
-
170
- logger.addHandler(h);
171
-
172
- logger.info('bar').then(null, function(err) {
173
- assert.strictEqual(err.message, 'foo');
174
- }).then(done);
175
- });
176
- });
177
-
178
- module.exports = {
179
- 'Logger': {
180
- 'handleExceptions': {
181
- 'should catch uncaughtErrors': function(done) {
182
- this.slow(300);
183
-
184
- spawn(false, function(err, stdout, stderr) {
185
- assert.strictEqual(stderr, 'root.ERROR - Uncaught exception handled');
186
- done();
187
- });
188
- },
189
- 'should not exit if exitOnError is false': function(done) {
190
- this.slow(300);
191
-
192
- spawn(true, function(err, stdout, stderr) {
193
- assert.strictEqual(stderr, 'root.ERROR - Uncaught exception handled');
194
- assert.strictEqual(stdout, 'root.INFO - noexit');
195
- done();
196
- });
197
- }
198
- }
199
- }
200
- };
201
-
@@ -1,21 +0,0 @@
1
- {
2
- "formatters": {
3
- "basic": "basic: %(message)s"
4
- },
5
- "filters": {},
6
- "handlers": {
7
- "empty": {
8
- "class": "rufus/handlers/null"
9
- },
10
- "spy": {
11
- "class": "./test/util/spyhandler"
12
- }
13
- },
14
- "loggers": {
15
- "test.config.json": {
16
- "level": "INFO",
17
- "propagate": false,
18
- "handlers": ["empty", "spy"]
19
- }
20
- }
21
- }
@@ -1,7 +0,0 @@
1
- /* This Source Code Form is subject to the terms of the Mozilla Public
2
- * License, v. 2.0. If a copy of the MPL was not distributed with this
3
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
-
5
- module.exports = function(x) {
6
- console.log(x);
7
- };
@@ -1,18 +0,0 @@
1
- /* This Source Code Form is subject to the terms of the Mozilla Public
2
- * License, v. 2.0. If a copy of the MPL was not distributed with this
3
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
-
5
- const rufus = require('../../');
6
- rufus.addHandler(new rufus.handlers.Console({
7
- formatter: new rufus.Formatter('%logger.%level - %message'),
8
- colorize: false
9
- }));
10
- rufus.handleExceptions(process.argv.indexOf('--noexit') === -1);
11
-
12
- /*setTimeout(function() {
13
- throw new Error('catch me if you can');
14
- }, 5);*/
15
-
16
- setTimeout(function() {
17
- rufus.info('noexit');
18
- }, 225);
@@ -1,18 +0,0 @@
1
- /* This Source Code Form is subject to the terms of the Mozilla Public
2
- * License, v. 2.0. If a copy of the MPL was not distributed with this
3
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
-
5
- const util = require('util');
6
-
7
- const rufus = require('../../');
8
-
9
- function Spy() {
10
- rufus.Handler.apply(this, arguments);
11
- }
12
- util.inherits(Spy, rufus.Handler);
13
-
14
- Spy.prototype.emit = function(record, callback) {
15
- callback();
16
- };
17
-
18
- module.exports = Spy;