Start rewriting logs
This commit is contained in:
parent
77fcced776
commit
4000d0e027
@ -1,3 +1,4 @@
|
||||
import { BLANK_LOGGER_CONFIG, LogAggregator } from './lib/logging/LogAggregator';
|
||||
import Debug from './conf/Debug';
|
||||
import ExtensionMode from '../common/enums/ExtensionMode.enum';
|
||||
import Settings from './lib/Settings';
|
||||
@ -10,6 +11,7 @@ import EventBus from './lib/EventBus';
|
||||
import KeyboardHandler from './lib/kbm/KeyboardHandler';
|
||||
import { SiteSettings } from './lib/settings/SiteSettings';
|
||||
import UI from './lib/uwui/UI';
|
||||
import { ComponentLogger } from './lib/logging/ComponentLogger';
|
||||
|
||||
export default class UWContent {
|
||||
pageInfo: PageInfo;
|
||||
@ -17,7 +19,8 @@ export default class UWContent {
|
||||
settings: Settings;
|
||||
siteSettings: SiteSettings;
|
||||
keyboardHandler: KeyboardHandler;
|
||||
logger: Logger;
|
||||
logAggregator: LogAggregator;
|
||||
logger: ComponentLogger;
|
||||
eventBus: EventBus;
|
||||
isIframe: boolean = false;
|
||||
|
||||
@ -34,7 +37,7 @@ export default class UWContent {
|
||||
|
||||
reloadSettings() {
|
||||
try {
|
||||
this.logger.log('info', 'debug', 'Things happened in the popup. Will reload extension settings.');
|
||||
this.logger.debug('reloadSettings', 'Things happened in the popup. Will reload extension settings.');
|
||||
this.init();
|
||||
} catch (e) {
|
||||
console.warn('Ultrawidify: settings reload failed. This probably shouldn\'t outright kill the extension, but page reload is recommended.');
|
||||
@ -50,8 +53,9 @@ export default class UWContent {
|
||||
// logger init is the first thing that needs to run
|
||||
try {
|
||||
if (!this.logger) {
|
||||
this.logger = new Logger();
|
||||
await this.logger.init(baseLoggingOptions);
|
||||
this.logAggregator = new LogAggregator('◈');
|
||||
this.logger = new ComponentLogger(this.logAggregator, 'UWContent');
|
||||
await this.logAggregator.init(BLANK_LOGGER_CONFIG);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("logger init failed!", e)
|
||||
@ -67,7 +71,7 @@ export default class UWContent {
|
||||
if (!this.settings) {
|
||||
this.settings = new Settings({
|
||||
onSettingsChanged: () => this.reloadSettings(),
|
||||
logger: this.logger
|
||||
logAggregator: this.logAggregator
|
||||
});
|
||||
await this.settings.init();
|
||||
this.siteSettings = this.settings.getSiteSettings();
|
||||
@ -81,13 +85,13 @@ export default class UWContent {
|
||||
function: () => this.initPhase2()
|
||||
}
|
||||
);
|
||||
this.comms = new CommsClient('content-main-port', this.logger, this.eventBus);
|
||||
this.comms = new CommsClient('content-main-port', this.logAggregator, this.eventBus);
|
||||
this.eventBus.setComms(this.comms);
|
||||
|
||||
|
||||
this.initPhase2();
|
||||
} catch (e) {
|
||||
console.error('Ultrawidify initalization failed for some reason:', e);
|
||||
console.error('Ultrawidify initialization failed for some reason:', e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,21 +99,21 @@ export default class UWContent {
|
||||
initPhase2() {
|
||||
try {
|
||||
if (this.pageInfo) {
|
||||
this.logger.log('info', 'debug', '[uw.js::setup] An instance of pageInfo already exists and will be destroyed.');
|
||||
this.logger.info('setup', 'An instance of pageInfo already exists and will be destroyed.');
|
||||
this.pageInfo.destroy();
|
||||
}
|
||||
this.pageInfo = new PageInfo(this.eventBus, this.siteSettings, this.settings, this.logger);
|
||||
this.logger.log('info', 'debug', "[uw.js::setup] pageInfo initialized.");
|
||||
this.pageInfo = new PageInfo(this.eventBus, this.siteSettings, this.settings, this.logAggregator);
|
||||
this.logger.debug('setup', "pageInfo initialized.");
|
||||
|
||||
this.logger.log('info', 'debug', "[uw.js::setup] will try to initate KeyboardHandler.");
|
||||
this.logger.debug('setup', "will try to initate KeyboardHandler.");
|
||||
|
||||
if (this.keyboardHandler) {
|
||||
this.keyboardHandler.destroy();
|
||||
}
|
||||
this.keyboardHandler = new KeyboardHandler(this.eventBus, this.siteSettings, this.settings, this.logger);
|
||||
this.keyboardHandler = new KeyboardHandler(this.eventBus, this.siteSettings, this.settings, this.logAggregator);
|
||||
this.keyboardHandler.init();
|
||||
|
||||
this.logger.log('info', 'debug', "[uw.js::setup] KeyboardHandler initiated.");
|
||||
this.logger.debug('setup', "KeyboardHandler initiated.");
|
||||
|
||||
this.globalUi = new UI('ultrawidify-global-ui', {eventBus: this.eventBus, isGlobal: true});
|
||||
this.globalUi.enable();
|
||||
@ -117,7 +121,7 @@ export default class UWContent {
|
||||
|
||||
} catch (e) {
|
||||
console.error('Ultrawidify: failed to start extension. Error:', e)
|
||||
this.logger.log('error', 'debug', "[uw::init] FAILED TO START EXTENSION. Error:", e);
|
||||
this.logger.error('setup', "FAILED TO START EXTENSION. Error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { BLANK_LOGGER_CONFIG, LogAggregator } from './lib/logging/LogAggregator';
|
||||
import Debug from './conf/Debug.js';
|
||||
import BrowserDetect from './conf/BrowserDetect';
|
||||
import CommsServer from './lib/comms/CommsServer';
|
||||
@ -5,10 +6,17 @@ import Settings from './lib/Settings';
|
||||
import Logger, { baseLoggingOptions } from './lib/Logger';
|
||||
import { sleep } from '../common/js/utils';
|
||||
import EventBus, { EventBusCommand } from './lib/EventBus';
|
||||
import { ComponentLogger } from './lib/logging/ComponentLogger.js';
|
||||
|
||||
|
||||
const BASE_LOGGING_STYLES = {
|
||||
'log': 'background-color: #243; color: #4a8',
|
||||
}
|
||||
|
||||
export default class UWServer {
|
||||
settings: Settings;
|
||||
logger: Logger;
|
||||
logger: ComponentLogger;
|
||||
logAggregator: LogAggregator;
|
||||
comms: CommsServer;
|
||||
eventBus: EventBus;
|
||||
|
||||
@ -64,22 +72,13 @@ export default class UWServer {
|
||||
async setup() {
|
||||
try {
|
||||
// logger is the first thing that goes up
|
||||
const loggingOptions = {
|
||||
isBackgroundScript: true,
|
||||
allowLogging: false,
|
||||
useConfFromStorage: true,
|
||||
logAll: true,
|
||||
fileOptions: {
|
||||
enabled: false,
|
||||
},
|
||||
consoleOptions: {
|
||||
enabled: false
|
||||
}
|
||||
};
|
||||
this.logger = new Logger();
|
||||
await this.logger.init(loggingOptions);
|
||||
const loggingOptions = BLANK_LOGGER_CONFIG;
|
||||
|
||||
this.settings = new Settings({logger: this.logger});
|
||||
this.logAggregator = new LogAggregator('🔶bg-script🔶');
|
||||
this.logger = new ComponentLogger(this.logAggregator, 'UwServer', {styles: BASE_LOGGING_STYLES});
|
||||
await this.logAggregator.init(loggingOptions);
|
||||
|
||||
this.settings = new Settings({logAggregator: this.logAggregator});
|
||||
await this.settings.init();
|
||||
|
||||
this.eventBus = new EventBus({isUWServer: true});
|
||||
@ -130,7 +129,7 @@ export default class UWServer {
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.log('error','debug', '[UwServer::injectCss] Error while injecting css:', {error: e, css, sender});
|
||||
this.logger.error('injectCss', 'Error while injecting css:', {error: e, css, sender});
|
||||
}
|
||||
}
|
||||
async removeCss(css, sender) {
|
||||
@ -160,7 +159,7 @@ export default class UWServer {
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.log('error','debug', '[UwServer::injectCss] Error while removing css:', {error: e, css, sender});
|
||||
this.logger.error('injectCss', 'Error while removing css:', {error: e, css, sender});
|
||||
}
|
||||
}
|
||||
async replaceCss(oldCss, newCss, sender) {
|
||||
@ -205,9 +204,9 @@ export default class UWServer {
|
||||
}
|
||||
|
||||
this.currentSite = this.extractHostname(tab.url);
|
||||
this.logger.log('info', 'debug', '[UwServer::onTabSwitched] user switched tab. New site:', this.currentSite);
|
||||
this.logger.info('onTabSwitched', 'user switched tab. New site:', this.currentSite);
|
||||
} catch(e) {
|
||||
this.logger.log('error', 'debug', '[UwServer::onTabSwitched] there was a problem getting currnet site:', e)
|
||||
this.logger.info('onTabSwitched', 'there was a problem getting current site:', e)
|
||||
}
|
||||
|
||||
this.selectedSubitem = {
|
||||
@ -220,7 +219,7 @@ export default class UWServer {
|
||||
}
|
||||
|
||||
registerVideo(sender) {
|
||||
this.logger.log('info', 'comms', '[UWServer::registerVideo] Registering video.\nsender:', sender);
|
||||
this.logger.info('registerVideo', 'Registering video.\nsender:', sender);
|
||||
|
||||
const tabHostname = this.extractHostname(sender.tab.url);
|
||||
const frameHostname = this.extractHostname(sender.url);
|
||||
@ -254,11 +253,11 @@ export default class UWServer {
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.log('info', 'comms', '[UWServer::registerVideo] Video registered. current videoTabs:', this.videoTabs);
|
||||
this.logger.info('registerVideo', 'Video registered. current videoTabs:', this.videoTabs);
|
||||
}
|
||||
|
||||
unregisterVideo(sender) {
|
||||
this.logger.log('info', 'comms', '[UwServer::unregisterVideo] Unregistering video.\nsender:', sender);
|
||||
this.logger.info('unregisterVideo', 'Unregistering video.\nsender:', sender);
|
||||
if (this.videoTabs[sender.tab.id]) {
|
||||
if ( Object.keys(this.videoTabs[sender.tab.id].frames).length <= 1) {
|
||||
delete this.videoTabs[sender.tab.id]
|
||||
@ -268,27 +267,27 @@ export default class UWServer {
|
||||
}
|
||||
}
|
||||
}
|
||||
this.logger.log('info', 'comms', '[UwServer::unregisterVideo] Video has been unregistered. Current videoTabs:', this.videoTabs);
|
||||
this.logger.info('unregisterVideo', 'Video has been unregistered. Current videoTabs:', this.videoTabs);
|
||||
}
|
||||
|
||||
setSelectedTab(menu, subitem) {
|
||||
this.logger.log('info', 'comms', '[UwServer::setSelectedTab] saving selected tab for', menu, ':', subitem);
|
||||
this.logger.info('setSelectedTab', 'saving selected tab for', menu, ':', subitem);
|
||||
this.selectedSubitem[menu] = subitem;
|
||||
}
|
||||
|
||||
async getCurrentSite() {
|
||||
this.logger.log('info', 'comms', '%c[UWServer::getCurrentSite] received get-current-site ...', 'background-color: #243; color: #4a8');
|
||||
this.logger.info('getCurrentSite', 'received get-current-site ...');
|
||||
|
||||
const site = await this.getVideoTab();
|
||||
|
||||
// Don't propagate 'INVALID SITE' to the popup.
|
||||
if (site.host === 'INVALID SITE') {
|
||||
this.logger.log('info', 'comms', '%c[UWServer::getCurrentSite] Host is not valid — no info for current tab.', 'background-color: #243; color: #4a8');
|
||||
this.logger.info('getCurrentSite', 'Host is not valid — no info for current tab.');
|
||||
return;
|
||||
}
|
||||
|
||||
const tabHostname = await this.getCurrentTabHostname();
|
||||
this.logger.log('info', 'comms', '%c[UWServer::getCurrentSite] Returning data:', 'background-color: #243; color: #4a8', {site, tabHostname});
|
||||
this.logger.info('getCurrentSite', 'Returning data:', {site, tabHostname});
|
||||
|
||||
|
||||
this.eventBus.send(
|
||||
|
@ -13,15 +13,28 @@ import SettingsInterface from '../../common/interfaces/SettingsInterface';
|
||||
import AspectRatioType from '../../common/enums/AspectRatioType.enum';
|
||||
import { SiteSettings } from './settings/SiteSettings';
|
||||
import { SettingsSnapshotManager } from './settings/SettingsSnapshotManager';
|
||||
import { ComponentLogger } from './logging/ComponentLogger';
|
||||
import { LogAggregator } from './logging/LogAggregator';
|
||||
|
||||
if(process.env.CHANNEL !== 'stable'){
|
||||
console.info("Loading Settings");
|
||||
}
|
||||
|
||||
interface SettingsOptions {
|
||||
logAggregator: LogAggregator,
|
||||
onSettingsChanged?: () => void,
|
||||
afterSettingsSaved?: () => void,
|
||||
activeSettings?: SettingsInterface,
|
||||
}
|
||||
|
||||
interface SetSettingsOptions {
|
||||
forcePreserveVersion?: boolean,
|
||||
}
|
||||
|
||||
const SETTINGS_LOGGER_STYLES = {
|
||||
log: 'color: #81d288',
|
||||
}
|
||||
|
||||
class Settings {
|
||||
//#region flags
|
||||
useSync: boolean = false;
|
||||
@ -29,7 +42,9 @@ class Settings {
|
||||
//#endregion
|
||||
|
||||
//#region helper classes
|
||||
logger: Logger;
|
||||
|
||||
logAggregator: LogAggregator;
|
||||
logger: ComponentLogger;
|
||||
//#endregion
|
||||
|
||||
//#region data
|
||||
@ -49,12 +64,12 @@ class Settings {
|
||||
|
||||
//#endregion
|
||||
|
||||
constructor(options) {
|
||||
constructor(options: SettingsOptions) {
|
||||
// Options: activeSettings, updateCallback, logger
|
||||
this.logger = options?.logger;
|
||||
this.onSettingsChanged = options?.onSettingsChanged;
|
||||
this.afterSettingsSaved = options?.afterSettingsSaved;
|
||||
this.active = options?.activeSettings ?? undefined;
|
||||
this.logger = options.logAggregator && new ComponentLogger(options.logAggregator, 'Settings', {styles: SETTINGS_LOGGER_STYLES}) || undefined;;
|
||||
this.onSettingsChanged = options.onSettingsChanged;
|
||||
this.afterSettingsSaved = options.afterSettingsSaved;
|
||||
this.active = options.activeSettings ?? undefined;
|
||||
this.default = ExtensionConf;
|
||||
this.snapshotManager = new SettingsSnapshotManager();
|
||||
|
||||
@ -67,14 +82,14 @@ class Settings {
|
||||
if (!changes.uwSettings) {
|
||||
return;
|
||||
}
|
||||
this.logger?.log('info', 'settings', "[Settings::<storage/on change>] Settings have been changed outside of here. Updating active settings. Changes:", changes, "storage area:", area);
|
||||
this.logger?.info('storageOnChange', "Settings have been changed outside of here. Updating active settings. Changes:", changes, "storage area:", area);
|
||||
// if (changes['uwSettings'] && changes['uwSettings'].newValue) {
|
||||
// this.logger?.log('info', 'settings',"[Settings::<storage/on change>] new settings object:", JSON.parse(changes.uwSettings.newValue));
|
||||
// }
|
||||
const parsedSettings = JSON.parse(changes.uwSettings.newValue);
|
||||
this.setActive(parsedSettings);
|
||||
|
||||
this.logger?.log('info', 'debug', 'Does parsedSettings.preventReload exist?', parsedSettings.preventReload, "Does callback exist?", !!this.onSettingsChanged);
|
||||
this.logger?.info('storageOnChange', 'Does parsedSettings.preventReload exist?', parsedSettings.preventReload, "Does callback exist?", !!this.onSettingsChanged);
|
||||
|
||||
if (!parsedSettings.preventReload) {
|
||||
try {
|
||||
@ -82,23 +97,23 @@ class Settings {
|
||||
try {
|
||||
fn();
|
||||
} catch (e) {
|
||||
this.logger?.log('warn', 'settings', "[Settings] afterSettingsChanged fallback failed. It's possible that a vue component got destroyed, and this function is nothing more than vestigal remains. It would be nice if we implemented something that allows us to remove callback functions from array, and remove vue callbacks from the callback array when their respective UI component gets destroyed. Or this could be an error with the function itself. IDK, here's the error.", e)
|
||||
this.logger?.warn('storageOnChange', "afterSettingsChanged fallback failed. It's possible that a vue component got destroyed, and this function is nothing more than vestigal remains. It would be nice if we implemented something that allows us to remove callback functions from array, and remove vue callbacks from the callback array when their respective UI component gets destroyed. Or this could be an error with the function itself. IDK, here's the error.", e)
|
||||
}
|
||||
}
|
||||
if (this.onSettingsChanged) {
|
||||
this.onSettingsChanged();
|
||||
}
|
||||
|
||||
this.logger?.log('info', 'settings', '[Settings] Update callback finished.')
|
||||
this.logger?.info('storageOnChange', 'Update callback finished.')
|
||||
} catch (e) {
|
||||
this.logger?.log('error', 'settings', "[Settings] CALLING UPDATE CALLBACK FAILED. Reason:", e)
|
||||
this.logger?.error('storageOnChange', "CALLING UPDATE CALLBACK FAILED. Reason:", e)
|
||||
}
|
||||
}
|
||||
for (const fn of this.afterSettingsChangedCallbacks) {
|
||||
try {
|
||||
fn();
|
||||
} catch (e) {
|
||||
this.logger?.log('warn', 'settings', "[Settings] afterSettingsChanged fallback failed. It's possible that a vue component got destroyed, and this function is nothing more than vestigal remains. It would be nice if we implemented something that allows us to remove callback functions from array, and remove vue callbacks from the callback array when their respective UI component gets destroyed. Or this could be an error with the function itself. IDK, here's the error.", e)
|
||||
this.logger?.warn('storageOnChange', "afterSettingsChanged fallback failed. It's possible that a vue component got destroyed, and this function is nothing more than vestigal remains. It would be nice if we implemented something that allows us to remove callback functions from array, and remove vue callbacks from the callback array when their respective UI component gets destroyed. Or this could be an error with the function itself. IDK, here's the error.", e)
|
||||
}
|
||||
}
|
||||
if (this.afterSettingsSaved) {
|
||||
@ -188,7 +203,7 @@ class Settings {
|
||||
let index = this.findFirstNecessaryPatch(oldVersion);
|
||||
|
||||
if (index === -1) {
|
||||
this.logger?.log('info','settings','[Settings::applySettingsPatches] There are no pending conf patches.');
|
||||
this.logger?.info('applySettingsPatches','There are no pending conf patches.');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -205,20 +220,14 @@ class Settings {
|
||||
|
||||
|
||||
// apply all remaining patches
|
||||
this.logger?.log('info', 'settings', `[Settings::applySettingsPatches] There are ${ExtensionConfPatch.length - index} settings patches to apply`);
|
||||
this.logger?.info('applySettingsPatches', `There are ${ExtensionConfPatch.length - index} settings patches to apply`);
|
||||
while (index < ExtensionConfPatch.length) {
|
||||
const updateFn = ExtensionConfPatch[index].updateFn;
|
||||
if (updateFn) {
|
||||
try {
|
||||
updateFn(this.active, this.getDefaultSettings());
|
||||
} catch (e) {
|
||||
this.logger?.log('error', 'settings', '[Settings::applySettingsPatches] Failed to execute update function. Keeping settings object as-is. Error:', e);
|
||||
console.warn(
|
||||
'————————————————————————————————————\n',
|
||||
'Applying patch', index, ' failed :', '\n',
|
||||
e, '\n',
|
||||
'————————————————————————————————————\n',
|
||||
);
|
||||
this.logger?.error('applySettingsPatches', 'Failed to execute update function. Keeping settings object as-is. Error:', e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,7 +239,7 @@ class Settings {
|
||||
let settings = await this.get();
|
||||
|
||||
if (settings?.dev?.loadFromSnapshot) {
|
||||
this.logger?.log('info', 'settings', '[Settings::init] Dev mode is enabled, Loading settings from snapshot:', settings.dev.loadFromSnapshot);
|
||||
this.logger?.info('init', 'Dev mode is enabled, Loading settings from snapshot:', settings.dev.loadFromSnapshot);
|
||||
const snapshot = await this.snapshotManager.getSnapshot();
|
||||
if (snapshot) {
|
||||
settings = snapshot.settings;
|
||||
@ -245,7 +254,7 @@ class Settings {
|
||||
const oldVersion = settings?.version ?? this.version;
|
||||
|
||||
if (settings) {
|
||||
this.logger?.log('info', 'settings', "[Settings::init] Configuration fetched from storage:", settings,
|
||||
this.logger?.info('init', "Configuration fetched from storage:", settings,
|
||||
"\nlast saved with:", settings.version,
|
||||
"\ncurrent version:", this.version
|
||||
);
|
||||
@ -253,10 +262,9 @@ class Settings {
|
||||
|
||||
// if there's no settings saved, return default settings.
|
||||
if(! settings || (Object.keys(settings).length === 0 && settings.constructor === Object)) {
|
||||
this.logger?.log(
|
||||
'info',
|
||||
'settings',
|
||||
'[Settings::init] settings don\'t exist. Using defaults.\n#keys:',
|
||||
this.logger?.info(
|
||||
'init',
|
||||
'settings don\'t exist. Using defaults.\n#keys:',
|
||||
settings ? Object.keys(settings).length : 0,
|
||||
'\nsettings:',
|
||||
settings
|
||||
@ -281,7 +289,7 @@ class Settings {
|
||||
|
||||
// check if extension has been updated. If not, return settings as they were retrieved
|
||||
if (this.active.version === this.version) {
|
||||
this.logger?.log('info', 'settings', "[Settings::init] extension was saved with current version of ultrawidify. Returning object as-is.");
|
||||
this.logger?.info('init', "extension was saved with current version of ultrawidify. Returning object as-is.");
|
||||
return this.active;
|
||||
}
|
||||
|
||||
@ -292,7 +300,7 @@ class Settings {
|
||||
// if extension has been updated, update existing settings with any options added in the
|
||||
// new version. In addition to that, we remove old keys that are no longer used.
|
||||
const patched = ObjectCopy.addNew(settings, this.default);
|
||||
this.logger?.log('info', 'settings',"[Settings.init] Results from ObjectCopy.addNew()?", patched, "\n\nSettings from storage", settings, "\ndefault?", this.default);
|
||||
this.logger?.info('init',"Results from ObjectCopy.addNew()?", patched, "\n\nSettings from storage", settings, "\ndefault?", this.default);
|
||||
|
||||
if (patched) {
|
||||
this.active = patched;
|
||||
@ -315,7 +323,7 @@ class Settings {
|
||||
|
||||
ret = await chrome.storage.local.get('uwSettings');
|
||||
|
||||
this.logger?.log('info', 'settings', 'Got settings:', ret && ret.uwSettings && JSON.parse(ret.uwSettings));
|
||||
this.logger?.info('get', 'Got settings:', ret && ret.uwSettings && JSON.parse(ret.uwSettings));
|
||||
|
||||
try {
|
||||
return JSON.parse(ret.uwSettings) as SettingsInterface;
|
||||
@ -328,7 +336,7 @@ class Settings {
|
||||
if (!options || !options.forcePreserveVersion) {
|
||||
extensionConf.version = this.version;
|
||||
}
|
||||
this.logger?.log('info', 'settings', "[Settings::set] setting new settings:", extensionConf)
|
||||
this.logger?.info('set', "setting new settings:", extensionConf)
|
||||
|
||||
return chrome.storage.local.set( {'uwSettings': JSON.stringify(extensionConf)});
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ import BrowserDetect from '../../conf/BrowserDetect';
|
||||
import Logger from '../Logger';
|
||||
import Settings from '../Settings';
|
||||
import EventBus, { EventBusContext } from '../EventBus';
|
||||
import { ComponentLogger } from '../logging/ComponentLogger';
|
||||
import { LogAggregator } from '../logging/LogAggregator';
|
||||
|
||||
if (process.env.CHANNEL !== 'stable'){
|
||||
console.info("Loading CommsClient");
|
||||
@ -73,7 +75,7 @@ class CommsClient {
|
||||
name: string;
|
||||
origin: CommsOrigin;
|
||||
|
||||
logger: Logger;
|
||||
logger: ComponentLogger;
|
||||
settings: any; // sus?
|
||||
|
||||
eventBus: EventBus;
|
||||
@ -82,10 +84,10 @@ class CommsClient {
|
||||
port: chrome.runtime.Port;
|
||||
|
||||
//#region lifecycle
|
||||
constructor(name: string, logger: Logger, eventBus: EventBus) {
|
||||
constructor(name: string, logAggregator: LogAggregator, eventBus: EventBus) {
|
||||
this.name = name;
|
||||
try {
|
||||
this.logger = logger;
|
||||
this.logger = new ComponentLogger(logAggregator, 'CommsClient', {});
|
||||
this.eventBus = eventBus;
|
||||
|
||||
if (name === 'popup-port') {
|
||||
@ -101,16 +103,16 @@ class CommsClient {
|
||||
this.port = chrome.runtime.connect(null, {name: name});
|
||||
// }
|
||||
|
||||
this.logger.onLogEnd(
|
||||
(history) => {
|
||||
this.logger.log('info', 'comms', 'Sending logging-stop-and-save to background script ...');
|
||||
try {
|
||||
this.port.postMessage({cmd: 'logging-stop-and-save', host: window.location.hostname, history})
|
||||
} catch (e) {
|
||||
this.logger.log('error', 'comms', 'Failed to send message to background script. Error:', e);
|
||||
}
|
||||
}
|
||||
);
|
||||
// this.logger.onLogEnd(
|
||||
// (history) => {
|
||||
// this.logger.log('info', 'comms', 'Sending logging-stop-and-save to background script ...');
|
||||
// try {
|
||||
// this.port.postMessage({cmd: 'logging-stop-and-save', host: window.location.hostname, history})
|
||||
// } catch (e) {
|
||||
// this.logger.log('error', 'comms', 'Failed to send message to background script. Error:', e);
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
|
||||
this._listener = m => this.processReceivedMessage(m);
|
||||
this.port.onMessage.addListener(this._listener);
|
||||
@ -118,7 +120,7 @@ class CommsClient {
|
||||
this.commsId = (Math.random() * 20).toFixed(0);
|
||||
|
||||
} catch (e) {
|
||||
console.error("CONSTRUCOTR FAILED:", e)
|
||||
console.error("CONSTRUCTOR FAILED:", e)
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,6 +132,8 @@ class CommsClient {
|
||||
//#endregion
|
||||
|
||||
async sendMessage(message, context?: EventBusContext){
|
||||
this.logger.info('sendMessage', ' <<< Sending message to background script:', message);
|
||||
|
||||
message = JSON.parse(JSON.stringify(message)); // vue quirk. We should really use vue store instead
|
||||
|
||||
// content script client and popup client differ in this one thing
|
||||
|
70
src/ext/lib/logging/ComponentLogger.ts
Normal file
70
src/ext/lib/logging/ComponentLogger.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { LogAggregator, LogSourceOptions } from './LogAggregator';
|
||||
|
||||
export enum LogLevel {
|
||||
Debug = 'debug',
|
||||
Info = 'info',
|
||||
Log = 'log',
|
||||
Warn = 'warn',
|
||||
Error = 'error',
|
||||
}
|
||||
|
||||
export type ComponentLoggerOptions = {
|
||||
styles?: {
|
||||
[x in LogLevel]?: string;
|
||||
}
|
||||
}
|
||||
|
||||
export class ComponentLogger {
|
||||
private logAggregator: LogAggregator;
|
||||
private component: string;
|
||||
private componentOptions?: ComponentLoggerOptions;
|
||||
|
||||
constructor(logAggregator: LogAggregator, component: string, componentOptions?: ComponentLoggerOptions) {
|
||||
this.logAggregator = logAggregator;
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
private handleLog(logLevel: LogLevel, sourceFunction: string | LogSourceOptions, ...message: any) {
|
||||
let functionSource = typeof sourceFunction === 'string' ? sourceFunction : sourceFunction?.src;
|
||||
|
||||
let consoleMessageString = `[${this.component}${functionSource ? `::${functionSource}` : ''}] `;
|
||||
const consoleMessageData = []
|
||||
|
||||
for (const m of message) {
|
||||
if (typeof m === 'string') {
|
||||
consoleMessageString = `${consoleMessageString} ${m}`;
|
||||
} else if (typeof m === 'number') {
|
||||
consoleMessageString = `${consoleMessageString} %f`;
|
||||
} else if (m instanceof HTMLElement) {
|
||||
consoleMessageString = `${consoleMessageString} %o`;
|
||||
} else {
|
||||
consoleMessageString = `${consoleMessageString} %O`;
|
||||
}
|
||||
}
|
||||
|
||||
const style = this.componentOptions?.styles?.[logLevel] ?? this.componentOptions?.styles?.[LogLevel.Log];
|
||||
if (style) {
|
||||
consoleMessageString = `%c${consoleMessageString}`;
|
||||
consoleMessageData.unshift(style);
|
||||
}
|
||||
|
||||
this.logAggregator.log(this.component, logLevel, typeof sourceFunction === 'object' ? sourceFunction : undefined, consoleMessageString, ...consoleMessageData);
|
||||
}
|
||||
|
||||
debug(sourceFunction: string | LogSourceOptions, ...message: any[]) {
|
||||
this.handleLog(LogLevel.Debug, sourceFunction, ...message);
|
||||
}
|
||||
info(sourceFunction: string | LogSourceOptions, ...message: any[]) {
|
||||
this.handleLog(LogLevel.Info, sourceFunction, ...message);
|
||||
}
|
||||
log(sourceFunction: string | LogSourceOptions, ...message: any[]) {
|
||||
this.handleLog(LogLevel.Log, sourceFunction, ...message);
|
||||
}
|
||||
warn(sourceFunction: string | LogSourceOptions, ...message: any[]) {
|
||||
this.handleLog(LogLevel.Warn, sourceFunction, ...message);
|
||||
}
|
||||
error(sourceFunction: string | LogSourceOptions, ...message: any[]) {
|
||||
this.handleLog(LogLevel.Error, sourceFunction, ...message);
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +1,218 @@
|
||||
import { log } from 'console';
|
||||
|
||||
export const BLANK_LOGGER_CONFIG: LogConfig = {
|
||||
logToConsole: false,
|
||||
logToFile: false,
|
||||
component: {
|
||||
aard: { enabled: false },
|
||||
resizer: { enabled: false },
|
||||
comms: { enabled: false },
|
||||
settings: { enabled: false },
|
||||
eventBus: { enabled: false },
|
||||
},
|
||||
origins: {
|
||||
videoRescan: { disabled: true},
|
||||
}
|
||||
}
|
||||
|
||||
export interface LogSourceOptions {
|
||||
src?: string;
|
||||
origin?: string;
|
||||
}
|
||||
|
||||
export interface LogComponentConfig {
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface LogConfig {
|
||||
logToConsole?: boolean;
|
||||
logToFile?: boolean;
|
||||
stopAfter?: number;
|
||||
component?: {[x: string]: LogComponentConfig};
|
||||
origins?: {
|
||||
videoRescan?: {
|
||||
disabled: boolean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class LogAggregator {
|
||||
private segment: string;
|
||||
private config: LogConfig;
|
||||
|
||||
private startTime: number;
|
||||
|
||||
history: any[];
|
||||
|
||||
log(message: any, originData: any) {
|
||||
static async getConfig() {
|
||||
let ret = await chrome.storage.local.get('uw-log-config');
|
||||
|
||||
if (process.env.CHANNEL === 'dev') {
|
||||
try {
|
||||
console.info("[Logger::getSaved] Got settings:", JSON.parse(ret.uwLogger));
|
||||
} catch (e) {
|
||||
console.info("[Logger::getSaved] No settings.")
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(ret['uw-log-config']);
|
||||
} catch (e) {
|
||||
return JSON.parse(JSON.stringify(BLANK_LOGGER_CONFIG));
|
||||
}
|
||||
}
|
||||
|
||||
static saveConfig(conf: LogConfig) {
|
||||
if (process.env.CHANNEL === 'dev') {
|
||||
console.info('Saving logger conf:', conf)
|
||||
}
|
||||
|
||||
chrome.storage.local.set( {'uw-log-config': JSON.stringify(conf)});
|
||||
}
|
||||
|
||||
static syncConfig(callback: (x) => void) {
|
||||
chrome.storage.onChanged.addListener( (changes, area) => {
|
||||
if (changes.uwLogger) {
|
||||
const newLoggerConf = JSON.parse(changes.uwLogger.newValue)
|
||||
if (process.env.CHANNEL === 'dev') {
|
||||
console.info('Logger settings reloaded. New conf:', newLoggerConf);
|
||||
}
|
||||
callback(newLoggerConf);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
constructor(segment: string) {
|
||||
this.segment = segment;
|
||||
|
||||
chrome.storage.onChanged.addListener((changes, area) => {
|
||||
this.storageChangeListener(changes, area)
|
||||
});
|
||||
}
|
||||
|
||||
private canLog(component: string, sourceOptions?: LogSourceOptions): boolean {
|
||||
if (this.config?.component?.[component]?.enabled) {
|
||||
if (sourceOptions?.origin && this.config?.origins?.[sourceOptions.origin]?.disabled) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private storageChangeListener(changes, area) {
|
||||
if (!changes.uwLogger) {
|
||||
console.info('We dont have any logging settings, not processing frther');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.config = JSON.parse(changes['uw-log-config'].newValue);
|
||||
} catch (e) {
|
||||
console.warn('[uwLogger] Error while trying to parse new conf for logger:', e, '\nWe received the following changes:', changes, 'for area:', area);
|
||||
}
|
||||
|
||||
// This code can only execute if user tried to enable or disable logging
|
||||
// through the popup. In cases like this, we do not gate the console.log
|
||||
// behind a check, since we _always_ want to have this feedback in response
|
||||
// to an action.
|
||||
console.info(
|
||||
'[uwLogger] logger config changed! New configuration:',
|
||||
this.config, '\nraw changes:', changes, 'area?', area,
|
||||
'\n————————————————————————————————————————————————————————————————————————\n\n\n\n\n\n\n\n\n\n\n\n-----\nLogging with new settings starts now.'
|
||||
);
|
||||
|
||||
this.init(this.config);
|
||||
}
|
||||
|
||||
private parseStack() {
|
||||
const trace = (new Error()).stack;
|
||||
|
||||
const stackInfo: any = {};
|
||||
// we turn our stack into array and remove the "file::line" part of the trace,
|
||||
// since that is useless because minification/webpack
|
||||
stackInfo['stack'] = {trace: trace.split('\n').map(a => a.split('@')[0])};
|
||||
|
||||
// here's possible sources that led to this log entry
|
||||
stackInfo['periodicPlayerCheck'] = false;
|
||||
stackInfo['periodicVideoStyleChangeCheck'] = false;
|
||||
stackInfo['aard'] = false;
|
||||
stackInfo['keyboard'] = false;
|
||||
stackInfo['popup'] = false;
|
||||
stackInfo['mousemove'] = false;
|
||||
stackInfo['exitLogs'] = false;
|
||||
|
||||
// here we check which source triggered the action. There can be more
|
||||
// than one source, too, so we don't break when we find the first one
|
||||
for (const line of stackInfo.stack.trace) {
|
||||
if (line === 'doPeriodicPlayerElementChangeCheck') {
|
||||
stackInfo['periodicPlayerCheck'] = true;
|
||||
} else if (line === 'doPeriodicFallbackChangeDetectionCheck') {
|
||||
stackInfo['periodicVideoStyleChangeCheck'] = true;
|
||||
} else if (line === 'frameCheck') {
|
||||
stackInfo['aard'] = true;
|
||||
} else if (line === 'execAction') {
|
||||
stackInfo['keyboard'] = true;
|
||||
} else if (line === 'processReceivedMessage') {
|
||||
stackInfo['popup'] = true;
|
||||
} else if (line === 'handleMouseMove') {
|
||||
stackInfo['mousemove'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// exitLog overrides any other exclusions, so we look for it separately.
|
||||
// we also remove some of the unnecessary messages to reduce log file size
|
||||
for(let i = 0; i < stackInfo.stack.trace.length; i++) {
|
||||
if (stackInfo.stack.trace[i] === 'finish') {
|
||||
stackInfo['exitLogs'] = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// if we hit one of these, we remove the rest of the array and call it a
|
||||
// day. Chances are there's nothing of value past this point.
|
||||
if (stackInfo.stack.trace[i].indexOf('promise callback') !== -1
|
||||
|| stackInfo.stack.trace[i].indexOf('asyncGeneratorStep') !== -1
|
||||
|| stackInfo.stack.trace[i].indexOf('_asyncToGenerator') !== -1
|
||||
|| stackInfo.stack.trace[i].startsWith('_next')) {
|
||||
stackInfo.stack.trace.splice(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return stackInfo;
|
||||
}
|
||||
|
||||
// TODO: implement this
|
||||
private stopLogging() {
|
||||
|
||||
}
|
||||
|
||||
async init(config: LogConfig) {
|
||||
this.config = config;
|
||||
this.startTime = performance.now();
|
||||
|
||||
if (this.config?.stopAfter) {
|
||||
setTimeout(
|
||||
() => {
|
||||
this.stopLogging();
|
||||
},
|
||||
this.config.stopAfter * 1000
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
log(component: string, logLevel: string, sourceOptions: LogSourceOptions, message: string, ...data: any[]) {
|
||||
if (! this.canLog(component, sourceOptions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.config.logToFile) {
|
||||
|
||||
}
|
||||
|
||||
if (this.config.logToConsole) {
|
||||
console[logLevel](`[${this.segment}]>>${message}`, ...data, {stack: this.parseStack()});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import CommsClient from '../comms/CommsClient';
|
||||
import EventBus from '../EventBus';
|
||||
import { SiteSettings } from '../settings/SiteSettings';
|
||||
import IframeManager from './IframeManager';
|
||||
import { LogAggregator } from '../logging/LogAggregator';
|
||||
import { ComponentLogger } from '../logging/ComponentLogger';
|
||||
|
||||
if (process.env.CHANNEL !== 'stable'){
|
||||
console.info("Loading PageInfo");
|
||||
@ -52,7 +54,8 @@ class PageInfo {
|
||||
//#endregion
|
||||
|
||||
//#region helper objects
|
||||
logger: Logger;
|
||||
logAggregator: LogAggregator;
|
||||
logger: ComponentLogger;
|
||||
settings: Settings;
|
||||
siteSettings: SiteSettings;
|
||||
comms: CommsClient;
|
||||
@ -80,8 +83,9 @@ class PageInfo {
|
||||
}
|
||||
};
|
||||
|
||||
constructor(eventBus: EventBus, siteSettings: SiteSettings, settings: Settings, logger: Logger, readOnly = false){
|
||||
this.logger = logger;
|
||||
constructor(eventBus: EventBus, siteSettings: SiteSettings, settings: Settings, logAggregator: LogAggregator, readOnly = false){
|
||||
this.logAggregator = logAggregator;
|
||||
this.logger = new ComponentLogger(logAggregator, 'PageInfo', {});
|
||||
this.settings = settings;
|
||||
this.siteSettings = siteSettings;
|
||||
|
||||
@ -109,10 +113,18 @@ class PageInfo {
|
||||
this.scheduleUrlCheck();
|
||||
|
||||
document.addEventListener('fullscreenchange', this.fsEventListener);
|
||||
|
||||
this.eventBus.subscribeMulti({
|
||||
'probe-video': {
|
||||
function: () => {
|
||||
console.warn('[uw] probe-video event received..');
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
destroy() {
|
||||
// this.logger.log('info', ['debug', 'init'], "[PageInfo::destroy] destroying all videos!")
|
||||
// this.logger.debug('destroy', 'destroying all videos!")
|
||||
if(this.rescanTimer){
|
||||
clearTimeout(this.rescanTimer);
|
||||
}
|
||||
@ -121,7 +133,7 @@ class PageInfo {
|
||||
this.eventBus.send('noVideo', undefined);
|
||||
video.videoData.destroy();
|
||||
} catch (e) {
|
||||
this.logger.log('error', ['debug', 'init'], '[PageInfo::destroy] unable to destroy video! Error:', e);
|
||||
this.logger.error('destroy', 'unable to destroy video! Error:', e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,7 +240,7 @@ class PageInfo {
|
||||
this.hasVideos = false;
|
||||
|
||||
if(rescanReason == RescanReason.PERIODIC){
|
||||
this.logger.log('info', 'videoRescan', "[PageInfo::rescan] Scheduling normal rescan.")
|
||||
this.logger.info({src: 'rescan', origin: 'videoRescan'}, "Scheduling normal rescan.")
|
||||
this.scheduleRescan(RescanReason.PERIODIC);
|
||||
}
|
||||
return;
|
||||
@ -265,16 +277,16 @@ class PageInfo {
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.log('info', 'videoRescan', "[PageInfo::rescan] found new video candidate:", videoElement, "NOTE:: Video initialization starts here:\n--------------------------------\n")
|
||||
this.logger.info({src: 'rescan', origin: 'videoRescan'}, "found new video candidate:", videoElement, "NOTE:: Video initialization starts here:\n--------------------------------\n")
|
||||
|
||||
try {
|
||||
const newVideo = new VideoData(videoElement, this.settings, this.siteSettings, this);
|
||||
this.videos.push({videoData: newVideo, element: videoElement});
|
||||
} catch (e) {
|
||||
this.logger.log('error', 'debug', "rescan error: failed to initialize videoData. Skipping this video.",e);
|
||||
this.logger.error('rescan', "rescan error: failed to initialize videoData. Skipping this video.",e);
|
||||
}
|
||||
|
||||
this.logger.log('info', 'videoRescan', "END VIDEO INITIALIZATION\n\n\n-------------------------------------\nvideos[] is now this:", this.videos,"\n\n\n\n\n\n\n\n")
|
||||
this.logger.info({src: 'rescan', origin: 'videoRescan'}, "END VIDEO INITIALIZATION\n\n\n-------------------------------------\nvideos[] is now this:", this.videos,"\n\n\n\n\n\n\n\n")
|
||||
}
|
||||
|
||||
this.removeDestroyed();
|
||||
@ -313,7 +325,7 @@ class PageInfo {
|
||||
// if we encounter a fuckup, we can assume that no videos were found on the page. We destroy all videoData
|
||||
// objects to prevent multiple initialization (which happened, but I don't know why). No biggie if we destroyed
|
||||
// videoData objects in error — they'll be back in the next rescan
|
||||
this.logger.log('error', 'debug', "rescan error: — destroying all videoData objects",e);
|
||||
this.logger.error('rescan', "rescan error: — destroying all videoData objects",e);
|
||||
for (const v of this.videos) {
|
||||
v.videoData.destroy();
|
||||
}
|
||||
@ -348,7 +360,7 @@ class PageInfo {
|
||||
ths = null;
|
||||
}, this.settings.active.pageInfo.timeouts.rescan, RescanReason.PERIODIC)
|
||||
} catch(e) {
|
||||
this.logger.log('error', 'debug', "[PageInfo::scheduleRescan] scheduling rescan failed. Here's why:",e)
|
||||
this.logger.error('scheduleRescan', "scheduling rescan failed. Here's why:",e)
|
||||
}
|
||||
}
|
||||
|
||||
@ -366,13 +378,13 @@ class PageInfo {
|
||||
ths = null;
|
||||
}, this.settings.active.pageInfo.timeouts.urlCheck)
|
||||
} catch(e){
|
||||
this.logger.log('error', 'debug', "[PageInfo::scheduleUrlCheck] scheduling URL check failed. Here's why:",e)
|
||||
this.logger.log('scheduleUrlCheck', "scheduling URL check failed. Here's why:",e)
|
||||
}
|
||||
}
|
||||
|
||||
ghettoUrlCheck() {
|
||||
if (this.lastUrl != window.location.href){
|
||||
this.logger.log('error', 'videoRescan', "[PageInfo::ghettoUrlCheck] URL has changed. Triggering a rescan!");
|
||||
this.logger.warn('ghettoUrlCheck', "URL has changed. Triggering a rescan!");
|
||||
|
||||
this.rescan(RescanReason.URL_CHANGE);
|
||||
this.lastUrl = window.location.href;
|
||||
|
Loading…
Reference in New Issue
Block a user