123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 |
- // Copyright 2006 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS-IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- /**
- * @fileoverview Definition of various formatters for logging. Please minimize
- * dependencies this file has on other closure classes as any dependency it
- * takes won't be able to use the logging infrastructure.
- *
- */
- goog.provide('goog.debug.Formatter');
- goog.provide('goog.debug.HtmlFormatter');
- goog.provide('goog.debug.TextFormatter');
- goog.require('goog.debug');
- goog.require('goog.debug.Logger');
- goog.require('goog.debug.RelativeTimeProvider');
- goog.require('goog.html.SafeHtml');
- goog.require('goog.html.SafeUrl');
- goog.require('goog.html.uncheckedconversions');
- goog.require('goog.string.Const');
- /**
- * Base class for Formatters. A Formatter is used to format a LogRecord into
- * something that can be displayed to the user.
- *
- * @param {string=} opt_prefix The prefix to place before text records.
- * @constructor
- */
- goog.debug.Formatter = function(opt_prefix) {
- this.prefix_ = opt_prefix || '';
- /**
- * A provider that returns the relative start time.
- * @type {goog.debug.RelativeTimeProvider}
- * @private
- */
- this.startTimeProvider_ =
- goog.debug.RelativeTimeProvider.getDefaultInstance();
- };
- /**
- * Whether to append newlines to the end of formatted log records.
- * @type {boolean}
- */
- goog.debug.Formatter.prototype.appendNewline = true;
- /**
- * Whether to show absolute time in the DebugWindow.
- * @type {boolean}
- */
- goog.debug.Formatter.prototype.showAbsoluteTime = true;
- /**
- * Whether to show relative time in the DebugWindow.
- * @type {boolean}
- */
- goog.debug.Formatter.prototype.showRelativeTime = true;
- /**
- * Whether to show the logger name in the DebugWindow.
- * @type {boolean}
- */
- goog.debug.Formatter.prototype.showLoggerName = true;
- /**
- * Whether to show the logger exception text.
- * @type {boolean}
- */
- goog.debug.Formatter.prototype.showExceptionText = false;
- /**
- * Whether to show the severity level.
- * @type {boolean}
- */
- goog.debug.Formatter.prototype.showSeverityLevel = false;
- /**
- * Formats a record.
- * @param {goog.debug.LogRecord} logRecord the logRecord to format.
- * @return {string} The formatted string.
- */
- goog.debug.Formatter.prototype.formatRecord = goog.abstractMethod;
- /**
- * Formats a record as SafeHtml.
- * @param {goog.debug.LogRecord} logRecord the logRecord to format.
- * @return {!goog.html.SafeHtml} The formatted string as SafeHtml.
- */
- goog.debug.Formatter.prototype.formatRecordAsHtml = goog.abstractMethod;
- /**
- * Sets the start time provider. By default, this is the default instance
- * but can be changed.
- * @param {goog.debug.RelativeTimeProvider} provider The provider to use.
- */
- goog.debug.Formatter.prototype.setStartTimeProvider = function(provider) {
- this.startTimeProvider_ = provider;
- };
- /**
- * Returns the start time provider. By default, this is the default instance
- * but can be changed.
- * @return {goog.debug.RelativeTimeProvider} The start time provider.
- */
- goog.debug.Formatter.prototype.getStartTimeProvider = function() {
- return this.startTimeProvider_;
- };
- /**
- * Resets the start relative time.
- */
- goog.debug.Formatter.prototype.resetRelativeTimeStart = function() {
- this.startTimeProvider_.reset();
- };
- /**
- * Returns a string for the time/date of the LogRecord.
- * @param {goog.debug.LogRecord} logRecord The record to get a time stamp for.
- * @return {string} A string representation of the time/date of the LogRecord.
- * @private
- */
- goog.debug.Formatter.getDateTimeStamp_ = function(logRecord) {
- var time = new Date(logRecord.getMillis());
- return goog.debug.Formatter.getTwoDigitString_((time.getFullYear() - 2000)) +
- goog.debug.Formatter.getTwoDigitString_((time.getMonth() + 1)) +
- goog.debug.Formatter.getTwoDigitString_(time.getDate()) + ' ' +
- goog.debug.Formatter.getTwoDigitString_(time.getHours()) + ':' +
- goog.debug.Formatter.getTwoDigitString_(time.getMinutes()) + ':' +
- goog.debug.Formatter.getTwoDigitString_(time.getSeconds()) + '.' +
- goog.debug.Formatter.getTwoDigitString_(
- Math.floor(time.getMilliseconds() / 10));
- };
- /**
- * Returns the number as a two-digit string, meaning it prepends a 0 if the
- * number if less than 10.
- * @param {number} n The number to format.
- * @return {string} A two-digit string representation of {@code n}.
- * @private
- */
- goog.debug.Formatter.getTwoDigitString_ = function(n) {
- if (n < 10) {
- return '0' + n;
- }
- return String(n);
- };
- /**
- * Returns a string for the number of seconds relative to the start time.
- * Prepads with spaces so that anything less than 1000 seconds takes up the
- * same number of characters for better formatting.
- * @param {goog.debug.LogRecord} logRecord The log to compare time to.
- * @param {number} relativeTimeStart The start time to compare to.
- * @return {string} The number of seconds of the LogRecord relative to the
- * start time.
- * @private
- */
- goog.debug.Formatter.getRelativeTime_ = function(logRecord, relativeTimeStart) {
- var ms = logRecord.getMillis() - relativeTimeStart;
- var sec = ms / 1000;
- var str = sec.toFixed(3);
- var spacesToPrepend = 0;
- if (sec < 1) {
- spacesToPrepend = 2;
- } else {
- while (sec < 100) {
- spacesToPrepend++;
- sec *= 10;
- }
- }
- while (spacesToPrepend-- > 0) {
- str = ' ' + str;
- }
- return str;
- };
- /**
- * Formatter that returns formatted html. See formatRecord for the classes
- * it uses for various types of formatted output.
- *
- * @param {string=} opt_prefix The prefix to place before text records.
- * @constructor
- * @extends {goog.debug.Formatter}
- */
- goog.debug.HtmlFormatter = function(opt_prefix) {
- goog.debug.Formatter.call(this, opt_prefix);
- };
- goog.inherits(goog.debug.HtmlFormatter, goog.debug.Formatter);
- /**
- * Exposes an exception that has been caught by a try...catch and outputs the
- * error as HTML with a stack trace.
- *
- * @param {*} err Error object or string.
- * @param {?Function=} fn If provided, when collecting the stack trace all
- * frames above the topmost call to this function, including that call,
- * will be left out of the stack trace.
- * @return {string} Details of exception, as HTML.
- */
- goog.debug.HtmlFormatter.exposeException = function(err, fn) {
- var html = goog.debug.HtmlFormatter.exposeExceptionAsHtml(err, fn);
- return goog.html.SafeHtml.unwrap(html);
- };
- /**
- * Exposes an exception that has been caught by a try...catch and outputs the
- * error with a stack trace.
- *
- * @param {*} err Error object or string.
- * @param {?Function=} fn If provided, when collecting the stack trace all
- * frames above the topmost call to this function, including that call,
- * will be left out of the stack trace.
- * @return {!goog.html.SafeHtml} Details of exception.
- */
- goog.debug.HtmlFormatter.exposeExceptionAsHtml = function(err, fn) {
- try {
- var e = goog.debug.normalizeErrorObject(err);
- // Create the error message
- var viewSourceUrl =
- goog.debug.HtmlFormatter.createViewSourceUrl_(e.fileName);
- var error = goog.html.SafeHtml.concat(
- goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
- 'Message: ' + e.message + '\nUrl: '),
- goog.html.SafeHtml.create(
- 'a', {href: viewSourceUrl, target: '_new'}, e.fileName),
- goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
- '\nLine: ' + e.lineNumber + '\n\nBrowser stack:\n' + e.stack +
- '-> ' +
- '[end]\n\nJS stack traversal:\n' + goog.debug.getStacktrace(fn) +
- '-> '));
- return error;
- } catch (e2) {
- return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
- 'Exception trying to expose exception! You win, we lose. ' + e2);
- }
- };
- /**
- * @param {?string=} fileName
- * @return {!goog.html.SafeUrl} SafeUrl with view-source scheme, pointing at
- * fileName.
- * @private
- */
- goog.debug.HtmlFormatter.createViewSourceUrl_ = function(fileName) {
- if (!goog.isDefAndNotNull(fileName)) {
- fileName = '';
- }
- if (!/^https?:\/\//i.test(fileName)) {
- return goog.html.SafeUrl.fromConstant(
- goog.string.Const.from('sanitizedviewsrc'));
- }
- var sanitizedFileName = goog.html.SafeUrl.sanitize(fileName);
- return goog.html.uncheckedconversions
- .safeUrlFromStringKnownToSatisfyTypeContract(
- goog.string.Const.from('view-source scheme plus HTTP/HTTPS URL'),
- 'view-source:' + goog.html.SafeUrl.unwrap(sanitizedFileName));
- };
- /**
- * Whether to show the logger exception text
- * @type {boolean}
- * @override
- */
- goog.debug.HtmlFormatter.prototype.showExceptionText = true;
- /**
- * Formats a record
- * @param {goog.debug.LogRecord} logRecord the logRecord to format.
- * @return {string} The formatted string as html.
- * @override
- */
- goog.debug.HtmlFormatter.prototype.formatRecord = function(logRecord) {
- if (!logRecord) {
- return '';
- }
- // OK not to use goog.html.SafeHtml.unwrap() here.
- return this.formatRecordAsHtml(logRecord).getTypedStringValue();
- };
- /**
- * Formats a record.
- * @param {goog.debug.LogRecord} logRecord the logRecord to format.
- * @return {!goog.html.SafeHtml} The formatted string as SafeHtml.
- * @override
- */
- goog.debug.HtmlFormatter.prototype.formatRecordAsHtml = function(logRecord) {
- if (!logRecord) {
- return goog.html.SafeHtml.EMPTY;
- }
- var className;
- switch (logRecord.getLevel().value) {
- case goog.debug.Logger.Level.SHOUT.value:
- className = 'dbg-sh';
- break;
- case goog.debug.Logger.Level.SEVERE.value:
- className = 'dbg-sev';
- break;
- case goog.debug.Logger.Level.WARNING.value:
- className = 'dbg-w';
- break;
- case goog.debug.Logger.Level.INFO.value:
- className = 'dbg-i';
- break;
- case goog.debug.Logger.Level.FINE.value:
- default:
- className = 'dbg-f';
- break;
- }
- // HTML for user defined prefix, time, logger name, and severity.
- var sb = [];
- sb.push(this.prefix_, ' ');
- if (this.showAbsoluteTime) {
- sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
- }
- if (this.showRelativeTime) {
- sb.push(
- '[', goog.debug.Formatter.getRelativeTime_(
- logRecord, this.startTimeProvider_.get()),
- 's] ');
- }
- if (this.showLoggerName) {
- sb.push('[', logRecord.getLoggerName(), '] ');
- }
- if (this.showSeverityLevel) {
- sb.push('[', logRecord.getLevel().name, '] ');
- }
- var fullPrefixHtml =
- goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(sb.join(''));
- // HTML for exception text and log record.
- var exceptionHtml = goog.html.SafeHtml.EMPTY;
- if (this.showExceptionText && logRecord.getException()) {
- exceptionHtml = goog.html.SafeHtml.concat(
- goog.html.SafeHtml.BR,
- goog.debug.HtmlFormatter.exposeExceptionAsHtml(
- logRecord.getException()));
- }
- var logRecordHtml = goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
- logRecord.getMessage());
- var recordAndExceptionHtml = goog.html.SafeHtml.create(
- 'span', {'class': className},
- goog.html.SafeHtml.concat(logRecordHtml, exceptionHtml));
- // Combine both pieces of HTML and, if needed, append a final newline.
- var html;
- if (this.appendNewline) {
- html = goog.html.SafeHtml.concat(
- fullPrefixHtml, recordAndExceptionHtml, goog.html.SafeHtml.BR);
- } else {
- html = goog.html.SafeHtml.concat(fullPrefixHtml, recordAndExceptionHtml);
- }
- return html;
- };
- /**
- * Formatter that returns formatted plain text
- *
- * @param {string=} opt_prefix The prefix to place before text records.
- * @constructor
- * @extends {goog.debug.Formatter}
- * @final
- */
- goog.debug.TextFormatter = function(opt_prefix) {
- goog.debug.Formatter.call(this, opt_prefix);
- };
- goog.inherits(goog.debug.TextFormatter, goog.debug.Formatter);
- /**
- * Formats a record as text
- * @param {goog.debug.LogRecord} logRecord the logRecord to format.
- * @return {string} The formatted string.
- * @override
- */
- goog.debug.TextFormatter.prototype.formatRecord = function(logRecord) {
- var sb = [];
- sb.push(this.prefix_, ' ');
- if (this.showAbsoluteTime) {
- sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
- }
- if (this.showRelativeTime) {
- sb.push(
- '[', goog.debug.Formatter.getRelativeTime_(
- logRecord, this.startTimeProvider_.get()),
- 's] ');
- }
- if (this.showLoggerName) {
- sb.push('[', logRecord.getLoggerName(), '] ');
- }
- if (this.showSeverityLevel) {
- sb.push('[', logRecord.getLevel().name, '] ');
- }
- sb.push(logRecord.getMessage());
- if (this.showExceptionText) {
- var exception = logRecord.getException();
- if (exception) {
- var exceptionText =
- exception instanceof Error ? exception.message : exception.toString();
- sb.push('\n', exceptionText);
- }
- }
- if (this.appendNewline) {
- sb.push('\n');
- }
- return sb.join('');
- };
- /**
- * Formats a record as text
- * @param {goog.debug.LogRecord} logRecord the logRecord to format.
- * @return {!goog.html.SafeHtml} The formatted string as SafeHtml. This is
- * just an HTML-escaped version of the text obtained from formatRecord().
- * @override
- */
- goog.debug.TextFormatter.prototype.formatRecordAsHtml = function(logRecord) {
- return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
- goog.debug.TextFormatter.prototype.formatRecord(logRecord));
- };
|