electron-log
Version:
Just a simple logging module for your Electron application
166 lines (139 loc) • 4.42 kB
JavaScript
;
const fs = require('fs');
const os = require('os');
const path = require('path');
const FileRegistry = require('./FileRegistry');
const { transform } = require('../../../core/transforms/transform');
const { removeStyles } = require('../../../core/transforms/style');
const {
format,
concatFirstStringElements,
} = require('../../../core/transforms/format');
const { toString } = require('../../transforms/object');
module.exports = fileTransportFactory;
// Shared between multiple file transport instances
const globalRegistry = new FileRegistry();
function fileTransportFactory(
logger,
{ registry = globalRegistry, externalApi } = {},
) {
/** @type {PathVariables} */
let pathVariables;
if (registry.listenerCount('error') < 1) {
registry.on('error', (e, file) => {
logConsole(`Can't write to ${file}`, e);
});
}
return Object.assign(transport, {
fileName: getDefaultFileName(logger.variables.processType),
format: '[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}]{scope} {text}',
getFile,
inspectOptions: { depth: 5 },
level: 'silly',
maxSize: 1024 ** 2,
readAllLogs,
sync: true,
transforms: [removeStyles, format, concatFirstStringElements, toString],
writeOptions: { flag: 'a', mode: 0o666, encoding: 'utf8' },
archiveLogFn(file) {
const oldPath = file.toString();
const inf = path.parse(oldPath);
try {
fs.renameSync(oldPath, path.join(inf.dir, `${inf.name}.old${inf.ext}`));
} catch (e) {
logConsole('Could not rotate log', e);
const quarterOfMaxSize = Math.round(transport.maxSize / 4);
file.crop(Math.min(quarterOfMaxSize, 256 * 1024));
}
},
resolvePathFn(vars) {
return path.join(vars.libraryDefaultDir, vars.fileName);
},
setAppName(name) {
logger.dependencies.externalApi.setAppName(name);
},
});
function transport(message) {
const file = getFile(message);
const needLogRotation = transport.maxSize > 0
&& file.size > transport.maxSize;
if (needLogRotation) {
transport.archiveLogFn(file);
file.reset();
}
const content = transform({ logger, message, transport });
file.writeLine(content);
}
function initializeOnFirstAccess() {
if (pathVariables) {
return;
}
// Make a shallow copy of pathVariables to keep getters intact
pathVariables = Object.create(
Object.prototype,
{
...Object.getOwnPropertyDescriptors(
externalApi.getPathVariables(),
),
fileName: {
get() {
return transport.fileName;
},
enumerable: true,
},
},
);
if (typeof transport.archiveLog === 'function') {
transport.archiveLogFn = transport.archiveLog;
logConsole('archiveLog is deprecated. Use archiveLogFn instead');
}
if (typeof transport.resolvePath === 'function') {
transport.resolvePathFn = transport.resolvePath;
logConsole('resolvePath is deprecated. Use resolvePathFn instead');
}
}
function logConsole(message, error = null, level = 'error') {
const data = [`electron-log.transports.file: ${message}`];
if (error) {
data.push(error);
}
logger.transports.console({ data, date: new Date(), level });
}
function getFile(msg) {
initializeOnFirstAccess();
const filePath = transport.resolvePathFn(pathVariables, msg);
return registry.provide({
filePath,
writeAsync: !transport.sync,
writeOptions: transport.writeOptions,
});
}
function readAllLogs({ fileFilter = (f) => f.endsWith('.log') } = {}) {
initializeOnFirstAccess();
const logsPath = path.dirname(transport.resolvePathFn(pathVariables));
if (!fs.existsSync(logsPath)) {
return [];
}
return fs.readdirSync(logsPath)
.map((fileName) => path.join(logsPath, fileName))
.filter(fileFilter)
.map((logPath) => {
try {
return {
path: logPath,
lines: fs.readFileSync(logPath, 'utf8').split(os.EOL),
};
} catch {
return null;
}
})
.filter(Boolean);
}
}
function getDefaultFileName(processType = process.type) {
switch (processType) {
case 'renderer': return 'renderer.log';
case 'worker': return 'worker.log';
default: return 'main.log';
}
}