2 lines
10 KiB
Plaintext
2 lines
10 KiB
Plaintext
)]}'
|
|
{"version":3,"sources":["logging/logging.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mB;AACA,yC;AACA,E;;AAEA,e;AACA,kB;AACA,0B;AACA,iB;;AAEA,iE;AACA,kE;AACA,sB;AACA,mC;AACA,qB;AACA,E;;AAEA,sE;AACA,mE;AACA,kC;AACA,kC;AACA,oB;AACA,E;;AAEA,8D;AACA,gC;AACA,+B;AACA,wB;AACA,gB;AACA,e;AACA,E;;AAEA,mC;AACA,E;AACA,8E;AACA,wE;AACA,gC;AACA,E;AACA,yE;AACA,2E;AACA,0D;AACA,0B;;AAEA,oB;AACA,iB;AACA,oC;AACA,kB;AACA,c;AACA,E;;AAEA,wB;;AAEA,c;AACA,sE;AACA,uE;;AAEA,gE;;AAEA,mC;AACA,4B;;AAEA,6D;AACA,wB;;AAEA,2D;AACA,wB;AACA,U;AACA,4E;AACA,yE;AACA,kC;AACA,uB;AACA,G;AACA,E;;AAEA,oD;AACA,qC;AACA,8B;AACA,gF;AACA,4E;AACA,kE;AACA,wB;AACA,0B;AACA,iB;AACA,I;;AAEA,yB;;AAEA,wB;;AAEA,gC;;AAEA,kE;AACA,gC;AACA,W;AACA,0C;AACA,oB;AACA,2C;AACA,4B;AACA,K;;AAEA,oE;AACA,Y;AACA,G;;AAEA,mB;;AAEA,4D;AACA,4E;AACA,0D;AACA,mE;AACA,a;AACA,mB;AACA,kD;AACA,wC;;AAEA,uE;AACA,oE;AACA,2B;AACA,gE;;AAEA,iB;AACA,E;;AAEA,6D;AACA,+B;AACA,+B;AACA,mB;AACA,iB;AACA,a;AACA,K;;AAEA,4B;AACA,oB;AACA,kB;AACA,yB;AACA,K;;AAEA,wE;AACA,2D;;AAEA,4C;AACA,mB;AACA,kE;AACA,O;;AAEA,0D;AACA,6E;AACA,+B;AACA,mD;AACA,0B;AACA,sB;;AAEA,4D;AACA,0B;AACA,a;;AAEA,sB;AACA,kD;AACA,iC;AACA,gD;AACA,oD;AACA,+C;AACA,0C;AACA,c;AACA,8E;AACA,O;AACA,Y;AACA,wB;AACA,K;AACA,I;AACA,G;;AAEA,sF;AACA,6B;AACA,iB;AACA,qF;AACA,iD;AACA,G;;AAEA,uD;AACA,oD;AACA,e;AACA,M;AACA,gB;AACA,E;;AAEA,oE;AACA,sC;AACA,sD;AACA,0B;;AAEA,sB;AACA,8B;AACA,oD;AACA,oC;;AAEA,gE;AACA,kC;AACA,sB;AACA,4B;AACA,8B;AACA,gC;AACA,kC;AACA,kC;AACA,gC;AACA,gC;;AAEA,wC;AACA,oB;AACA,K;;AAEA,wB;AACA,gC;AACA,oC;AACA,G;;AAEA,qE;AACA,4E;;AAEA,iD;AACA,2C;AACA,yB;AACA,yC;AACA,a;AACA,iC;AACA,a;AACA,iC;AACA,a;AACA,qC;;AAEA,oD;AACA,0E;;AAEA,mB;AACA,kC;AACA,yE;AACA,8C;;AAEA,2B;AACA,6C;AACA,uC;AACA,mD;AACA,+C;AACA,gD;;AAEA,gB;AACA,iD;;AAEA,kD;;AAEA,oB;AACA,kC;AACA,c;AACA,Q;AACA,c;AACA,iB;AACA,6B;AACA,Y;AACA,e;AACA,8B;;AAEA,yC;AACA,wD;AACA,mD;AACA,I;;AAEA,gE;AACA,2C;AACA,E;;AAEA,8C;AACA,uB;AACA,2B;AACA,6C;AACA,gF;AACA,iC;AACA,E","file":"/packages/logging.js","sourcesContent":["Log = function () {\n return Log.info.apply(this, arguments);\n};\n\n/// FOR TESTING\nvar intercept = 0;\nvar interceptedLines = [];\nvar suppress = 0;\n\n// Intercept the next 'count' calls to a Log function. The actual\n// lines printed to the console can be cleared and read by calling\n// Log._intercepted().\nLog._intercept = function (count) {\n intercept += count;\n};\n\n// Suppress the next 'count' calls to a Log function. Use this to stop\n// tests from spamming the console, especially with red errors that\n// might look like a failing test.\nLog._suppress = function (count) {\n suppress += count;\n};\n\n// Returns intercepted lines and resets the intercept counter.\nLog._intercepted = function () {\n var lines = interceptedLines;\n interceptedLines = [];\n intercept = 0;\n return lines;\n};\n\n// Either 'json' or 'colored-text'.\n//\n// When this is set to 'json', print JSON documents that are parsed by another\n// process ('satellite' or 'meteor run'). This other process should call\n// 'Log.format' for nice output.\n//\n// When this is set to 'colored-text', call 'Log.format' before printing.\n// This should be used for logging from within satellite, since there is no\n// other process that will be reading its standard output.\nLog.outputFormat = 'json';\n\nvar LEVEL_COLORS = {\n debug: 'green',\n // leave info as the default color\n warn: 'magenta',\n error: 'red'\n};\n\nvar META_COLOR = 'blue';\n\n// XXX package\nvar RESTRICTED_KEYS = ['time', 'timeInexact', 'level', 'file', 'line',\n 'program', 'originApp', 'satellite', 'stderr'];\n\nvar FORMATTED_KEYS = RESTRICTED_KEYS.concat(['app', 'message']);\n\nvar logInBrowser = function (obj) {\n var str = Log.format(obj);\n\n // XXX Some levels should be probably be sent to the server\n var level = obj.level;\n\n if ((typeof console !== 'undefined') && console[level]) {\n console[level](str);\n } else {\n // XXX Uses of Meteor._debug should probably be replaced by Log.debug or\n // Log.info, and we should have another name for \"do your best to\n // call call console.log\".\n Meteor._debug(str);\n }\n};\n\n// @returns {Object: { line: Number, file: String }}\nLog._getCallerDetails = function () {\n var getStack = function () {\n // We do NOT use Error.prepareStackTrace here (a V8 extension that gets us a\n // pre-parsed stack) since it's impossible to compose it with the use of\n // Error.prepareStackTrace used on the server for source maps.\n var err = new Error;\n var stack = err.stack;\n return stack;\n };\n\n var stack = getStack();\n\n if (!stack) return {};\n\n var lines = stack.split('\\n');\n\n // looking for the first line outside the logging package (or an\n // eval if we find that first)\n var line;\n for (var i = 1; i < lines.length; ++i) {\n line = lines[i];\n if (line.match(/^\\s*at eval \\(eval/)) {\n return {file: \"eval\"};\n }\n\n if (!line.match(/packages\\/(?:local-test:)?logging(?:\\/|\\.js)/))\n break;\n }\n\n var details = {};\n\n // The format for FF is 'functionName@filePath:lineNumber'\n // The format for V8 is 'functionName (packages/logging/logging.js:81)' or\n // 'packages/logging/logging.js:81'\n var match = /(?:[@(]| at )([^(]+?):([0-9:]+)(?:\\)|$)/.exec(line);\n if (!match)\n return details;\n // in case the matched block here is line:column\n details.line = match[2].split(':')[0];\n\n // Possible format: https://foo.bar.com/scripts/file.js?random=foobar\n // XXX: if you can write the following in better way, please do it\n // XXX: what about evals?\n details.file = match[1].split('/').slice(-1)[0].split('?')[0];\n\n return details;\n};\n\n_.each(['debug', 'info', 'warn', 'error'], function (level) {\n // @param arg {String|Object}\n Log[level] = function (arg) {\n if (suppress) {\n suppress--;\n return;\n }\n\n var intercepted = false;\n if (intercept) {\n intercept--;\n intercepted = true;\n }\n\n var obj = (_.isObject(arg) && !_.isRegExp(arg) && !_.isDate(arg) ) ?\n arg : {message: new String(arg).toString() };\n\n _.each(RESTRICTED_KEYS, function (key) {\n if (obj[key])\n throw new Error(\"Can't set '\" + key + \"' in log message\");\n });\n\n if (_.has(obj, 'message') && !_.isString(obj.message))\n throw new Error(\"The 'message' field in log objects must be a string\");\n if (!obj.omitCallerDetails)\n obj = _.extend(Log._getCallerDetails(), obj);\n obj.time = new Date();\n obj.level = level;\n\n // XXX allow you to enable 'debug', probably per-package\n if (level === 'debug')\n return;\n\n if (intercepted) {\n interceptedLines.push(EJSON.stringify(obj));\n } else if (Meteor.isServer) {\n if (Log.outputFormat === 'colored-text') {\n console.log(Log.format(obj, {color: true}));\n } else if (Log.outputFormat === 'json') {\n console.log(EJSON.stringify(obj));\n } else {\n throw new Error(\"Unknown logging output format: \" + Log.outputFormat);\n }\n } else {\n logInBrowser(obj);\n }\n };\n});\n\n// tries to parse line as EJSON. returns object if parse is successful, or null if not\nLog.parse = function (line) {\n var obj = null;\n if (line && line.charAt(0) === '{') { // might be json generated from calling 'Log'\n try { obj = EJSON.parse(line); } catch (e) {}\n }\n\n // XXX should probably check fields other than 'time'\n if (obj && obj.time && (obj.time instanceof Date))\n return obj;\n else\n return null;\n};\n\n// formats a log object into colored human and machine-readable text\nLog.format = function (obj, options) {\n obj = EJSON.clone(obj); // don't mutate the argument\n options = options || {};\n\n var time = obj.time;\n if (!(time instanceof Date))\n throw new Error(\"'time' must be a Date object\");\n var timeInexact = obj.timeInexact;\n\n // store fields that are in FORMATTED_KEYS since we strip them\n var level = obj.level || 'info';\n var file = obj.file;\n var lineNumber = obj.line;\n var appName = obj.app || '';\n var originApp = obj.originApp;\n var message = obj.message || '';\n var program = obj.program || '';\n var satellite = obj.satellite;\n var stderr = obj.stderr || '';\n\n _.each(FORMATTED_KEYS, function(key) {\n delete obj[key];\n });\n\n if (!_.isEmpty(obj)) {\n if (message) message += \" \";\n message += EJSON.stringify(obj);\n }\n\n var pad2 = function(n) { return n < 10 ? '0' + n : n.toString(); };\n var pad3 = function(n) { return n < 100 ? '0' + pad2(n) : n.toString(); };\n\n var dateStamp = time.getFullYear().toString() +\n pad2(time.getMonth() + 1 /*0-based*/) +\n pad2(time.getDate());\n var timeStamp = pad2(time.getHours()) +\n ':' +\n pad2(time.getMinutes()) +\n ':' +\n pad2(time.getSeconds()) +\n '.' +\n pad3(time.getMilliseconds());\n\n // eg in San Francisco in June this will be '(-7)'\n var utcOffsetStr = '(' + (-(new Date().getTimezoneOffset() / 60)) + ')';\n\n var appInfo = '';\n if (appName) appInfo += appName;\n if (originApp && originApp !== appName) appInfo += ' via ' + originApp;\n if (appInfo) appInfo = '[' + appInfo + '] ';\n\n var sourceInfoParts = [];\n if (program) sourceInfoParts.push(program);\n if (file) sourceInfoParts.push(file);\n if (lineNumber) sourceInfoParts.push(lineNumber);\n var sourceInfo = _.isEmpty(sourceInfoParts) ?\n '' : '(' + sourceInfoParts.join(':') + ') ';\n\n if (satellite)\n sourceInfo += ['[', satellite, ']'].join('');\n\n var stderrIndicator = stderr ? '(STDERR) ' : '';\n\n var metaPrefix = [\n level.charAt(0).toUpperCase(),\n dateStamp,\n '-',\n timeStamp,\n utcOffsetStr,\n timeInexact ? '? ' : ' ',\n appInfo,\n sourceInfo,\n stderrIndicator].join('');\n\n var prettify = function (line, color) {\n return (options.color && Meteor.isServer && color) ?\n Npm.require('cli-color')[color](line) : line;\n };\n\n return prettify(metaPrefix, options.metaColor || META_COLOR) +\n prettify(message, LEVEL_COLORS[level]);\n};\n\n// Turn a line of text into a loggable object.\n// @param line {String}\n// @param override {Object}\nLog.objFromText = function (line, override) {\n var obj = {message: line, level: \"info\", time: new Date(), timeInexact: true};\n return _.extend(obj, override);\n};\n"]} |