Skip to content

Commit

Permalink
patched some better formatting into it..
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Froehlingsdorf committed Jun 30, 2016
1 parent a8aa03b commit ed86653
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 49 deletions.
Empty file modified .gitignore
100644 → 100755
Empty file.
Empty file modified LICENSE
100644 → 100755
Empty file.
64 changes: 63 additions & 1 deletion README.md
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# log4bro (nodejs logger)
- the (only) one usable logger

- log4bro makes it hassle free to have compliant microservice log behaviour
- just require & init and log via global variable in a few seconds
- you can run in production mode to automatically switch log-levels
- you can run in dockerMode to stop logfile writing and change output to json fields
- you can attach some extra fields to json logs so that they are also loved by your ELK stack and your sysops
- node + docker + log4bro = happy you, happy ELK stack and happy sysops

# simple example

```javascript

Expand Down Expand Up @@ -31,4 +39,58 @@ LOG.fatal("bla");
//thats all there is to it..
```

# different example show text & json output
- (just run npm start to run example locally)

```
var log4bro = require("log4bro");
var options = {
"productionMode": false,
"logDir": "logs",
"skipEnhance": true,
"namespace": "",
"silence": false,
"loggerName": "dev",
"dockerMode": false,
"varKey": "MLOG"
};
var logger = new log4bro(options);
var msg = "ich mache mir sorgen, ob der logger denn noch funktioniert.";
MLOG.trace(msg);
MLOG.debug(msg);
MLOG.info(msg);
MLOG.warn(msg);
MLOG.error(msg);
MLOG.fatal(msg);
console.log("");
/* json style */
var options2 = {
"productionMode": true,
"logDir": "logs",
"skipEnhance": true,
"namespace": "",
"silence": false,
"loggerName": "dev",
"dockerMode": true,
"varKey": "JLOG"
};
var logger2 = new log4bro(options2);
JLOG.trace(msg);
JLOG.debug(msg);
JLOG.info(msg);
JLOG.warn(msg);
JLOG.error(msg);
JLOG.fatal(msg);
```

