playwright/src/logger.ts

110 lines
3.5 KiB
TypeScript
Raw Normal View History

/**
* Copyright Microsoft Corporation. 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.
*/
import * as util from 'util';
export type LoggerSeverity = 'verbose' | 'info' | 'warning' | 'error';
export type Log = {
name: string;
severity?: LoggerSeverity;
color?: string | undefined;
};
export interface Logger {
_isLogEnabled(log: Log): boolean;
_log(log: Log, message: string | Error, ...args: any[]): void;
}
export interface LoggerSink {
isEnabled(name: string, severity: LoggerSeverity): boolean;
log(name: string, severity: LoggerSeverity, message: string | Error, args: any[], hints: { color?: string }): void;
}
export const errorLog: Log = { name: 'generic', severity: 'error' };
export function logError(logger: Logger): (error: Error) => void {
return error => logger._log(errorLog, error, []);
}
const colorMap = new Map<string, number>([
['black', 30],
['red', 31],
['green', 32],
['yellow', 33],
['blue', 34],
['magenta', 35],
['cyan', 36],
['white', 37],
['reset', 0],
]);
export class RootLogger implements Logger {
private _userSink: LoggerSink | undefined;
private _consoleSink: ConsoleLoggerSink;
constructor(userSink: LoggerSink | undefined) {
this._userSink = userSink;
this._consoleSink = new ConsoleLoggerSink();
}
_isLogEnabled(log: Log): boolean {
return (this._userSink && this._userSink.isEnabled(log.name, log.severity || 'info')) ||
this._consoleSink.isEnabled(log.name, log.severity || 'info');
}
_log(log: Log, message: string | Error, ...args: any[]) {
if (this._userSink && this._userSink.isEnabled(log.name, log.severity || 'info'))
this._userSink.log(log.name, log.severity || 'info', message, args, log.color ? { color: log.color } : {});
if (this._consoleSink.isEnabled(log.name, log.severity || 'info'))
this._consoleSink.log(log.name, log.severity || 'info', message, args, log.color ? { color: log.color } : {});
}
}
class ConsoleLoggerSink implements LoggerSink {
private _enabled: string[];
private _enabledCache = new Map<string, boolean>();
constructor() {
this._enabled = process.env.PWDEBUG ? process.env.PWDEBUG.split(',') : [];
}
isEnabled(name: string, severity: LoggerSeverity): boolean {
const result = this._enabledCache.get(name);
if (typeof result === 'boolean')
return result;
for (const logger of this._enabled) {
if (name.includes(logger)) {
this._enabledCache.set(name, true);
return true;
}
}
this._enabledCache.set(name, false);
return false;
}
log(name: string, severity: LoggerSeverity, message: string | Error, args: any[], hints: { color?: string }) {
let color = hints.color || 'reset';
switch (severity) {
case 'error': color = 'red'; break;
case 'warning': color = 'yellow'; break;
}
const escape = colorMap.get(color) || 0;
console.log(`[${new Date().toISOString()}:\u001b[${escape}m${name}\u001b[0m] ${util.format(message, ...args)}`); // eslint-disable-line no-console
}
}