[Electron] ログをファイルに記録する - electron-log

開発中はconsole.logで見れば良いのですが、ファイルにも情報を記録しておきたい場合にelectron-logを利用すると非常に簡単にログを記録することができます。

const log = require('electron-log');

log.info('Hello, log');
log.warn('Some problem appears');

以上です。めっちゃシンプルじゃないですかw?あとはOSによってログを保存するのによく利用されるディレクトリへ自動で保存されます。

今回はelectron-logのもう少し詳しい使い方を見ていきます。

準備

モジュールをnpmでインストールしてやります。

$ npm install electron-log

基本的な使い方

今回は最新版の4系の利用方法になります。旧版とは異なるようなのでご注意を。

コード

使い方は非常にシンプルです。最初にモジュールを読み込み、記録したい値をログレベルに合わせたメソッドに渡すだけです。

const log = require('electron-log');

log.info('Hello, log');

実際のログファイルには以下のように保存されます。以下のコマンドはmacOSの場合。

$ cat ~/Library/Logs/electron-sample-log/main.log
[2020-12-28 19:08:57.066] [info] Hello, log

メソッドには文字列の他、数値や真偽値、配列や連想配列なども利用可能ます。またconsole.log()のように複数の値を同時に渡すこともできます(スペース区切りで保存されます)。

ログレベル

ログレベルが6種類用意されており状況に応じて使い分けます。例えばエラーが発生した場合はlog.error()を、デバッグ情報ならlog.debug()といった具合です。

# レベル 備考
1 error エラー
2 warn 警告
3 info 情報
4 verbose 詳細な情報
5 debug デバッグ
6 silly その他

保存先

デフォルトではOS毎に定められているログを記録するのに適した場所に保存されます。

Platform パス
Windows %USERPROFILE%\AppData\Roaming{app name}\logs{process type}.log
macOS ~/Library/Logs/{app name}/{process type}.log
Linux ~/.config/{app name}/logs/{process type}.log

ファイル名はどこで実行されたかにより次の3種類に分かれます。

  • main.log
  • renderer.log
  • worker.log

Windows

PS C:\Users\katsube> type '.\AppData\Roaming\electron-sample-log\logs\main.log'
[2020-12-28 19:44:25.225] [info] Hello, log

macOS

$ cat ~/Library/Logs/electron-sample-log/main.log
[2020-12-28 19:08:57.066] [info] Hello, log

記録できる値

前述の文字列もですが、以下のようなオブジェクトもログに記録することが可能です。

log.info({status:true, code:200, message:'起動'});

ファイルの内容は以下の通り。

$ cat ~/Library/Logs/electron-sample-log/main.log
[2020-12-28 19:20:43.811] [info] { status: true, code: 200, message: '起動' }

応用的な使い方

ファイル名に年月日を入れる

log.transports.file.fileNameの値を書き換えればその通りファイル名で保存されます。

以下のようにしてやれば「YYYYMMDD」を先頭に付けることが可能です。

const log = require('electron-log')

(() => {
  const d = new Date();
  const prefix = d.getFullYear() +
                 ('00' + (d.getMonth() + 1)).slice(-2) +
                 ('00' + (d.getDate())).slice(-2);

  const curr = log.transports.file.fileName;
  log.transports.file.fileName = `${prefix}_${curr}`;
})();

log.info('Change filename');

ご覧の通りです。

$ cat ~/Library/Logs/electron-sample-log/20201228_main.log
[2020-12-28 19:56:52.401] [info] Change filename

プロセスIDを記録する

Node.jsの機能ですが、process.pidを参照すればプロセスIDが入っていますので、これを同時に記録しておくと調査がしやすくなります。

const log = require('electron-log')

log.error(process.pid, 'Not found file');

以下のように出力されます。

$ cat ~/Library/Logs/electron-sample-log/20201228_main.log
[2020-12-28 20:18:44.531] [error] 27452 Not found file

例外が発生したら自動で記録する

どこにもcatchされずにprocessまでやってきてしまった例外(エラー)を補足した際に、ログファイルにも記録してやります。

const log = require('electron-log')

process.on('uncaughtException', (err) => {
  log.error(err); // ログファイルへ記録
  app.quit();     // アプリを終了する (継続しない方が良い)
});

// わざと例外を起こす (throw new Error()などでもOK)
const fs = require('fs')
const buff = fs.readFileSync('foobar.txt')  // 存在しないファイルを読み込もうとする

期待通り例外の内容を記録できました。

$ cat ~/Library/Logs/electron-sample-log/main.log
[2020-12-28 20:08:42.324] [error] Error: ENOENT: no such file or directory, open 'foobar.txt'
    at Object.openSync (fs.js:466:3)
    at Object.func [as openSync] (electron/js2c/asar_bundle.js:5:1812)
    at Object.readFileSync (fs.js:368:35)
    at Object.e.readFileSync (electron/js2c/asar_bundle.js:5:8583)
    at Object.<anonymous> (/Users/katsube/Library/Mobile Documents/com~apple~CloudDocs/Develop/electron-sample-log/index.js:26:11)
    at Module._compile (internal/modules/cjs/loader.js:1152:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1173:10)
    at Module.load (internal/modules/cjs/loader.js:992:32)
    at Module._load (internal/modules/cjs/loader.js:885:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12738)

参考ページ