- enjoy.. need help? contact me.. @krystianity or on twitter: @silentleave
- author: Christian Fröhlingsdorf, <[email protected]>
Empty file modified index.js
100644 → 100755
Empty file.
8 changes: 5 additions & 3 deletions package.json
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
{
"name": "log4bro",
"version": "1.0.5",
"description": "no-brain logger with perfect output format, based on bunyan.",
"version": "1.0.6",
"description": "no-brain logger with compliant output format, based on bunyan.",
"main": "index.js",
"scripts": {},
"scripts": {
"start": "node ./src/example/index.js"
},
"repository": {
"type": "git",
"url": "https://github.com/krystianity/log4bro.git"
Expand Down
96 changes: 83 additions & 13 deletions src/LoggerRawStream.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,22 @@ var chalk = require("chalk");
* will either write to process.stdout or logfile (depending on a given logFile)
* @constructor
*/
function LoggerRawStream(logFile) {
function LoggerRawStream(logFile, logFieldOptions, dockerMode) {

this.buffer = [];
this.bufferFlushSize = 10;
this.bufferTimeout = 5000;
this.logFieldOptions = logFieldOptions || null;
this.logFieldKeys = this.logFieldOptions ? Object.keys(logFieldOptions) : null; //do once only
this.dockerMode = dockerMode || false;

this.logStream = null;
this.outStream = null;

if (logFile) {
if (logFile && !dockerMode) {
this.logStream = fs.createWriteStream(logFile, { "flags": "a" });
} else {
this.outStream = process.stdout; //get ref and stop using the getter
}
}

Expand All @@ -26,41 +33,104 @@ function LoggerRawStream(logFile) {
LoggerRawStream.prototype.write = function(rec) {

if (typeof rec !== "object") {
console.error("error: raw stream got a non-object record: %j", rec);
console.log("[log4bro] error: raw stream got a non-object record: %j", rec);
return;
}

rec = this.alterLogFields(rec);

this.consoleOutput(rec);
this.buffer.push(JSON.stringify(rec));
rec = null;
this.checkAndFlushBuffer();
this.dockerMode ? this.jsonConsoleOutput(rec) : this.consoleOutput(rec);

if(this.logStream){
this.buffer.push(JSON.stringify(rec));
rec = null;
this.checkAndFlushBuffer();
}
};

/**
* alter method were log objects are re-mapped
* @param log
* @returns {*}
*/
LoggerRawStream.prototype.alterLogFields = function(log) {
LoggerRawStream.prototype.alterLogFields = function(_log) {

//TODO hmm..
var log = JSON.parse(JSON.stringify(_log)); //work on copy

//time -> @timestamp
if (log.time) {
log["@timestamp"] = JSON.parse(JSON.stringify(log.time));
delete log.time;
}

//remove v:0 field
if(log.v !== null){
delete log.v;
}

//remove logger name field
if(log.name !== null){
delete log.name;
}

//level -> loglevel_value(int) + loglevel(string)
if(log.level !== null){
log["loglevel"] = this.levelToName(log.level);
log["loglevel_value"] = JSON.parse(JSON.stringify(log.level));
delete log.level;
}

var jmsg = this._isJsonString(log.msg);
if(jmsg != null){
log["msg_json"] = jmsg;
delete log.msg;
}

if(this.logFieldKeys){
for(var i = 0; i < this.logFieldKeys.length; i++){
log[this.logFieldKeys[i]] = this.logFieldOptions[this.logFieldKeys[i]];
}
}

return log;
};

/**
* writes a console output if the logstream is not set
* parses json if possible
*/
LoggerRawStream.prototype.consoleOutput = function(str) {
LoggerRawStream.prototype._isJsonString = function(str) {
var obj = null;
try {
obj = JSON.parse(str);
} catch (e) {
//empty
}
return obj;
};

/**
* writes a text console output if the logstream is not set
*/
LoggerRawStream.prototype.consoleOutput = function(obj) {

if (!this.logStream) {
var msg = this.levelToName(obj.level ? obj.level : obj.loglevel_value)
+ " @ " + obj["@timestamp"] + " : " + (obj.msg ? obj.msg : JSON.stringify(obj.msg_json)) + "\n";
msg = this.levelToColorWrap(msg, obj.level ? obj.level : obj.loglevel_value);
this.outStream.write(msg);
msg = null;
}
};

/**
* writes a json console output if the logstream is not set
*/
LoggerRawStream.prototype.jsonConsoleOutput = function(obj) {

if (!this.logStream) {
var msg = this.levelToName(str.level) + " @ " + str["@timestamp"] + " : " + str.msg + "\n";
process.stdout.write(this.levelToColorWrap(msg, str.level));
var msg = this.levelToColorWrap(JSON.stringify(obj), obj.level ? obj.level : obj.loglevel_value) + "\n";
this.outStream.write(msg);
msg = null;
}
};
Expand Down Expand Up @@ -92,7 +162,7 @@ LoggerRawStream.prototype.levelToColorWrap = function(str, level) {
case 30: return chalk.green(str);
case 40: return chalk.yellow(str);
case 50: return chalk.red(str);
case 60: return chalk.purple(str);
case 60: return chalk.red(str);
default: return chalk.blue(str);
}
};
Expand Down
63 changes: 31 additions & 32 deletions src/ServiceLogger.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,85 +2,77 @@ var fs = require("fs");
var bunyan = require("bunyan");
var RawStream = require("./LoggerRawStream.js");

function ServiceLogger(loggerName, silence, logDir, productionMode, dockerMode, varKey) {

if (ServiceLogger.instance) return ServiceLogger.instance;
function ServiceLogger(loggerName, silence, logDir, productionMode, dockerMode, varKey, logFieldOptions) {

if(typeof loggerName === "object" && arguments.length === 1){
productionMode = loggerName.productionMode;
logDir = loggerName.logDir;
silence = loggerName.silence;
dockerMode = loggerName.dockerMode;
varKey = loggerName.varKey;
logFieldOptions = loggerName.logFieldOptions;

loggerName = loggerName.name; //last
}

this.varKey = varKey || "LOG";

this.dockerMode = dockerMode || false;
this.logFieldOptions = logFieldOptions || null;
this.silence = silence || false;
this.logDir = logDir || "logs";

if (!loggerName && !productionMode) {
loggerName = loggerName || "dev";
this.loggerName = loggerName || "dev";
} else {
loggerName = loggerName || "prod";
this.loggerName = loggerName || "prod";
}

if(productionMode){
console.log("[ServiceLogger] Logger is in production mode.");
console.log("[log4bro] Logger is in production mode.");
} else {
console.log("[ServiceLogger] Logger is in development mode.");
}

this.silence = silence || false;
if (this.silence) {
//console.log("Any kind of logger was silenced!");
//console.log = function() {};
//console.dir = function() {};
console.log("[log4bro] Logger is in development mode.");
}

this.logDir = logDir || "logs";

var streams = [
{
"type": "raw",
"level": productionMode ? "WARN" : "TRACE",
"stream": new RawStream(null) //will only write to console/stdout
"stream": new RawStream(null, this.logFieldOptions, this.dockerMode) //will only write to console/stdout
}
];

if(!dockerMode){
if(!this.dockerMode){

console.log("[log4bro] Logger is not in docker mode.");
this.createLoggingDir();

streams.push({
"type": "raw",
"level": productionMode ? "WARN" : "INFO",
"stream": new RawStream(this.logDir + "/service-log.json") //will only write to logfile
"stream": new RawStream(this.logDir + "/service-log.json", this.logFieldOptions) //will only write to logfile
});
} else {
console.log("[ServiceLogger] Logger is in docker mode.");
console.log("[log4bro] Logger is in docker mode.");
}

this.createLoggingDir();
this.LOG = bunyan.createLogger({
"name": loggerName,
"name": this.loggerName,
"streams": streams,
"src": false
});

this.setGlobal();

ServiceLogger.instance = this;
return this;
}

ServiceLogger.prototype.createLoggingDir = function() {

if (!fs.existsSync(this.logDir)) {
console.log("[ServiceLogger] Logs folder does not exists creating " + this.logDir + " make sure to set path in blammo.xml.");
console.log("[log4bro] Logs folder does not exists creating " + this.logDir + " make sure to set path in blammo.xml.");
fs.mkdirSync(this.logDir);
return;
}

console.log("[ServiceLogger] Logs folder exists, clearing " + this.logDir);
console.log("[log4bro] Logs folder exists, clearing " + this.logDir);

var files = null;
try { files = fs.readdirSync(this.logDir); }
Expand All @@ -96,10 +88,6 @@ ServiceLogger.prototype.createLoggingDir = function() {
}
};

ServiceLogger.prototype.getLogger = function() {
return this;
};

ServiceLogger.prototype.setGlobal = function() {
global[this.varKey] = this;
};
Expand Down Expand Up @@ -136,6 +124,17 @@ ServiceLogger.prototype.fatal = function(message) {

ServiceLogger.prototype.enhance = function(message) {
/* enhance */

//TODO hmm..
if(typeof message === "object"){

if(Object.keys(message).length <= 15){
return JSON.stringify(message);
}

return "[Object object, with more than 15 keys.]";
}

return message;
};

Expand Down
Loading

0 comments on commit ed86653

Please sign in to comment.