Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/debug/formatter.js
2868 views
1
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Definition of various formatters for logging. Please minimize
17
* dependencies this file has on other closure classes as any dependency it
18
* takes won't be able to use the logging infrastructure.
19
*
20
*/
21
22
goog.provide('goog.debug.Formatter');
23
goog.provide('goog.debug.HtmlFormatter');
24
goog.provide('goog.debug.TextFormatter');
25
26
goog.require('goog.debug');
27
goog.require('goog.debug.Logger');
28
goog.require('goog.debug.RelativeTimeProvider');
29
goog.require('goog.html.SafeHtml');
30
goog.require('goog.html.SafeUrl');
31
goog.require('goog.html.uncheckedconversions');
32
goog.require('goog.string.Const');
33
34
35
36
/**
37
* Base class for Formatters. A Formatter is used to format a LogRecord into
38
* something that can be displayed to the user.
39
*
40
* @param {string=} opt_prefix The prefix to place before text records.
41
* @constructor
42
*/
43
goog.debug.Formatter = function(opt_prefix) {
44
this.prefix_ = opt_prefix || '';
45
46
/**
47
* A provider that returns the relative start time.
48
* @type {goog.debug.RelativeTimeProvider}
49
* @private
50
*/
51
this.startTimeProvider_ =
52
goog.debug.RelativeTimeProvider.getDefaultInstance();
53
};
54
55
56
/**
57
* Whether to append newlines to the end of formatted log records.
58
* @type {boolean}
59
*/
60
goog.debug.Formatter.prototype.appendNewline = true;
61
62
63
/**
64
* Whether to show absolute time in the DebugWindow.
65
* @type {boolean}
66
*/
67
goog.debug.Formatter.prototype.showAbsoluteTime = true;
68
69
70
/**
71
* Whether to show relative time in the DebugWindow.
72
* @type {boolean}
73
*/
74
goog.debug.Formatter.prototype.showRelativeTime = true;
75
76
77
/**
78
* Whether to show the logger name in the DebugWindow.
79
* @type {boolean}
80
*/
81
goog.debug.Formatter.prototype.showLoggerName = true;
82
83
84
/**
85
* Whether to show the logger exception text.
86
* @type {boolean}
87
*/
88
goog.debug.Formatter.prototype.showExceptionText = false;
89
90
91
/**
92
* Whether to show the severity level.
93
* @type {boolean}
94
*/
95
goog.debug.Formatter.prototype.showSeverityLevel = false;
96
97
98
/**
99
* Formats a record.
100
* @param {goog.debug.LogRecord} logRecord the logRecord to format.
101
* @return {string} The formatted string.
102
*/
103
goog.debug.Formatter.prototype.formatRecord = goog.abstractMethod;
104
105
106
/**
107
* Formats a record as SafeHtml.
108
* @param {goog.debug.LogRecord} logRecord the logRecord to format.
109
* @return {!goog.html.SafeHtml} The formatted string as SafeHtml.
110
*/
111
goog.debug.Formatter.prototype.formatRecordAsHtml = goog.abstractMethod;
112
113
114
/**
115
* Sets the start time provider. By default, this is the default instance
116
* but can be changed.
117
* @param {goog.debug.RelativeTimeProvider} provider The provider to use.
118
*/
119
goog.debug.Formatter.prototype.setStartTimeProvider = function(provider) {
120
this.startTimeProvider_ = provider;
121
};
122
123
124
/**
125
* Returns the start time provider. By default, this is the default instance
126
* but can be changed.
127
* @return {goog.debug.RelativeTimeProvider} The start time provider.
128
*/
129
goog.debug.Formatter.prototype.getStartTimeProvider = function() {
130
return this.startTimeProvider_;
131
};
132
133
134
/**
135
* Resets the start relative time.
136
*/
137
goog.debug.Formatter.prototype.resetRelativeTimeStart = function() {
138
this.startTimeProvider_.reset();
139
};
140
141
142
/**
143
* Returns a string for the time/date of the LogRecord.
144
* @param {goog.debug.LogRecord} logRecord The record to get a time stamp for.
145
* @return {string} A string representation of the time/date of the LogRecord.
146
* @private
147
*/
148
goog.debug.Formatter.getDateTimeStamp_ = function(logRecord) {
149
var time = new Date(logRecord.getMillis());
150
return goog.debug.Formatter.getTwoDigitString_((time.getFullYear() - 2000)) +
151
goog.debug.Formatter.getTwoDigitString_((time.getMonth() + 1)) +
152
goog.debug.Formatter.getTwoDigitString_(time.getDate()) + ' ' +
153
goog.debug.Formatter.getTwoDigitString_(time.getHours()) + ':' +
154
goog.debug.Formatter.getTwoDigitString_(time.getMinutes()) + ':' +
155
goog.debug.Formatter.getTwoDigitString_(time.getSeconds()) + '.' +
156
goog.debug.Formatter.getTwoDigitString_(
157
Math.floor(time.getMilliseconds() / 10));
158
};
159
160
161
/**
162
* Returns the number as a two-digit string, meaning it prepends a 0 if the
163
* number if less than 10.
164
* @param {number} n The number to format.
165
* @return {string} A two-digit string representation of {@code n}.
166
* @private
167
*/
168
goog.debug.Formatter.getTwoDigitString_ = function(n) {
169
if (n < 10) {
170
return '0' + n;
171
}
172
return String(n);
173
};
174
175
176
/**
177
* Returns a string for the number of seconds relative to the start time.
178
* Prepads with spaces so that anything less than 1000 seconds takes up the
179
* same number of characters for better formatting.
180
* @param {goog.debug.LogRecord} logRecord The log to compare time to.
181
* @param {number} relativeTimeStart The start time to compare to.
182
* @return {string} The number of seconds of the LogRecord relative to the
183
* start time.
184
* @private
185
*/
186
goog.debug.Formatter.getRelativeTime_ = function(logRecord, relativeTimeStart) {
187
var ms = logRecord.getMillis() - relativeTimeStart;
188
var sec = ms / 1000;
189
var str = sec.toFixed(3);
190
191
var spacesToPrepend = 0;
192
if (sec < 1) {
193
spacesToPrepend = 2;
194
} else {
195
while (sec < 100) {
196
spacesToPrepend++;
197
sec *= 10;
198
}
199
}
200
while (spacesToPrepend-- > 0) {
201
str = ' ' + str;
202
}
203
return str;
204
};
205
206
207
208
/**
209
* Formatter that returns formatted html. See formatRecord for the classes
210
* it uses for various types of formatted output.
211
*
212
* @param {string=} opt_prefix The prefix to place before text records.
213
* @constructor
214
* @extends {goog.debug.Formatter}
215
*/
216
goog.debug.HtmlFormatter = function(opt_prefix) {
217
goog.debug.Formatter.call(this, opt_prefix);
218
};
219
goog.inherits(goog.debug.HtmlFormatter, goog.debug.Formatter);
220
221
222
/**
223
* Exposes an exception that has been caught by a try...catch and outputs the
224
* error as HTML with a stack trace.
225
*
226
* @param {*} err Error object or string.
227
* @param {?Function=} fn If provided, when collecting the stack trace all
228
* frames above the topmost call to this function, including that call,
229
* will be left out of the stack trace.
230
* @return {string} Details of exception, as HTML.
231
*/
232
goog.debug.HtmlFormatter.exposeException = function(err, fn) {
233
var html = goog.debug.HtmlFormatter.exposeExceptionAsHtml(err, fn);
234
return goog.html.SafeHtml.unwrap(html);
235
};
236
237
238
/**
239
* Exposes an exception that has been caught by a try...catch and outputs the
240
* error with a stack trace.
241
*
242
* @param {*} err Error object or string.
243
* @param {?Function=} fn If provided, when collecting the stack trace all
244
* frames above the topmost call to this function, including that call,
245
* will be left out of the stack trace.
246
* @return {!goog.html.SafeHtml} Details of exception.
247
*/
248
goog.debug.HtmlFormatter.exposeExceptionAsHtml = function(err, fn) {
249
try {
250
var e = goog.debug.normalizeErrorObject(err);
251
// Create the error message
252
var viewSourceUrl =
253
goog.debug.HtmlFormatter.createViewSourceUrl_(e.fileName);
254
var error = goog.html.SafeHtml.concat(
255
goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
256
'Message: ' + e.message + '\nUrl: '),
257
goog.html.SafeHtml.create(
258
'a', {href: viewSourceUrl, target: '_new'}, e.fileName),
259
goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
260
'\nLine: ' + e.lineNumber + '\n\nBrowser stack:\n' + e.stack +
261
'-> ' +
262
'[end]\n\nJS stack traversal:\n' + goog.debug.getStacktrace(fn) +
263
'-> '));
264
return error;
265
} catch (e2) {
266
return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
267
'Exception trying to expose exception! You win, we lose. ' + e2);
268
}
269
};
270
271
272
/**
273
* @param {?string=} fileName
274
* @return {!goog.html.SafeUrl} SafeUrl with view-source scheme, pointing at
275
* fileName.
276
* @private
277
*/
278
goog.debug.HtmlFormatter.createViewSourceUrl_ = function(fileName) {
279
if (!goog.isDefAndNotNull(fileName)) {
280
fileName = '';
281
}
282
if (!/^https?:\/\//i.test(fileName)) {
283
return goog.html.SafeUrl.fromConstant(
284
goog.string.Const.from('sanitizedviewsrc'));
285
}
286
var sanitizedFileName = goog.html.SafeUrl.sanitize(fileName);
287
return goog.html.uncheckedconversions
288
.safeUrlFromStringKnownToSatisfyTypeContract(
289
goog.string.Const.from('view-source scheme plus HTTP/HTTPS URL'),
290
'view-source:' + goog.html.SafeUrl.unwrap(sanitizedFileName));
291
};
292
293
294
295
/**
296
* Whether to show the logger exception text
297
* @type {boolean}
298
* @override
299
*/
300
goog.debug.HtmlFormatter.prototype.showExceptionText = true;
301
302
303
/**
304
* Formats a record
305
* @param {goog.debug.LogRecord} logRecord the logRecord to format.
306
* @return {string} The formatted string as html.
307
* @override
308
*/
309
goog.debug.HtmlFormatter.prototype.formatRecord = function(logRecord) {
310
if (!logRecord) {
311
return '';
312
}
313
// OK not to use goog.html.SafeHtml.unwrap() here.
314
return this.formatRecordAsHtml(logRecord).getTypedStringValue();
315
};
316
317
318
/**
319
* Formats a record.
320
* @param {goog.debug.LogRecord} logRecord the logRecord to format.
321
* @return {!goog.html.SafeHtml} The formatted string as SafeHtml.
322
* @override
323
*/
324
goog.debug.HtmlFormatter.prototype.formatRecordAsHtml = function(logRecord) {
325
if (!logRecord) {
326
return goog.html.SafeHtml.EMPTY;
327
}
328
329
var className;
330
switch (logRecord.getLevel().value) {
331
case goog.debug.Logger.Level.SHOUT.value:
332
className = 'dbg-sh';
333
break;
334
case goog.debug.Logger.Level.SEVERE.value:
335
className = 'dbg-sev';
336
break;
337
case goog.debug.Logger.Level.WARNING.value:
338
className = 'dbg-w';
339
break;
340
case goog.debug.Logger.Level.INFO.value:
341
className = 'dbg-i';
342
break;
343
case goog.debug.Logger.Level.FINE.value:
344
default:
345
className = 'dbg-f';
346
break;
347
}
348
349
// HTML for user defined prefix, time, logger name, and severity.
350
var sb = [];
351
sb.push(this.prefix_, ' ');
352
if (this.showAbsoluteTime) {
353
sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
354
}
355
if (this.showRelativeTime) {
356
sb.push(
357
'[', goog.debug.Formatter.getRelativeTime_(
358
logRecord, this.startTimeProvider_.get()),
359
's] ');
360
}
361
if (this.showLoggerName) {
362
sb.push('[', logRecord.getLoggerName(), '] ');
363
}
364
if (this.showSeverityLevel) {
365
sb.push('[', logRecord.getLevel().name, '] ');
366
}
367
var fullPrefixHtml =
368
goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(sb.join(''));
369
370
// HTML for exception text and log record.
371
var exceptionHtml = goog.html.SafeHtml.EMPTY;
372
if (this.showExceptionText && logRecord.getException()) {
373
exceptionHtml = goog.html.SafeHtml.concat(
374
goog.html.SafeHtml.BR,
375
goog.debug.HtmlFormatter.exposeExceptionAsHtml(
376
logRecord.getException()));
377
}
378
var logRecordHtml = goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
379
logRecord.getMessage());
380
var recordAndExceptionHtml = goog.html.SafeHtml.create(
381
'span', {'class': className},
382
goog.html.SafeHtml.concat(logRecordHtml, exceptionHtml));
383
384
385
// Combine both pieces of HTML and, if needed, append a final newline.
386
var html;
387
if (this.appendNewline) {
388
html = goog.html.SafeHtml.concat(
389
fullPrefixHtml, recordAndExceptionHtml, goog.html.SafeHtml.BR);
390
} else {
391
html = goog.html.SafeHtml.concat(fullPrefixHtml, recordAndExceptionHtml);
392
}
393
return html;
394
};
395
396
397
398
/**
399
* Formatter that returns formatted plain text
400
*
401
* @param {string=} opt_prefix The prefix to place before text records.
402
* @constructor
403
* @extends {goog.debug.Formatter}
404
* @final
405
*/
406
goog.debug.TextFormatter = function(opt_prefix) {
407
goog.debug.Formatter.call(this, opt_prefix);
408
};
409
goog.inherits(goog.debug.TextFormatter, goog.debug.Formatter);
410
411
412
/**
413
* Formats a record as text
414
* @param {goog.debug.LogRecord} logRecord the logRecord to format.
415
* @return {string} The formatted string.
416
* @override
417
*/
418
goog.debug.TextFormatter.prototype.formatRecord = function(logRecord) {
419
var sb = [];
420
sb.push(this.prefix_, ' ');
421
if (this.showAbsoluteTime) {
422
sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
423
}
424
if (this.showRelativeTime) {
425
sb.push(
426
'[', goog.debug.Formatter.getRelativeTime_(
427
logRecord, this.startTimeProvider_.get()),
428
's] ');
429
}
430
431
if (this.showLoggerName) {
432
sb.push('[', logRecord.getLoggerName(), '] ');
433
}
434
if (this.showSeverityLevel) {
435
sb.push('[', logRecord.getLevel().name, '] ');
436
}
437
sb.push(logRecord.getMessage());
438
if (this.showExceptionText) {
439
var exception = logRecord.getException();
440
if (exception) {
441
var exceptionText =
442
exception instanceof Error ? exception.message : exception.toString();
443
sb.push('\n', exceptionText);
444
}
445
}
446
if (this.appendNewline) {
447
sb.push('\n');
448
}
449
return sb.join('');
450
};
451
452
453
/**
454
* Formats a record as text
455
* @param {goog.debug.LogRecord} logRecord the logRecord to format.
456
* @return {!goog.html.SafeHtml} The formatted string as SafeHtml. This is
457
* just an HTML-escaped version of the text obtained from formatRecord().
458
* @override
459
*/
460
goog.debug.TextFormatter.prototype.formatRecordAsHtml = function(logRecord) {
461
return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
462
goog.debug.TextFormatter.prototype.formatRecord(logRecord));
463
};
464
465