From 90449bc745546f0f25bc93ee4b06d21b7c0210e8 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 18 Feb 2024 08:01:22 -0500 Subject: Log update (#701) * Don't export Logger * Rename logger.js to log.js * Move helper function * Update extension name configuration * Simplify docs * Move issue URL to a field * Simplify context * Remove optional params that are never used * Configure backend * Update eslint * Simplify * Rename function * Simplify _api reference * Simplify docs * Remove unused log levels (except 'log') * Add log function * Rename for more clear intent * Use log.log --- ext/js/core/log-utilities.js | 28 ++++++++ ext/js/core/log.js | 149 ++++++++++++++++++++++++++++++++++++++++ ext/js/core/logger.js | 158 ------------------------------------------- 3 files changed, 177 insertions(+), 158 deletions(-) create mode 100644 ext/js/core/log-utilities.js create mode 100644 ext/js/core/log.js delete mode 100644 ext/js/core/logger.js (limited to 'ext/js/core') diff --git a/ext/js/core/log-utilities.js b/ext/js/core/log-utilities.js new file mode 100644 index 00000000..b7e0c914 --- /dev/null +++ b/ext/js/core/log-utilities.js @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @param {import('log').LogLevel} errorLevel + * @returns {number} + */ +export function logErrorLevelToNumber(errorLevel) { + switch (errorLevel) { + case 'warn': return 1; + case 'error': return 2; + default: return 0; + } +} diff --git a/ext/js/core/log.js b/ext/js/core/log.js new file mode 100644 index 00000000..8401cc2b --- /dev/null +++ b/ext/js/core/log.js @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2023-2024 Yomitan Authors + * Copyright (C) 2019-2022 Yomichan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import {EventDispatcher} from './event-dispatcher.js'; +import {ExtensionError} from './extension-error.js'; + +/** + * This class handles logging of messages to the console and triggering an event for log calls. + * @augments EventDispatcher + */ +class Logger extends EventDispatcher { + constructor() { + super(); + /** @type {string} */ + this._extensionName = 'Extension'; + /** @type {?string} */ + this._issueUrl = 'https://github.com/themoeway/yomitan/issues'; + } + + /** + * @param {string} extensionName + */ + configure(extensionName) { + this._extensionName = extensionName; + } + + /** + * @param {unknown} message + * @param {...unknown} optionalParams + */ + log(message, ...optionalParams) { + /* eslint-disable no-console */ + console.log(message, ...optionalParams); + /* eslint-enable no-console */ + } + + /** + * Logs a warning. + * @param {unknown} error The error to log. This is typically an `Error` or `Error`-like object. + */ + warn(error) { + this.logGenericError(error, 'warn'); + } + + /** + * Logs an error. + * @param {unknown} error The error to log. This is typically an `Error` or `Error`-like object. + */ + error(error) { + this.logGenericError(error, 'error'); + } + + /** + * Logs a generic error. + * @param {unknown} error The error to log. This is typically an `Error` or `Error`-like object. + * @param {import('log').LogLevel} level + * @param {import('log').LogContext} [context] + */ + logGenericError(error, level, context) { + if (typeof context === 'undefined') { + context = {url: location.href}; + } + + let errorString; + try { + if (typeof error === 'string') { + errorString = error; + } else { + errorString = ( + typeof error === 'object' && error !== null ? + // eslint-disable-next-line @typescript-eslint/no-base-to-string + error.toString() : + `${error}` + ); + if (/^\[object \w+\]$/.test(errorString)) { + errorString = JSON.stringify(error); + } + } + } catch (e) { + errorString = `${error}`; + } + + let errorStack; + try { + errorStack = ( + error instanceof Error ? + (typeof error.stack === 'string' ? error.stack.trimEnd() : '') : + '' + ); + } catch (e) { + errorStack = ''; + } + + let errorData; + try { + if (error instanceof ExtensionError) { + errorData = error.data; + } + } catch (e) { + // NOP + } + + if (errorStack.startsWith(errorString)) { + errorString = errorStack; + } else if (errorStack.length > 0) { + errorString += `\n${errorStack}`; + } + + let message = `${this._extensionName} has encountered a problem.`; + message += `\nOriginating URL: ${context.url}\n`; + message += errorString; + if (typeof errorData !== 'undefined') { + message += `\nData: ${JSON.stringify(errorData, null, 4)}`; + } + if (this._issueUrl !== null) { + message += `\n\nIssues can be reported at ${this._issueUrl}`; + } + + /* eslint-disable no-console */ + switch (level) { + case 'log': console.log(message); break; + case 'warn': console.warn(message); break; + case 'error': console.error(message); break; + } + /* eslint-enable no-console */ + + this.trigger('logGenericError', {error, level, context}); + } +} + +/** + * This object is the default logger used by the runtime. + */ +export const log = new Logger(); diff --git a/ext/js/core/logger.js b/ext/js/core/logger.js deleted file mode 100644 index 6cf1cc1f..00000000 --- a/ext/js/core/logger.js +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2023-2024 Yomitan Authors - * Copyright (C) 2019-2022 Yomichan Authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import {EventDispatcher} from './event-dispatcher.js'; -import {ExtensionError} from './extension-error.js'; - -/** - * This class handles logging of messages to the console and triggering - * an event for log calls. - * @augments EventDispatcher - */ -export class Logger extends EventDispatcher { - /** - * Creates a new instance. - */ - constructor() { - super(); - /** @type {string} */ - this._extensionName = 'Yomitan'; - try { - const {name, version} = chrome.runtime.getManifest(); - this._extensionName = `${name} ${version}`; - } catch (e) { - // NOP - } - } - - /** - * Logs a generic error. This will trigger the 'log' event with the same arguments as the function invocation. - * @param {unknown} error The error to log. This is typically an `Error` or `Error`-like object. - * @param {import('log').LogLevel} level The level to log at. Values include `'info'`, `'debug'`, `'warn'`, and `'error'`. - * Other values will be logged at a non-error level. - * @param {?import('log').LogContext} [context] An optional context object for the error which should typically include a `url` field. - */ - log(error, level, context = null) { - if (typeof context !== 'object' || context === null) { - context = {url: location.href}; - } - - let errorString; - try { - if (typeof error === 'string') { - errorString = error; - } else { - errorString = ( - typeof error === 'object' && error !== null ? - // eslint-disable-next-line @typescript-eslint/no-base-to-string - error.toString() : - `${error}` - ); - if (/^\[object \w+\]$/.test(errorString)) { - errorString = JSON.stringify(error); - } - } - } catch (e) { - errorString = `${error}`; - } - - let errorStack; - try { - errorStack = ( - error instanceof Error ? - (typeof error.stack === 'string' ? error.stack.trimEnd() : '') : - '' - ); - } catch (e) { - errorStack = ''; - } - - let errorData; - try { - if (error instanceof ExtensionError) { - errorData = error.data; - } - } catch (e) { - // NOP - } - - if (errorStack.startsWith(errorString)) { - errorString = errorStack; - } else if (errorStack.length > 0) { - errorString += `\n${errorStack}`; - } - - let message = `${this._extensionName} has encountered a problem.`; - message += `\nOriginating URL: ${context.url}\n`; - message += errorString; - if (typeof errorData !== 'undefined') { - message += `\nData: ${JSON.stringify(errorData, null, 4)}`; - } - message += '\n\nIssues can be reported at https://github.com/themoeway/yomitan/issues'; - - /* eslint-disable no-console */ - switch (level) { - case 'log': console.log(message); break; - case 'info': console.info(message); break; - case 'debug': console.debug(message); break; - case 'warn': console.warn(message); break; - case 'error': console.error(message); break; - } - /* eslint-enable no-console */ - - this.trigger('log', {error, level, context}); - } - - /** - * Logs a warning. This function invokes `log` internally. - * @param {unknown} error The error to log. This is typically an `Error` or `Error`-like object. - * @param {?import('log').LogContext} context An optional context object for the error which should typically include a `url` field. - */ - warn(error, context = null) { - this.log(error, 'warn', context); - } - - /** - * Logs an error. This function invokes `log` internally. - * @param {unknown} error The error to log. This is typically an `Error` or `Error`-like object. - * @param {?import('log').LogContext} context An optional context object for the error which should typically include a `url` field. - */ - error(error, context = null) { - this.log(error, 'error', context); - } - - /** - * @param {import('log').LogLevel} errorLevel - * @returns {import('log').LogErrorLevelValue} - */ - getLogErrorLevelValue(errorLevel) { - switch (errorLevel) { - case 'log': - case 'info': - case 'debug': - return 0; - case 'warn': return 1; - case 'error': return 2; - } - } -} - -/** - * This object is the default logger used by the runtime. - */ -export const log = new Logger(); -- cgit v1.2.3