electron-log review
A desktop bug is harder to investigate when the only clue was in a DevTools window the user has closed. electron-log gives Electron applications local file logging alongside console output, with a main-process logger and a renderer entry point that forwards messages over IPC. This guide targets electron-log 5.4.4. By default, electron-log writes to both the console and a file. Use it when you need a support log on the user's machine and can take responsibility for what that file contains.
Choose electron-log when your Electron app needs a local support file and you can configure the process bridge, output level and retention policy. Before adopting the setup, inspect a sample log from your packaged app for both useful context and private data.
Answers from our run
electron-log or debug: which should you use?
debug: Consider debug for debugging output in Node.js and the browser. It is worth evaluating when your requirement is debugging messages rather than the local Electron support-file workflow described here. Choose electron-log when your Electron app needs a local support file and you can configure the process bridge, output level and retention policy.
When should you not use electron-log?
You only need console messages in a browser or small script. The Electron process bridge and file workflow add responsibilities you don't need.
Use it if
- You maintain an Electron app and need messages from the main process and renderer available for a support investigation.
- A local log file is the desired output, and you want to configure its path and severity threshold in application code.
- Component labels would help you distinguish updater messages from other application activity.
- You can review sample logs for private data and decide how users will find and share them.
- You only need console messages in a browser or small script. The Electron process bridge and file workflow add responsibilities you don't need.
- You require a dated archive history out of the box. The default archiver renames the current file to a fixed .old filename, so design retention separately.
- Your app emits large volumes of logs and you cannot accept synchronous file writes without evaluating their effect. This guide contains no throughput or responsiveness measurement.
- You expect a severity filter to remove credentials or private content. Choosing warn instead of debug does not inspect the message for secrets.
- Your runtime is older than the documented v5 minimum of Electron 13 or Node.js 14. Those minimums are compatibility requirements, not a recommendation to deploy an unsupported runtime.
Setup reality
Install the version used here with npm install --save-exact electron-log@5.4.4. The pinned README documents Electron 13+ or Node.js 14+ for v5; choose a currently supported runtime for your application. We inspected npm metadata, the release page and version-pinned documentation and file-transport source. No application was installed or launched, and the recipes below were not executed. There is no desktop, packaging, performance or concurrency result here.
Start in the main process with electron-log/main and call log.initialize() for renderer logging. With a renderer bundler, use electron-log/renderer. The preload entry point is a bridge and does not export a logger. Configure file paths and transport thresholds in the main process. The renderer example below is the companion to the first recipe; the remaining main-process configurations are separate illustrations you can combine deliberately in your logger setup. Keep the package available at runtime in the packaged application, then verify a renderer message reaches the intended file in that packaged build. A development-console message alone doesn't verify that path.
For an Electron app, the README lists main.log under the app's logs directory: ~/.config/{app name}/logs on Linux, ~/Library/Logs/{app name} on macOS, and %USERPROFILE%\AppData\Roaming{app name}\logs on Windows. These are documented defaults, not paths observed on three test machines. Set a different filename or path before the first file access if support needs a predictable location. electron-builder addresses packaging and release work; logging configuration still needs its own packaged-app check.
The file transport defaults to synchronous writes and a 1 MiB rotation threshold. The implementation checks the file's current size before appending the next message. A write can therefore take it past the threshold, with rotation considered on a later call. Its default archiver uses the same basename with .old before the extension, such as main.old.log. If renaming fails, it tries to crop the existing file. This is a small local archive mechanism, not a retention schedule or a strict disk-usage limit. Decide whether losing earlier diagnostic context is acceptable before raising log volume.
The documented console and file thresholds both default to silly, which includes the most verbose named level. Set thresholds intentionally, and keep passwords, tokens and raw user content out of the arguments you pass. Remote transport is documented as disabled by default; leave it disabled unless you have separately designed and reviewed collection. Before asking someone to attach a log, inspect a representative file and explain what they are sending. The ratings below are source-based editorial judgments on a five-point rubric: 1 means little inspectable support, 3 means a concrete usable contract with gaps, and 5 requires broader evidence than a source reading alone.
Patterns
Initialize logging in the main process initialize-main-logger
import log from 'electron-log/main';
log.initialize();
log.info('Application starting');Unexecuted documentation-based illustration for 5.4.4, as are all recipes below. Put this in the Electron main entry point as part of application startup. initialize() is the documented setup for making the logger available to the renderer; launching the main process alone does not verify renderer forwarding.
Send a renderer message through the bridge log-from-renderer
import log from 'electron-log/renderer';
log.info('Settings screen opened');This is renderer code for a project with a bundler and the main-process initialization from the first recipe. The documented renderer IPC path forwards messages to the main process for console and file output. Avoid importing electron-log/main into renderer code, and do not weaken your Electron security settings just to make logging work.
Use the explicit Node entry point log-from-node
import log from 'electron-log/node';
log.info('Support script started');A separate Node.js illustration, not an Electron main entry point. The pinned README documents electron-log/node for Node.js and NW.js. Save this as an .mjs file in a project with the package installed. The Electron paths listed above do not establish this script's actual output path.
Keep routine events in the file filter-transport-levels
import log from 'electron-log/main';
log.transports.file.level = 'info';
log.transports.console.level = 'warn';
log.info('Updater check started');
log.warn('Updater response delayed');Each transport has its own level setting. The info file threshold keeps info and more severe messages; the warn console threshold excludes the info call. This filters severity, not sensitive data. Configure before the calls you want to affect.
Turn off the console transport disable-console-output
import log from 'electron-log/main';
log.transports.console.level = false;
log.info('Background check completed');Use the boolean false, not the string 'false'. This disables the named transport only. The default file transport remains enabled, so the message can still be stored locally and must still avoid private content.
Label updater messages with a scope label-component-messages
import log from 'electron-log/main';
const updaterLog = log.scope('updater');
updaterLog.info('Checking for updates');
updaterLog.warn('Update check postponed');The scope labels messages through the existing logger. It is not a separate file destination. Use a fixed component label rather than a user identifier; configure transports on the main logger.
Choose a filename in the default log directory choose-support-filename
import path from 'node:path';
import log from 'electron-log/main';
log.transports.file.resolvePathFn = (vars) =>
path.join(vars.libraryDefaultDir, 'support.log');
log.info('Support logging started');The pinned file implementation supplies libraryDefaultDir to resolvePathFn. Keeping that directory changes the filename without assuming a writable installation directory. Set this before your first log call or getFile() access. The output remains a local file, with the same rotation policy unless you change it.
Change the size threshold for rotation set-rotation-threshold
import log from 'electron-log/main';
log.transports.file.maxSize = 2 * 1024 * 1024;
log.info('File rotation threshold configured');This chooses a 2 MiB threshold instead of the implementation's 1 MiB default. Rotation checks whether the current size is greater than maxSize before the next write; it is not a strict upper bound. The default archive name is reused rather than timestamped. No retention history or concurrent-writer guarantee follows from this setting.
Simplify the console format format-console-messages
import log from 'electron-log/main';
log.transports.console.format = '{h}:{i}:{s} {text}';
log.info('Update check finished');This is the console format syntax shown in the pinned README. It changes presentation on that transport, not the file format or the logged arguments. A shorter format does not remove secrets from message text.
Give another logger its own file separate-support-logger
import path from 'node:path';
import log from 'electron-log/main';
const supportLog = log.create({ logId: 'support' });
supportLog.transports.file.resolvePathFn = (vars) =>
path.join(vars.libraryDefaultDir, 'support.log');
supportLog.transports.file.level = 'warn';
supportLog.warn('Update installation postponed');The README documents create({ logId }) and warns that each instance needs its own settings, including its file path. This main-process-only recipe chooses a distinct destination deliberately. Do not combine it with the earlier support.log recipe if you intend separate files. A different logId alone is not a promise of a different file.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| debug | npm | Consider debug for debugging output in Node.js and the browser. It is worth evaluating when your requirement is debugging messages rather than the local Electron support-file workflow described here. |
| loglevel | npm | Consider loglevel when you want level methods around the available console.log output. That is a narrower requirement than configuring a main-process file and renderer forwarding. |
More utils guides
lru-cache · type-fest · ajv · zod · p-limit · find-up · the whole shelf →
How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.