Ver código fonte

Initial commit

luis 9 anos atrás
commit
4f39bea8e5
14 arquivos alterados com 586 adições e 0 exclusões
  1. 89 0
      README.md
  2. 19 0
      doc/CHANGELOG.md
  3. 63 0
      doc/TODO.md
  4. 7 0
      index.js
  5. 12 0
      lib/adapter.js
  6. 34 0
      lib/defaults.js
  7. 112 0
      lib/logger.js
  8. 114 0
      lib/system.js
  9. 19 0
      lib/writer.js
  10. 19 0
      lib/writers/console.js
  11. 19 0
      lib/writers/file.js
  12. 14 0
      package.json
  13. 34 0
      test/test-conf/conf.json
  14. 31 0
      test/test-conf/index.js

+ 89 - 0
README.md

@@ -0,0 +1,89 @@
+# Simple log system
+
+```javascript
+var log = require('hlogger').createLogger("name");
+
+log.info("test");
+```
+
+---
+## Initial relase
+
+Simple pet project that contains ways to create new Writers, Adapters
+
+
+#### Logger
+The way developer issues logging
+
+```javascript
+	log.info("info log");
+	log.error("error log");
+	log.warn("warning log");
+	log.verb("verbose log");
+```
+
+#### Adapter
+Log filtering, adapters can be created to receive only error, warning logs
+
+
+#### Writer
+Attached to adapter, writers will be responsible to write the logs either files, console, sql, socket
+
+Right now only two predefined loggers availalbe: file and console
+
+
+
+### Log formats
+Formats for adapters:
+
+* __%m__  - The actual message
+* __%c__  - logWriter count			
+* __%l__  - TAG name [ERROR,WARN,INFO,VERBOSE]
+* __%n__	-	Logger name
+* __%e__	-	Ellapsed time per writer
+* __%E__  - Ellapsed per Logger
+* __%t__	- Date string
+* __%a__	- Ascii escape char
+* __%%__  - Literal '%'
+* __%|__  - Special case, all chars after %| will be presented on the right
+
+
+### Config format:
+Create a set of writers, and setup adapters using those writers
+
+```json
+{
+	"writers" : {
+		"filetolog":{
+			"writer":"file",
+			"opts":{
+				"path":"log3.txt"
+			}
+		},
+		"errorfile": {
+			"writer":"file",
+			"opts": {
+				"path":"error3.txt"
+			}
+		},
+		"console1": {
+			"writer":"console",
+			"opts":{}
+		}
+	},
+
+	"adapters" : [
+		{
+			"levels": ["ERROR","WARN","INFO"],
+			"fmt": "[%c:%n -%l-  %m %| %E/%c]",
+			"writers": ["filetolog"]
+		},
+		{ 
+			"levels":["ERROR"],
+			"fmt": "ERR - %m",
+			"writers": ["errorfile","console1"]
+		}
+	]
+}
+```
+

+ 19 - 0
doc/CHANGELOG.md

@@ -0,0 +1,19 @@
+### 07-May-2016
+Changed console.log from ConsoleWriter to process.stdout.write, so we can warp console.log into a logger
+```javascript
+console.log = require('hlogger').createLogger('name');
+```
+### 26-Jun-2016
+Changed logger to support objects as console.log
+```
+var obj = {
+	test: {
+		msg: 'testing depth'
+	},
+	arr:[1,2,3]
+}
+
+log.info("Testing: ", obj);
+```
+
+Changed package.json test to run test-conf

+ 63 - 0
doc/TODO.md

