0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-12-16 21:56:25 -05:00

feat: exposed rotating-file log for json logging (#948)

This both allows for logger type 'rotating-file' and
passing of other options from the config "option" example:
{type: rotating-file, format: json, path: /path/to/log.jsonl, level: http, options: {period: 1d}}
This commit is contained in:
Marc Udoff 2018-08-31 18:42:15 -04:00 committed by Juan Picado @jotadeveloper
parent d0798c491f
commit 5ca0ca5228
5 changed files with 84 additions and 45 deletions

View file

@ -126,7 +126,8 @@ packages:
#
# parameters for file: name is filename
# {type: 'file', path: 'verdaccio.log', level: 'debug'},
#
# Rotating log stream. Options are passed directly to bunyan. See: https://github.com/trentm/node-bunyan#stream-type-rotating-file
# {type: rotating-file, format: json, path: /path/to/log.jsonl, level: http, options: {period: 1d}}
# parameters for stdout and stderr: format: json | pretty | pretty-timestamped
# {type: 'stdout', format: 'pretty', level: 'debug'},
logs:

View file

@ -11,9 +11,12 @@ logs:
- {type: stdout, format: pretty, level: http}
# file output
- {type: file, path: verdaccio.log, level: info}
# Rotating log stream. Options are passed directly to bunyan. See: https://github.com/trentm/node-bunyan#stream-type-rotating-file
- {type: rotating-file, format: json, path: /path/to/log.jsonl, level: http, options: {period: 1d}}
```
Use `SIGUSR2` to notify the application, the log-file was rotated and it needs to reopen it.
Note: Rotating log stream is not supported in cluster mode. [See here](https://github.com/trentm/node-bunyan#stream-type-rotating-file)
### Configuration

View file

@ -43,6 +43,7 @@
"mime": "2.3.1",
"minimatch": "3.0.4",
"mkdirp": "0.5.1",
"mv": "2.1.1",
"pkginfo": "0.4.1",
"request": "2.87.0",
"semver": "5.5.0",

View file

@ -1,9 +1,11 @@
const cluster = require('cluster');
const Logger = require('bunyan');
const Error = require('http-errors');
const Stream = require('stream');
const chalk = require('chalk');
const Utils = require('./utils');
const pkgJSON = require('../../package.json');
const _ = require('lodash');
/**
* Match the level based on buyan severity scale
@ -22,6 +24,16 @@ function getlvl(x) {
}
}
/**
* A RotatingFileStream that modifes the message first
*/
class VerdaccioRotatingFileStream extends Logger.RotatingFileStream { // We depend on mv so that this is there
write(obj) {
const msg = fillInMsgTemplate(obj.msg, obj, false);
super.write(JSON.stringify({...obj, msg}, Logger.safeCycles()) + '\n');
}
}
/**
* Setup the Buyan logger
* @param {*} logs list of log configuration
@ -33,55 +45,77 @@ function setup(logs) {
}
logs.forEach(function(target) {
let level = target.level || 35;
if (level === 'http') {
level = 35;
}
// create a stream for each log configuration
const stream = new Stream();
stream.writable = true;
if (target.type === 'rotating-file') {
if (target.format !== 'json') {
throw new Error('Rotating file streams only work with JSON!');
}
if (cluster.isWorker) {
// https://github.com/trentm/node-bunyan#stream-type-rotating-file
throw new Error('Cluster mode is not supported for rotating-file!');
}
let dest;
let destIsTTY = false;
const prettyPrint = (obj) => print(obj.level, obj.msg, obj, destIsTTY) + '\n';
const prettyTimestampedPrint = (obj) => obj.time.toISOString() + print(obj.level, obj.msg, obj, destIsTTY) + '\n';
const jsonPrint = (obj) => {
const msg = fillInMsgTemplate(obj.msg, obj, destIsTTY);
return JSON.stringify({...obj, msg}, Logger.safeCycles()) + '\n';
};
const stream = new VerdaccioRotatingFileStream(
_.merge({},
// Defaults can be found here: https://github.com/trentm/node-bunyan#stream-type-rotating-file
target.options || {},
{path: target.path, level})
);
if (target.type === 'file') {
// destination stream
dest = require('fs').createWriteStream(target.path, {flags: 'a', encoding: 'utf8'});
dest.on('error', function(err) {
Logger.emit('error', err);
streams.push(
{
type: 'raw',
level,
stream,
}
);
} else {
const stream = new Stream();
stream.writable = true;
let destination;
let destinationIsTTY = false;
if (target.type === 'file') {
// destination stream
destination = require('fs').createWriteStream(target.path, {flags: 'a', encoding: 'utf8'});
destination.on('error', function(err) {
stream.emit('error', err);
});
} else if (target.type === 'stdout' || target.type === 'stderr') {
destination = target.type === 'stdout' ? process.stdout : process.stderr;
destinationIsTTY = destination.isTTY;
} else {
throw Error('wrong target type for a log');
}
if (target.format === 'pretty') {
// making fake stream for prettypritting
stream.write = (obj) => {
destination.write(`${print(obj.level, obj.msg, obj, destinationIsTTY)}\n`);
};
} else if (target.format === 'pretty-timestamped') {
// making fake stream for pretty pritting
stream.write = (obj) => {
destination.write(`${obj.time.toISOString()}${print(obj.level, obj.msg, obj, destinationIsTTY)}\n`);
};
} else {
stream.write = (obj) => {
const msg = fillInMsgTemplate(obj.msg, obj, destinationIsTTY);
destination.write(`${JSON.stringify({...obj, msg}, Logger.safeCycles())}\n`);
};
}
streams.push({
type: 'raw',
level,
stream: stream,
});
} else if (target.type === 'stdout' || target.type === 'stderr') {
dest = target.type === 'stdout' ? process.stdout : process.stderr;
destIsTTY = dest.isTTY;
} else {
throw Error('wrong target type for a log');
}
if (target.format === 'pretty') {
// making fake stream for prettypritting
stream.write = (obj) => {
dest.write(prettyPrint(obj));
};
} else if (target.format === 'pretty-timestamped') {
// making fake stream for prettypritting
stream.write = (obj) => {
dest.write(prettyTimestampedPrint(obj));
};
} else {
stream.write = (obj) => {
dest.write(jsonPrint(obj));
};
}
if (target.level === 'http') target.level = 35;
streams.push({
type: 'raw',
level: target.level || 35,
stream: stream,
});
});
// buyan default configuration

BIN
yarn.lock

Binary file not shown.