├── .gitignore ├── settings.json ├── .travis.yml ├── CHANGELOG.md ├── .versions ├── package.js ├── ObjectLogger.coffee ├── LoggerFactory.coffee ├── tests ├── ObjectLoggerTest.coffee └── LoggerFactoryTest.coffee ├── LICENSE.txt ├── README.md └── loglevel-1.2.0.js /.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | -------------------------------------------------------------------------------- /settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "loglevel": "debug", 3 | "public": { 4 | "loglevel": "info" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10.36" 4 | 5 | before_install: 6 | - "curl https://install.meteor.com | /bin/sh" 7 | - "npm install -g spacejam" 8 | 9 | script: "spacejam test-packages ./" 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.2.0_1 2 | 3 | * Upgrade to loglevel 1.2.0. 4 | * Add fine loglevel, between trace and debug. 5 | * Add setPrefix method. 6 | * Add ObjectLogger with .enter, .fineEnter, .return and .fineReturn that auto sets prefix to ClassName.MethodName on every enter and return. 7 | -------------------------------------------------------------------------------- /.versions: -------------------------------------------------------------------------------- 1 | base64@1.0.3 2 | binary-heap@1.0.3 3 | callback-hook@1.0.3 4 | check@1.0.5 5 | coffeescript@1.0.6 6 | ddp@1.1.0 7 | ejson@1.0.6 8 | geojson-utils@1.0.3 9 | id-map@1.0.3 10 | jquery@1.11.3_2 11 | json@1.0.3 12 | local-test:practicalmeteor:loglevel@1.2.0_2 13 | logging@1.0.7 14 | meteor@1.1.6 15 | minimongo@1.0.8 16 | mongo@1.1.0 17 | ordered-dict@1.0.3 18 | practicalmeteor:chai@2.1.0_1 19 | practicalmeteor:loglevel@1.2.0_2 20 | practicalmeteor:munit@2.1.5 21 | practicalmeteor:sinon@1.14.1_2 22 | random@1.0.3 23 | retry@1.0.3 24 | test-helpers@1.0.4 25 | tinytest@1.0.5 26 | tracker@1.0.7 27 | underscore@1.0.3 28 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: "practicalmeteor:loglevel", 3 | summary: "Simple logger with app and per-package log levels and line number preserving output.", 4 | version: "1.2.0_2", 5 | git: "https://github.com/practicalmeteor/meteor-loglevel.git" 6 | }); 7 | 8 | 9 | Package.onUse(function (api) { 10 | api.versionsFrom('0.9.3'); 11 | 12 | api.use(['meteor', 'coffeescript']); 13 | 14 | api.use(['practicalmeteor:chai@2.1.0_1']); 15 | 16 | api.addFiles('loglevel-1.2.0.js'); 17 | api.addFiles('LoggerFactory.coffee'); 18 | api.addFiles('ObjectLogger.coffee'); 19 | 20 | api.export(['loglevel', 'ObjectLogger']); 21 | }); 22 | 23 | 24 | Package.onTest(function(api) { 25 | api.use(['coffeescript', 'practicalmeteor:loglevel@1.2.0_2', 'practicalmeteor:munit@2.1.5']); 26 | 27 | api.addFiles('tests/LoggerFactoryTest.coffee'); 28 | api.addFiles('tests/ObjectLoggerTest.coffee'); 29 | }); 30 | -------------------------------------------------------------------------------- /ObjectLogger.coffee: -------------------------------------------------------------------------------- 1 | class ObjectLogger 2 | 3 | constructor:(@className, @defaultLevel = 'info')-> 4 | 5 | @log = loglevel.createLogger(@className, @defaultLevel) 6 | 7 | @callStack = [] 8 | 9 | @log.enter = @bindMethod(@enter, 'debug') 10 | @log.fineEnter = @bindMethod(@enter, 'fine') 11 | @log.return = @bindMethod(@return, 'debug') 12 | @log.fineReturn = @bindMethod(@return, 'fine') 13 | 14 | return @log 15 | 16 | enter: (level, args...)-> 17 | throw new Error ('ObjectLogger: No method name provided to enter') if args.length is 0 18 | methodName = args.shift() 19 | @callStack.unshift methodName 20 | @log.setPrefix "#{@className}.#{methodName}:" 21 | args.unshift 'ENTER' 22 | @log[level].apply @log, args 23 | 24 | return: (level)-> 25 | @log[level].call @log, 'RETURN' 26 | @callStack.shift() 27 | if @callStack.length > 0 28 | methodName = @callStack[0] 29 | @log.setPrefix "#{@className}.#{methodName}:" 30 | 31 | 32 | bindMethod: (method, level) -> 33 | if typeof method.bind == 'function' 34 | return method.bind(@, level) 35 | else 36 | try 37 | return Function::bind.call(method, @, level) 38 | catch e 39 | # Missing bind shim or IE8 + Modernizr, fallback to wrapping 40 | return (args...)=> 41 | args.unshift(level) 42 | Function::apply.apply method, [ 43 | @ 44 | args 45 | ] 46 | -------------------------------------------------------------------------------- /LoggerFactory.coffee: -------------------------------------------------------------------------------- 1 | @practical ?= {} 2 | 3 | class practical.LoggerFactory 4 | 5 | instance = null 6 | 7 | @get: -> 8 | instance ?= new practical.LoggerFactory() 9 | 10 | # The 'global' namespace is checked first, in order to allow people to enforce 11 | # a loglevel across the board. 12 | _getSettingsLoglevel: (namespace = '', defaultLevel = 'info')-> 13 | expect(namespace).to.be.a('string') 14 | expect(defaultLevel).to.be.a('string').that.has.length.above(0) 15 | globalLevel = @_getNamespaceLoglevel('global') 16 | return globalLevel if globalLevel? 17 | level = @_getNamespaceLoglevel(namespace) if namespace.length > 0 18 | level ?= @_getNamespaceLoglevel('default') 19 | level ?= defaultLevel 20 | 21 | # @returns Meteor.settings.loglevel.namespace server side 22 | # or if called client side or it doesn't exist server side, 23 | # Meteor.settings.public.loglevel.namespace. 24 | # This allows to set only public loglevel for both client and server side. 25 | _getNamespaceLoglevel: (namespace)-> 26 | expect(namespace).to.be.a('string').that.has.length.above(0) 27 | level = Meteor.settings?.public?.loglevel?[namespace] 28 | if Meteor.isServer 29 | serverLevel = Meteor.settings?.loglevel?[namespace] 30 | level = serverLevel if serverLevel? 31 | return level 32 | 33 | createLogger: (namespace = '', defaultLevel = 'info')-> 34 | log.debug 'LoggerFactory.createLogger()', arguments 35 | expect(namespace).to.be.a('string') 36 | expect(defaultLevel).to.be.a('string').that.has.length.above(0) 37 | expect(Loglevel).to.be.a 'function' 38 | 39 | options = {} 40 | options.prefix = namespace + ':' if namespace.length > 0 41 | options.level = @_getSettingsLoglevel(namespace, defaultLevel) 42 | return Loglevel(options) 43 | 44 | createPackageLogger: (packageName, defaultLevel = 'info')-> 45 | return @createLogger(packageName, defaultLevel) 46 | 47 | createAppLogger: (appName = 'app', defaultLevel = 'info')-> 48 | return @createLogger(appName, defaultLevel) 49 | 50 | loglevel = practical.LoggerFactory.get() 51 | -------------------------------------------------------------------------------- /tests/ObjectLoggerTest.coffee: -------------------------------------------------------------------------------- 1 | class ObjectLoggerTest 2 | 3 | setup: -> 4 | 5 | tearDown: -> 6 | 7 | createObjectLogger = (className, defaultLevel)-> 8 | logger = new ObjectLogger(className, defaultLevel) 9 | 10 | logAllLevels = (logger, msg)-> 11 | for level in ['trace', 'fine', 'debug', 'info', 'warn', 'error'] 12 | logger[level](level.toUpperCase(), '-', msg) 13 | 14 | tests:[ 15 | { 16 | name:"should log all levels" 17 | func: (test)-> 18 | logger = new ObjectLogger('Class1', 'trace') 19 | logAllLevels logger, 'loglevel is trace' 20 | } 21 | { 22 | name:"setLevel() - should work" 23 | func: (test)-> 24 | logger = new ObjectLogger('Class2') 25 | logger.setLevel('debug') 26 | logAllLevels logger, 'loglevel is debug' 27 | } 28 | { 29 | name:"enter() - should work" 30 | func: (test)-> 31 | logger = new ObjectLogger('Class3', 'debug') 32 | logger.enter 'method1', 'loglevel is debug' 33 | logAllLevels logger, 'loglevel is debug' 34 | logger.return() 35 | } 36 | { 37 | name:"enter() - should work recursively" 38 | func: (test)-> 39 | logger = new ObjectLogger('Class4') 40 | logger.enter 'method1', 'loglevel is info' 41 | logger.info 'method1' 42 | logger.enter 'method2', 'loglevel is info' 43 | logger.info 'method2' 44 | logger.return() 45 | logger.info 'back to method1' 46 | logger.return() 47 | } 48 | { 49 | name:"fineEnter() - should work" 50 | func: (test)-> 51 | logger = new ObjectLogger('Class5', 'fine') 52 | logger.enter 'method1', 'loglevel is fine' 53 | logAllLevels logger, 'loglevel is fine' 54 | logger.return() 55 | } 56 | { 57 | name:"fineEnter() - should work recursively" 58 | func: (test)-> 59 | logger = new ObjectLogger('Class6') 60 | logger.fineEnter 'method1', 'loglevel is info' 61 | logger.info 'method1' 62 | logger.fineEnter 'method2', 'loglevel is info' 63 | logger.info 'method2' 64 | logger.fineReturn() 65 | logger.info 'back to method1' 66 | logger.fineReturn() 67 | } 68 | ] 69 | 70 | 71 | 72 | Munit.run( new ObjectLoggerTest()) 73 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 LaVaina Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | loglevel Licence 24 | ================ 25 | 26 | Copyright (c) 2013 Tim Perry 27 | 28 | Permission is hereby granted, free of charge, to any person 29 | obtaining a copy of this software and associated documentation 30 | files (the "Software"), to deal in the Software without 31 | restriction, including without limitation the rights to use, 32 | copy, modify, merge, publish, distribute, sublicense, and/or sell 33 | copies of the Software, and to permit persons to whom the 34 | Software is furnished to do so, subject to the following 35 | conditions: 36 | 37 | The above copyright notice and this permission notice shall be 38 | included in all copies or substantial portions of the Software. 39 | 40 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 41 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 42 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 43 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 44 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 45 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 46 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 47 | OTHER DEALINGS IN THE SOFTWARE. 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/practicalmeteor/meteor-loglevel.svg?branch=master)](https://travis-ci.org/practicalmeteor/meteor-loglevel) 2 | 3 | ## Overview 4 | 5 | A minimal lightweight console logger that preserves line numbers and supports per-package and app specific prefixes and log levels that are read from Meteor.settings. Based on the [loglevel.js](https://github.com/pimterry/loglevel) logging library. 6 | 7 | ## API summary 8 | 9 | ```javascript 10 | 11 | // Creating loggers 12 | log = loglevel.createPackageLogger(packageName, defaultLevel = 'info'); 13 | log = loglevel.createAppLogger(appName, defaultLevel = 'info'); 14 | log = loglevel.createLogger(namespace = '', defaultLevel = 'info'); 15 | 16 | // Logging 17 | log.trace(msg); 18 | log.fine(obj); 19 | log.debug(obj); 20 | log.info(msg1 + msg2); 21 | log.warn('obj=\n', obj); 22 | log.error(err); 23 | 24 | // Set the log level 25 | log.setLevel(level); // Any of the levels above. 26 | log.enableAll(); 27 | log.disableAll(); 28 | ``` 29 | 30 | Logging methods will use the same console method or fallback to console.log, if not defined. 31 | 32 | # Creating a package scoped logger 33 | 34 | Add to your package a log.js file that is loaded before any other source files with the following line: 35 | 36 | ```javascript 37 | 38 | log = loglevel.createPackageLogger('myacct:mypkg', 'debug'); 39 | ``` 40 | 41 | Note: It must be a .js file, not a .coffee file. 42 | 43 | Then, use it in any other source file, js or coffee: 44 | 45 | ```javascript 46 | 47 | log.debug('Hello world'); 48 | // Output: 49 | // myacct:mypkg: Hello world 50 | ``` 51 | 52 | All log messages will be prefixed with the package name and a colon, so package authors and users can easily identify the source of the log message. 53 | 54 | ## Creating an app logger 55 | 56 | Add to your app's lib folder a .js file that is loaded before any other source files in your app with the following line: 57 | 58 | ```javascript 59 | 60 | log = loglevel.createAppLogger('myapp', 'warn'); 61 | ``` 62 | 63 | Then, use it in any other source file, js or coffee: 64 | 65 | ```javascript 66 | 67 | log.warn('Hello world!'); 68 | // Output: 69 | // myapp: Hello world! 70 | ``` 71 | 72 | Here too, all log messages will be prefixed with the app name and a colon. If you prefer not to have app log messages prefixed, just set appName to an empty string. 73 | 74 | ## Creating a namespaced logger 75 | 76 | If you'd like to create additional loggers, such as for javascript objects or coffeescript classes, just create a logger at the top of your source file: 77 | 78 | ```javascript 79 | 80 | log = loglevel.createLogger('myacct:mypkg:myobject', 'trace'); 81 | // Or 82 | log = loglevel.createLogger('myapp.myclass', 'trace'); 83 | ``` 84 | 85 | ## Setting log levels in Meteor.settings 86 | 87 | Just create a key under Meteor.settings.loglevel (server side) or Meteor.settings.public.loglevel (client side) with your package, app or namespace name: 88 | 89 | ```javascript 90 | 91 | Meteor.settings.loglevel['myacct:mypkg'] 92 | Meteor.settings.public.loglevel['myyapp'] 93 | Meteor.settings.public.loglevel['myyapp.myclass'] 94 | ``` 95 | 96 | Note that server side, if a key will not be found under Meteor.settings.loglevel, the client side log level will be used. This allows you to control the log level both server side and client side by setting it only under Meteor.settings.public.loglevel. 97 | 98 | ## Forcing a global log level 99 | 100 | Meteor.settings.loglevel.global - server side. 101 | 102 | Meteor.settings.public.loglevel.global - client side (or if server side global isn't set, server side too). 103 | 104 | This will overwrite all log levels for all loggers. 105 | 106 | ## Specifying a default log level 107 | 108 | Meteor.settings.loglevel.default - server side. 109 | 110 | Meteor.settings.public.loglevel.default - client side (or if server side default isn't set, server side too). 111 | 112 | This will be used, if no other log level was found in Meteor.settings. 113 | 114 | ## Coming soon / please contribute 115 | 116 | 1. Hierarchical namespace log levels - so package authors can control log levels for all their packages with one setting and app authors can control log levels for submodules / subsystems. 117 | 118 | 2. User specific log levels. 119 | 120 | ## Changelog 121 | 122 | [CHANGELOG](https://github.com/practicalmeteor/meteor-loglevel/blob/master/CHANGELOG.md) 123 | 124 | ## License 125 | 126 | practicalmeteor:loglevel - [MIT](https://github.com/practicalmeteor/meteor-loglevel/blob/master/LICENSE.txt) 127 | 128 | loglevel.js - [MIT](https://github.com/pimterry/loglevel/blob/master/LICENSE-MIT) 129 | -------------------------------------------------------------------------------- /loglevel-1.2.0.js: -------------------------------------------------------------------------------- 1 | /*! loglevel - v1.2.0 - https://github.com/pimterry/loglevel - (c) 2014 Tim Perry - licensed MIT */ 2 | 3 | Loglevel = function (options) { 4 | var self = {}; 5 | if(options && options.prefix) { 6 | self.prefix = options.prefix; 7 | } else { 8 | self.prefix = ''; 9 | } 10 | if(options && options.level) { 11 | self.level = options.level; 12 | } else { 13 | self.level = 'info'; 14 | } 15 | var noop = function() {}; 16 | var undefinedType = "undefined"; 17 | 18 | function realMethod(methodName) { 19 | if (typeof console === undefinedType) { 20 | return false; // We can't build a real method without a console to log to 21 | } else if (console[methodName] !== undefined) { 22 | return bindMethod(console, methodName); 23 | } else if (console.log !== undefined) { 24 | return bindMethod(console, 'log'); 25 | } else { 26 | return noop; 27 | } 28 | } 29 | 30 | function bindMethod(obj, methodName) { 31 | var method = obj[methodName]; 32 | if (typeof method.bind === 'function') { 33 | return method.bind(obj, self.prefix); 34 | } else { 35 | try { 36 | return Function.prototype.bind.call(method, obj, self.prefix); 37 | } catch (e) { 38 | // Missing bind shim or IE8 + Modernizr, fallback to wrapping 39 | return function() { 40 | return Function.prototype.apply.apply(method, [obj, arguments]); 41 | }; 42 | } 43 | } 44 | } 45 | 46 | function enableLoggingWhenConsoleArrives(methodName, level) { 47 | return function () { 48 | if (typeof console !== undefinedType) { 49 | replaceLoggingMethods(level); 50 | self[methodName].apply(self, arguments); 51 | } 52 | }; 53 | } 54 | 55 | var logMethods = [ 56 | "trace", 57 | "fine", 58 | "debug", 59 | "info", 60 | "warn", 61 | "error" 62 | ]; 63 | 64 | function replaceLoggingMethods(level) { 65 | for (var i = 0; i < logMethods.length; i++) { 66 | var methodName = logMethods[i]; 67 | self[methodName] = (i < level) ? noop : self.methodFactory(methodName, level); 68 | } 69 | } 70 | 71 | function persistLevelIfPossible(levelNum) { 72 | var levelName = (logMethods[levelNum] || 'silent').toUpperCase(); 73 | 74 | // Use localStorage if available 75 | try { 76 | window.localStorage['loglevel'] = levelName; 77 | return; 78 | } catch (ignore) {} 79 | 80 | // Use session cookie as fallback 81 | try { 82 | window.document.cookie = "loglevel=" + levelName + ";"; 83 | } catch (ignore) {} 84 | } 85 | 86 | function loadPersistedLevel() { 87 | var storedLevel; 88 | 89 | try { 90 | storedLevel = window.localStorage['loglevel']; 91 | } catch (ignore) {} 92 | 93 | if (typeof storedLevel === undefinedType) { 94 | try { 95 | storedLevel = /loglevel=([^;]+)/.exec(window.document.cookie)[1]; 96 | } catch (ignore) {} 97 | } 98 | 99 | if (self.levels[storedLevel] === undefined) { 100 | storedLevel = "WARN"; 101 | } 102 | 103 | self.setLevel(self.levels[storedLevel]); 104 | } 105 | 106 | /* 107 | * 108 | * Public API 109 | * 110 | */ 111 | 112 | self.levels = { "TRACE": 0, "FINE": 1, "DEBUG": 2, "INFO": 3, "WARN": 4, 113 | "ERROR": 5, "SILENT": 6}; 114 | 115 | self.methodFactory = function (methodName, level) { 116 | return realMethod(methodName) || 117 | enableLoggingWhenConsoleArrives(methodName, level); 118 | }; 119 | 120 | self.setLevel = function (level) { 121 | if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) { 122 | level = self.levels[level.toUpperCase()]; 123 | } 124 | if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) { 125 | //persistLevelIfPossible(level); 126 | self.level = level; 127 | replaceLoggingMethods(level); 128 | if (typeof console === undefinedType && level < self.levels.SILENT) { 129 | return "No console available for logging"; 130 | } 131 | } else { 132 | throw "log.setLevel() called with invalid level: " + level; 133 | } 134 | }; 135 | 136 | self.enableAll = function() { 137 | self.setLevel(self.levels.TRACE); 138 | }; 139 | 140 | self.disableAll = function() { 141 | self.setLevel(self.levels.SILENT); 142 | }; 143 | 144 | // Grab the current global log variable in case of overwrite 145 | var _log = (typeof window !== undefinedType) ? window.log : undefined; 146 | self.noConflict = function() { 147 | if (typeof window !== undefinedType && 148 | window.log === self) { 149 | window.log = _log; 150 | } 151 | 152 | return self; 153 | }; 154 | 155 | self.setPrefix = function(prefix) { 156 | if(typeof prefix === undefinedType || prefix === null) { 157 | prefix = ''; 158 | } 159 | self.prefix = prefix; 160 | self.setLevel(self.level); 161 | }; 162 | 163 | //loadPersistedLevel(); 164 | self.setLevel(self.level); 165 | return self; 166 | }; 167 | 168 | log = Loglevel({prefix: 'practicalmeteor:loglevel:'}); 169 | -------------------------------------------------------------------------------- /tests/LoggerFactoryTest.coffee: -------------------------------------------------------------------------------- 1 | describe "loglevel", -> 2 | 3 | meteorSettings = Meteor.settings 4 | 5 | logAllLevels = (log)-> 6 | log.trace("1 I'm log.trace"); 7 | log.fine("2 I'm log.fine"); 8 | log.debug("3 I'm log.debug"); 9 | log.info("4 I'm log.info"); 10 | log.warn("5 I'm log.warn"); 11 | log.error("6 I'm log.error"); 12 | 13 | beforeEach -> 14 | Meteor.settings = {} 15 | 16 | afterEach -> 17 | spies.restoreAll() 18 | 19 | afterAll -> 20 | spies.restoreAll() 21 | Meteor.settings = meteorSettings 22 | 23 | it 'setPrefix - should work', -> 24 | log = loglevel.createLogger() 25 | log.info ('Without prefix') 26 | log.setPrefix('My prefix:') 27 | log.info('With prefix') 28 | 29 | describe "_getNamespaceLoglevel", -> 30 | 31 | it.client 'should return public loglevel client side', -> 32 | Meteor.settings = 33 | loglevel: 34 | 'acct:pkg': 'trace' 35 | public: 36 | loglevel: 37 | 'acct:pkg': 'debug' 38 | expect(loglevel._getNamespaceLoglevel('acct:pkg')).to.equal 'debug' 39 | 40 | it.server 'should return server loglevel server side', -> 41 | Meteor.settings = 42 | loglevel: 43 | 'acct:pkg': 'trace' 44 | public: 45 | loglevel: 46 | 'acct:pkg': 'debug' 47 | expect(loglevel._getNamespaceLoglevel('acct:pkg')).to.equal 'trace' 48 | 49 | it.server 'should return public loglevel server side, if no server loglevel', -> 50 | Meteor.settings = 51 | public: 52 | loglevel: 53 | 'acct:pkg': 'debug' 54 | expect(loglevel._getNamespaceLoglevel('acct:pkg')).to.equal 'debug' 55 | 56 | it 'should return undefined, if no loglevel', -> 57 | Meteor.settings = {} 58 | expect(loglevel._getNamespaceLoglevel('acct:pkg')).to.be.undefined 59 | 60 | describe "_getSettingsLoglevel", -> 61 | 62 | it 'should return global loglevel, if set', -> 63 | Meteor.settings = 64 | loglevel: 65 | 'global': 'info' 66 | 'acct:pkg': 'trace' 67 | public: 68 | loglevel: 69 | 'global': 'warn' 70 | 'acct:pkg': 'debug' 71 | if Meteor.isServer 72 | expect(loglevel._getSettingsLoglevel('acct:pkg')).to.equal 'info' 73 | else 74 | expect(loglevel._getSettingsLoglevel('acct:pkg')).to.equal 'warn' 75 | 76 | it 'should return namespace loglevel, if set', -> 77 | Meteor.settings = 78 | loglevel: 79 | 'acct:pkg': 'trace' 80 | public: 81 | loglevel: 82 | 'acct:pkg': 'debug' 83 | if Meteor.isServer 84 | expect(loglevel._getSettingsLoglevel('acct:pkg')).to.equal 'trace' 85 | else 86 | expect(loglevel._getSettingsLoglevel('acct:pkg')).to.equal 'debug' 87 | 88 | it 'should return default loglevel from settings, if set', -> 89 | Meteor.settings = 90 | loglevel: 91 | 'default': 'warn' 92 | public: 93 | loglevel: 94 | 'default': 'error' 95 | if Meteor.isServer 96 | expect(loglevel._getSettingsLoglevel('acct:pkg')).to.equal 'warn' 97 | else 98 | expect(loglevel._getSettingsLoglevel('acct:pkg')).to.equal 'error' 99 | 100 | it 'should return default loglevel from input arg, if no settings loglevel', -> 101 | Meteor.settings = {} 102 | expect(loglevel._getSettingsLoglevel('acct:pkg', 'debug')).to.equal 'debug' 103 | 104 | it 'should deal with empty namespaces', -> 105 | Meteor.settings = 106 | loglevel: 107 | 'default': 'warn' 108 | public: 109 | loglevel: 110 | 'default': 'error' 111 | if Meteor.isServer 112 | expect(loglevel._getSettingsLoglevel()).to.equal 'warn' 113 | else 114 | expect(loglevel._getSettingsLoglevel()).to.equal 'error' 115 | 116 | describe "createLogger", -> 117 | 118 | it "should set prefix to an empty string, if not specified", -> 119 | log = loglevel.createLogger() 120 | expect(log.prefix).to.equal '' 121 | 122 | it "should set prefix to namespace + ':'", -> 123 | log = loglevel.createLogger('loglevel:namespace') 124 | expect(log.prefix).to.equal 'loglevel:namespace:' 125 | log.enableAll() 126 | logAllLevels(log) 127 | 128 | it "should set level to info, if not specified", -> 129 | log = loglevel.createLogger() 130 | expect(log.level).to.equal log.levels.INFO 131 | 132 | it "should set level to debug, if specified", -> 133 | log = loglevel.createLogger('', 'debug') 134 | expect(log.level).to.equal log.levels.DEBUG 135 | 136 | it 'should output only log levels enabled by default', -> 137 | log = loglevel.createLogger() 138 | logAllLevels(log) 139 | 140 | it 'should output all log levels', -> 141 | log = loglevel.createLogger() 142 | log.enableAll() 143 | logAllLevels(log) 144 | 145 | describe "createPackageLogger", -> 146 | it "should set prefix to package name", -> 147 | log = loglevel.createPackageLogger('loglevel:mypackage') 148 | expect(log.prefix).to.equal('loglevel:mypackage:') 149 | log.enableAll() 150 | log.trace("1 I'm log.trace") 151 | log.fine("2 I'm log.fine") 152 | log.debug("3 I'm log.debug") 153 | log.info("4 I'm log.info") 154 | log.warn("5 I'm log.warn") 155 | log.error("6 I'm log.error") 156 | 157 | it "should read level from Meteor.settings", -> 158 | Meteor.settings = 159 | loglevel: 160 | 'acct:pkg': 'trace' 161 | public: 162 | loglevel: 163 | 'acct:pkg': 'debug' 164 | log = loglevel.createLogger('acct:pkg') 165 | if Meteor.isServer 166 | expect(log.level).to.equal log.levels.TRACE 167 | else 168 | expect(log.level).to.equal log.levels.DEBUG 169 | 170 | describe "createAppLogger", -> 171 | it "should set prefix to app name", -> 172 | log = loglevel.createAppLogger('myapp') 173 | expect(log.prefix).to.equal('myapp:') 174 | log.enableAll() 175 | log.trace("1 I'm log.trace") 176 | log.fine("2 I'm log.fine") 177 | log.debug("3 I'm log.debug") 178 | log.info("4 I'm log.info") 179 | log.warn("5 I'm log.warn") 180 | log.error("6 I'm log.error") 181 | --------------------------------------------------------------------------------