@@ -0,0 +1,63 @@
+### TODO
+
+Rearrange the format better, keep it together
+
+create  logger chains as in:
+```
+var log = Logger.createLogger("log1");
+var log2 = log.createLogger("log2");
+```
+
+resulting in name: "
+[0:log1.log2 -LVL- message           +0.2ms/0]
+
+create loggers from configuration
+" no point doing that we can create new loggers based on name
+Logger.createLogger("c1.log");
+Logger.createLogger("c1.log.app");
+
+
+### Feature 2	
+	Create named adapters so we could load in json config using a file watcher maybe
+
+{
+	"writer" : {
+		FileWriter: {
+			"ansi":off
+		}
+		console: {
+		}
+	},
+	"adapter" : [
+		{
+			levels:["ERROR","WARN"],
+			match: ".*",
+			writers: "FileWriter","console"
+		}
+	]
+}
+
+### Simplify config aswell only wrapper needed
+
+{
+	"adapterFile" {
+		ansi:off,
+		"levels":["ERROR","WARN"],
+		match: ".*",
+		writer: {
+			name: "FileWriter",
+			options: {
+				file: "",
+				ansi: false
+			}
+	}
+	"console": {
+		ansi:on,
+		"levels":["ERROR","WARN","INFO","VERBOSE"],
+		match: ".*",
+		writer: "Console"
+	}
+
+},
+
+

+ 7 - 0
index.js

@@ -0,0 +1,7 @@
+
+module.exports = require('./lib/logger');
+module.exports.Adapter = require('./lib/adapter');
+module.exports.Writer = require('./lib/writer');
+
+// This will install in default Logger
+require('./lib/defaults');

+ 12 - 0
lib/adapter.js

@@ -0,0 +1,12 @@
+
+
+module.exports = class LogAdapter {
+
+	constructor(filterFunc,writers,fmt) {
+		this.writers = writers;
+		this.filterFunc = filterFunc;
+		this.logFmt = fmt;
+	}
+
+
+}

+ 34 - 0
lib/defaults.js

@@ -0,0 +1,34 @@
+var Logger = require('./logger');
+var LoggerSystem = require('./system');
+var LogWriter = require('./writer');
+var LogAdapter = require('./adapter');
+var ConsoleWriter = require('./writers/console.js');
+var FileWriter = require('./writers/file.js');
+
+// Some defaults
+Logger.root = new LoggerSystem();
+
+Logger.defaults = {
+	fmt:{
+		error: "\033[0;37m[\033[01;30m%c\033[0m:\033[1;34m%n\033[0;37m" +"\033[0;31m -%l- " + "\033[1;31m%m\033[0m%|\033[01;30m%E/%c\33[0m]" ,
+		warn:  "\033[0;37m[\033[01;30m%c\033[0m:\033[1;34m%n\033[0;37m" +"\033[0;33m -%l- " + "\033[0;37m%m\033[0m%|\033[01;30m%E/%c\33[0m]" ,
+		info:  "\033[0;37m[\033[01;30m%c\033[0m:\033[1;34m%n\033[0;37m" +"\033[0;32m -%l- " + "\033[0;37m%m\033[0m%|\033[01;30m%E/%c\33[0m]",
+		verbose:  "\033[0;37m[\033[01;30m%c\033[0m:\033[1;34m%n\033[0;37m" +"\033[1;30m -%l- " + "\033[1;30m%m\033[0m%|\033[01;30m%E/%c\33[0m]" ,
+	}
+}
+
+
+Logger.root.writer('console', ConsoleWriter);
+Logger.root.writer('file',FileWriter);
+
+
+var consoleWri = new Logger.root.writers['console'];
+
+
+Logger.root.adapter(new LogAdapter(Logger.eq(Logger.INFO),[consoleWri],Logger.defaults.fmt.info));
+Logger.root.adapter(new LogAdapter(Logger.eq(Logger.ERROR),[consoleWri],Logger.defaults.fmt.error));
+Logger.root.adapter(new LogAdapter(Logger.eq(Logger.WARN),[consoleWri],Logger.defaults.fmt.warn));
+Logger.root.adapter(new LogAdapter(Logger.eq(Logger.VERBOSE),[consoleWri],Logger.defaults.fmt.verbose));
+
+
+

+ 112 - 0
lib/logger.js

@@ -0,0 +1,112 @@
+var LoggerSystem = require('./system');
+var LogWriter = require('./writer');
+var LogAdapter = require('./adapter');
+
+var util = require('util');
+
+var Logger = class Logger {
+
+	constructor(name) {
+		this.name = name;
+		this.lastTime = process.hrtime();
+		this.count = 0;
+	}
+	base(LVL,args) {
+		var msg = args.map(a => (typeof(a) == "object")? util.inspect(a).replace(/\n/g,''):a).join(" ");
+		this.sys.base(this,LVL,msg);
+		this.lastTime = process.hrtime();
+		this.count++;
+	}
+
+	info(...args) {
+		this.base(Logger.INFO,args);
+	}
+	error(...args) {
+		this.base(Logger.ERROR,args);
+	}
+	warn(...args) {
+		this.base(Logger.WARN,args);
+	}
+	verb(...args) {
+		this.base(Logger.VERBOSE,args);
+	}
+}
+
+
+	
+Logger.createLogger = function (name) {
+	var logger = new Logger(name);
+	logger.sys = Logger.root;
+	return logger;
+}
+
+// By order of importance
+Logger.logTags = ["ERROR","WARN","INFO","VERBOSE"];
+for( var i in Logger.logTags) {
+	Logger[Logger.logTags[i]] = i;
+}
+
+// Filter functions
+//
+//
+Logger.le = function(TAG) {
+	return function(itag) {
+		return itag <= TAG;
+	}
+}
+Logger.ge = function(TAG) {
+	return function(itag) {
+		return itag <= TAG;
+	}
+}
+Logger.eq = function(TAG) {
+	return function(itag) {
+		return itag == TAG;
+	}
+};
+Logger.in = function(...args) {
+	var TAGS = args;
+	return function(itag) {
+		return TAGS.indexOf(itag) >= 0;	
+	}
+}
+
+
+Logger.setup = function (conf) {
+	var writerInst = [];	
+
+	conf.adapters.forEach(function(ad) {
+		var levels = [];
+		var adapterWriter = [];
+		ad.writers.forEach(function(e) { // Writer selection
+			// Use same or create new, should be stored in Logger somehow	
+			if(conf.writers[e] == undefined) {
+				throw new Error	("Adapter requested an inexistent writer: '" + e + "'");
+			}
+			if(Logger.root.writers[conf.writers[e].writer] == undefined) {
+				throw new Error ("Requested writer: '" + conf.writers[e].writer + "' does not exists in context");
+			}
+			if(writerInst[e] == undefined) {
+				writerInst[e] = new Logger.root.writers[conf.writers[e].writer](conf.writers[e].opts);
+			}
+		
+			if(writerInst[e] != undefined) {
+				adapterWriter.push( writerInst[e]);
+			};
+		})
+		ad.levels.forEach(function(e) {
+			levels = Logger[e];		
+		});
+		var adapter = new LogAdapter(Logger.in(levels),adapterWriter,ad.fmt);
+		Logger.root.adapter(adapter);
+	})
+}
+
+
+
+module.exports = Logger;
+
+
+
+
+

+ 114 - 0
lib/system.js

@@ -0,0 +1,114 @@
+var LogAdapter = require('./adapter');
+var LogWriter = require('./writer');
+
+
+var LoggerSystem = class LoggerSystem {
+	
+	constructor() {
+		this.adapters = [];
+		this.writers = {};
+		// Prepare TAGS
+		
+		// Global log count? per log
+
+		// Stuff to replace
+		this.logFmt = "[%c]:%t: %m %e";
+	}
+	writer(name,writer) {
+		this.writers[name]= writer;
+	}
+	adapter(adapter) {
+		if(!adapter instanceof LogAdapter) {
+			throw Error("Should be an adapter");
+		}
+		this.adapters.push(adapter);
+		return adapter;
+	}
+	clear() {
+		this.adapters = [];
+	}
+
+	base(logger,TAG,msg) {
+		var self = this;
+		this.adapters.forEach((e) => {
+			if(e.filterFunc(TAG)) {
+				var fmt = e.logFmt || this.logFmt;
+				e.writers.forEach(function(w) {
+					var outmsg = self.format(TAG,w.count,logger.name,w.lastTime,logger.lastTime,fmt,msg);
+
+					// Strip ansi if any
+					w.doLog(outmsg);
+				});
+			}
+		});
+	}
+	
+	format(TAG,count,name,lastDate, lastLoggerDate, fmt, msg) {
+		var now = new Date();
+		var dateStr = (("0" + now.getDate()).slice(-2) 
+									+ "-" + ("0" +now.getMonth()).slice(-2) 
+									+ "-" + now.getFullYear() 
+									+ " " + ("0" + now.getHours()).slice(-2) 
+									+ ":" + ("0" + now.getMinutes()).slice(-2) 
+									+ ":" + ("0"+now.getSeconds()).slice(-2)) ;
+		var dateDiff = (now - lastDate);
+		var dateDiffStr = dateDiff + "ms";
+		if(dateDiff>1000) dateDiffStr = (dateDiff / 1000).toFixed(2) + "s";
+
+		var ldateDiffhr = process.hrtime(lastLoggerDate);
+		var ldateDiff = ( ldateDiffhr[0] * 1000000 + ldateDiffhr[1] / 1000 ) / 1000;
+		var ldateDiffStr = "";
+		if(ldateDiff > 1000) 
+			ldateDiffStr = (ldateDiff / 1000).toFixed(2) + "s";
+		else {
+			ldateDiffStr = ldateDiff.toFixed(2) +"ms";
+		}
+
+		var s = fmt;
+		s = s.replace(/%c/g,count);
+		s = s.replace(/%m/g,msg); 
+		s = s.replace(/%l/g,require('./logger').logTags[TAG]); 
+		s = s.replace(/%n/g,name); 
+		s = s.replace(/%e/g,"+" +dateDiffStr); 
+		s = s.replace(/%E/g,"+" +ldateDiffStr); 
+		s = s.replace(/%t/g,dateStr);
+		s = s.replace(/%%/g,"%"); 
+		s = s.replace(/%a/g,"\x1b");
+		
+
+		var logSplit = s.split("%|");
+		// Might be sloooww
+		if(logSplit.length == 2) {
+			var ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
+
+			var llen = logSplit[0].replace(ansiRegex,"").length;
+			var rlen = logSplit[1].replace(ansiRegex,"").length+1;
+
+			// Only works if it has columns else just give some default
+			var col = process.stdout.columns || 80;
+			var pad = col - llen -rlen;
+
+			s = logSplit[0];
+			for(var i = 0;i<pad;i++) { s+=" "; }
+			s+= " "+logSplit[1];
+		}
+	
+		
+		
+
+
+
+
+
+
+		
+		return s;
+	}
+}
+
+module.exports = LoggerSystem;
+
+
+
+
+

+ 19 - 0
lib/writer.js

@@ -0,0 +1,19 @@
+// Part of Logger
+//
+var Writer = class Writer {
+
+	constructor() {
+		this.count = 0;
+		this.lastTime = new Date();
+	}
+	doLog(msg) {
+		this.count++;
+		this.lastTime = new Date();
+		this.log(msg);
+	}
+	log(msg) {
+		throw Error("Not implemented");
+	}
+
+}
+module.exports = Writer;

+ 19 - 0
lib/writers/console.js

@@ -0,0 +1,19 @@
+var LogWriter = require('../writer');
+
+
+
+class ConsoleWriter extends LogWriter {
+
+
+	log(msg) {
+		process.stdout.write(msg);
+		process.stdout.write("\n");
+	}
+}
+
+
+
+
+
+
+module.exports = ConsoleWriter;

+ 19 - 0
lib/writers/file.js

@@ -0,0 +1,19 @@
+var LogWriter = require('../writer');
+var fs = require('fs');
+
+
+
+class FileWriter extends LogWriter {
+
+		constructor(opt) {
+			super(opt);
+			this.targetFile = opt.path;
+		}
+
+		log(msg) {
+			fs.appendFile(this.targetFile, msg +"\n");
+
+		}
+}
+
+module.exports = FileWriter;

+ 14 - 0
package.json

@@ -0,0 +1,14 @@
+{
+  "name": "hlogger",
+  "version": "0.0.6",
+  "description": "Yet another logger",
+  "main": "index.js",
+  "scripts": {
+    "test": "cd test;node test-conf"
+  },
+  "author": {
+		"email": "luisf@hexasoftware.com",	
+		"name": "Luis Figueiredo"
+	},
+  "license": "ISC"
+}

+ 34 - 0
test/test-conf/conf.json

@@ -0,0 +1,34 @@
+{
+	"writers" : {
+		"filetolog":{
+			"writer":"file",
+			"opts":{
+				"path":"log3.txt"
+			}
+		},
+		"errorfile": {
+			"writer":"file",
+			"opts": {
+				"path":"error3.txt"
+			}
+		},
+		"console1": {
+			"writer":"console",
+			"opts":{}
+		}
+	},
+
+	"adapters" : [
+		{
+			"levels": ["ERROR","WARN","INFO"],
+			"fmt": "[%c:%n -%l-  %m %| %E/%c]",
+			"writers": ["filetolog"]
+		},
+		{ 
+			"levels":["ERROR"],
+			"fmt": "ERR - %m",
+			"writers": ["errorfile","console1"]
+		}
+	]
+}
+

+ 31 - 0
test/test-conf/index.js

@@ -0,0 +1,31 @@
+var Logger = require('../../'); // Require logger
+
+
+
+var log = Logger.createLogger("Hello");
+
+log.info("World");
+
+log.error("This will log an error with default adapters");
+
+
+log.verb("Application initiating");
+
+log.info("Loading loggers from config");
+Logger.setup(require('./conf.json'));
+
+
+log.info("Now writing logs with config loaded");
+log.error("Error log");
+log.warn("Warning");
+log.verb("Verbose");
+
+
+var obj = {
+	test: {
+		msg: 'testing depth'
+	},
+	arr:[1,2,3]
+}
+
+log.info("Testing: ", obj);