Files
Remote-Control-Center/mc_test/node_modules/electron-log/src/node/EventLogger.js
2025-11-25 09:56:15 +03:00

248 lines
5.7 KiB
JavaScript
Executable File

'use strict';
class EventLogger {
disposers = [];
format = '{eventSource}#{eventName}:';
formatters = {
app: {
'certificate-error': ({ args }) => {
return this.arrayToObject(args.slice(1, 4), [
'url',
'error',
'certificate',
]);
},
'child-process-gone': ({ args }) => {
return args.length === 1 ? args[0] : args;
},
'render-process-gone': ({ args: [webContents, details] }) => {
return details && typeof details === 'object'
? { ...details, ...this.getWebContentsDetails(webContents) }
: [];
},
},
webContents: {
'console-message': ({ args: [level, message, line, sourceId] }) => {
// 0: debug, 1: info, 2: warning, 3: error
if (level < 3) {
return undefined;
}
return { message, source: `${sourceId}:${line}` };
},
'did-fail-load': ({ args }) => {
return this.arrayToObject(args, [
'errorCode',
'errorDescription',
'validatedURL',
'isMainFrame',
'frameProcessId',
'frameRoutingId',
]);
},
'did-fail-provisional-load': ({ args }) => {
return this.arrayToObject(args, [
'errorCode',
'errorDescription',
'validatedURL',
'isMainFrame',
'frameProcessId',
'frameRoutingId',
]);
},
'plugin-crashed': ({ args }) => {
return this.arrayToObject(args, ['name', 'version']);
},
'preload-error': ({ args }) => {
return this.arrayToObject(args, ['preloadPath', 'error']);
},
},
};
events = {
app: {
'certificate-error': true,
'child-process-gone': true,
'render-process-gone': true,
},
webContents: {
// 'console-message': true,
'did-fail-load': true,
'did-fail-provisional-load': true,
'plugin-crashed': true,
'preload-error': true,
'unresponsive': true,
},
};
externalApi = undefined;
level = 'error';
scope = '';
constructor(options = {}) {
this.setOptions(options);
}
setOptions({
events,
externalApi,
level,
logger,
format,
formatters,
scope,
}) {
if (typeof events === 'object') {
this.events = events;
}
if (typeof externalApi === 'object') {
this.externalApi = externalApi;
}
if (typeof level === 'string') {
this.level = level;
}
if (typeof logger === 'object') {
this.logger = logger;
}
if (typeof format === 'string' || typeof format === 'function') {
this.format = format;
}
if (typeof formatters === 'object') {
this.formatters = formatters;
}
if (typeof scope === 'string') {
this.scope = scope;
}
}
startLogging(options = {}) {
this.setOptions(options);
this.disposeListeners();
for (const eventName of this.getEventNames(this.events.app)) {
this.disposers.push(
this.externalApi.onAppEvent(eventName, (...handlerArgs) => {
this.handleEvent({ eventSource: 'app', eventName, handlerArgs });
}),
);
}
for (const eventName of this.getEventNames(this.events.webContents)) {
this.disposers.push(
this.externalApi.onEveryWebContentsEvent(
eventName,
(...handlerArgs) => {
this.handleEvent(
{ eventSource: 'webContents', eventName, handlerArgs },
);
},
),
);
}
}
stopLogging() {
this.disposeListeners();
}
arrayToObject(array, fieldNames) {
const obj = {};
fieldNames.forEach((fieldName, index) => {
obj[fieldName] = array[index];
});
if (array.length > fieldNames.length) {
obj.unknownArgs = array.slice(fieldNames.length);
}
return obj;
}
disposeListeners() {
this.disposers.forEach((disposer) => disposer());
this.disposers = [];
}
formatEventLog({ eventName, eventSource, handlerArgs }) {
const [event, ...args] = handlerArgs;
if (typeof this.format === 'function') {
return this.format({ args, event, eventName, eventSource });
}
const formatter = this.formatters[eventSource]?.[eventName];
let formattedArgs = args;
if (typeof formatter === 'function') {
formattedArgs = formatter({ args, event, eventName, eventSource });
}
if (!formattedArgs) {
return undefined;
}
const eventData = {};
if (Array.isArray(formattedArgs)) {
eventData.args = formattedArgs;
} else if (typeof formattedArgs === 'object') {
Object.assign(eventData, formattedArgs);
}
if (eventSource === 'webContents') {
Object.assign(eventData, this.getWebContentsDetails(event?.sender));
}
const title = this.format
.replace('{eventSource}', eventSource === 'app' ? 'App' : 'WebContents')
.replace('{eventName}', eventName);
return [title, eventData];
}
getEventNames(eventMap) {
if (!eventMap || typeof eventMap !== 'object') {
return [];
}
return Object.entries(eventMap)
.filter(([_, listen]) => listen)
.map(([eventName]) => eventName);
}
getWebContentsDetails(webContents) {
if (!webContents?.loadURL) {
return {};
}
try {
return {
webContents: {
id: webContents.id,
url: webContents.getURL(),
},
};
} catch {
return {};
}
}
handleEvent({ eventName, eventSource, handlerArgs }) {
const log = this.formatEventLog({ eventName, eventSource, handlerArgs });
if (log) {
const logFns = this.scope ? this.logger.scope(this.scope) : this.logger;
logFns?.[this.level]?.(...log);
}
}
}
module.exports = EventLogger;