UNPKG

6.74 kBJavaScriptView Raw
1/*
2* loglevel - https://github.com/pimterry/loglevel
3*
4* Copyright (c) 2013 Tim Perry
5* Licensed under the MIT license.
6*/
7(function (root, definition) {
8 "use strict";
9 if (typeof define === 'function' && define.amd) {
10 define(definition);
11 } else if (typeof module === 'object' && module.exports) {
12 module.exports = definition();
13 } else {
14 root.log = definition();
15 }
16}(this, function () {
17 "use strict";
18 var noop = function() {};
19 var undefinedType = "undefined";
20
21 function realMethod(methodName) {
22 if (typeof console === undefinedType) {
23 return false; // We can't build a real method without a console to log to
24 } else if (console[methodName] !== undefined) {
25 return bindMethod(console, methodName);
26 } else if (console.log !== undefined) {
27 return bindMethod(console, 'log');
28 } else {
29 return noop;
30 }
31 }
32
33 function bindMethod(obj, methodName) {
34 var method = obj[methodName];
35 if (typeof method.bind === 'function') {
36 return method.bind(obj);
37 } else {
38 try {
39 return Function.prototype.bind.call(method, obj);
40 } catch (e) {
41 // Missing bind shim or IE8 + Modernizr, fallback to wrapping
42 return function() {
43 return Function.prototype.apply.apply(method, [obj, arguments]);
44 };
45 }
46 }
47 }
48
49 // these private functions always need `this` to be set properly
50
51 function enableLoggingWhenConsoleArrives(methodName, level, loggerName) {
52 return function () {
53 if (typeof console !== undefinedType) {
54 replaceLoggingMethods.call(this, level, loggerName);
55 this[methodName].apply(this, arguments);
56 }
57 };
58 }
59
60 function replaceLoggingMethods(level, loggerName) {
61 /*jshint validthis:true */
62 for (var i = 0; i < logMethods.length; i++) {
63 var methodName = logMethods[i];
64 this[methodName] = (i < level) ?
65 noop :
66 this.methodFactory(methodName, level, loggerName);
67 }
68 }
69
70 function defaultMethodFactory(methodName, level, loggerName) {
71 /*jshint validthis:true */
72 return realMethod(methodName) ||
73 enableLoggingWhenConsoleArrives.apply(this, arguments);
74 }
75
76 var logMethods = [
77 "trace",
78 "debug",
79 "info",
80 "warn",
81 "error"
82 ];
83
84 function Logger(name, defaultLevel, factory) {
85 var self = this;
86 var currentLevel;
87 var storageKey = "loglevel";
88 if (name) {
89 storageKey += ":" + name;
90 }
91
92 function persistLevelIfPossible(levelNum) {
93 var levelName = (logMethods[levelNum] || 'silent').toUpperCase();
94
95 // Use localStorage if available
96 try {
97 window.localStorage[storageKey] = levelName;
98 return;
99 } catch (ignore) {}
100
101 // Use session cookie as fallback
102 try {
103 window.document.cookie =
104 encodeURIComponent(storageKey) + "=" + levelName + ";";
105 } catch (ignore) {}
106 }
107
108 function getPersistedLevel() {
109 var storedLevel;
110
111 try {
112 storedLevel = window.localStorage[storageKey];
113 } catch (ignore) {}
114
115 if (typeof storedLevel === undefinedType) {
116 try {
117 var cookie = window.document.cookie;
118 var location = cookie.indexOf(
119 encodeURIComponent(storageKey) + "=");
120 if (location) {
121 storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1];
122 }
123 } catch (ignore) {}
124 }
125
126 // If the stored level is not valid, treat it as if nothing was stored.
127 if (self.levels[storedLevel] === undefined) {
128 storedLevel = undefined;
129 }
130
131 return storedLevel;
132 }
133
134 /*
135 *
136 * Public API
137 *
138 */
139
140 self.levels = { "TRACE": 0, "DEBUG": 1, "INFO": 2, "WARN": 3,
141 "ERROR": 4, "SILENT": 5};
142
143 self.methodFactory = factory || defaultMethodFactory;
144
145 self.getLevel = function () {
146 return currentLevel;
147 };
148
149 self.setLevel = function (level, persist) {
150 if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
151 level = self.levels[level.toUpperCase()];
152 }
153 if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
154 currentLevel = level;
155 if (persist !== false) { // defaults to true
156 persistLevelIfPossible(level);
157 }
158 replaceLoggingMethods.call(self, level, name);
159 if (typeof console === undefinedType && level < self.levels.SILENT) {
160 return "No console available for logging";
161 }
162 } else {
163 throw "log.setLevel() called with invalid level: " + level;
164 }
165 };
166
167 self.setDefaultLevel = function (level) {
168 if (!getPersistedLevel()) {
169 self.setLevel(level, false);
170 }
171 };
172
173 self.enableAll = function(persist) {
174 self.setLevel(self.levels.TRACE, persist);
175 };
176
177 self.disableAll = function(persist) {
178 self.setLevel(self.levels.SILENT, persist);
179 };
180
181 // Initialize with the right level
182 var initialLevel = getPersistedLevel();
183 if (initialLevel == null) {
184 initialLevel = defaultLevel == null ? "WARN" : defaultLevel;
185 }
186 self.setLevel(initialLevel, false);
187 }
188
189 /*
190 *
191 * Package-level API
192 *
193 */
194
195 var defaultLogger = new Logger();
196
197 var _loggersByName = {};
198 defaultLogger.getLogger = function getLogger(name) {
199 if (typeof name !== "string" || name === "") {
200 throw new TypeError("You must supply a name when creating a logger.");
201 }
202
203 var logger = _loggersByName[name];
204 if (!logger) {
205 logger = _loggersByName[name] = new Logger(
206 name, defaultLogger.getLevel(), defaultLogger.methodFactory);
207 }
208 return logger;
209 };
210
211 // Grab the current global log variable in case of overwrite
212 var _log = (typeof window !== undefinedType) ? window.log : undefined;
213 defaultLogger.noConflict = function() {
214 if (typeof window !== undefinedType &&
215 window.log === defaultLogger) {
216 window.log = _log;
217 }
218
219 return defaultLogger;
220 };
221
222 return defaultLogger;
223}));