Electronでクラッシュ検知してログを送信する

Electronで色々と社内向けのアプリケーションを作成していますが、つい最近1例だけ、同じアプリで同じ環境にも関わらず、「起動しない」「イベントビューアにID 1000のクラッシュ記録が残ってる」という事例が。起動しないので、エラー出力もなく、開発環境で再現できない為、何が悪さをしてるのか?全く不明という状況。

他のマシンでは一切起きていない現象であり、当然クラッシュ記録も無い為、デバッグのしようがない・・・という事で、このクラッシュを検知してログを自動出力する仕組みを取り入れる事にしました。その記録です。

今回使用するモジュール

今回試しにPower Automateのインスタントクラウドフローを用意して受け取ってみようと思います。electron-logはローカルにログを出力するので、これをPower Automateに送信して、OneDriveにファイルを保存し、Teamsに通知してみたいと思います。

モジュールのインストール

インストール

プロジェクトフォルダに移動してから、ターミナル(コマンドプロンプト)より以下のコマンドでインストールします。

ロードする

2つのモジュールをロードする記述をindex.jsの冒頭に追加します。

次項でそれぞれのモジュールの使い方を記述しています。

意図的にクラッシュさせる

開発テストの間でだけ使う「意図的にクラッシュさせる」コードは以下の通り。index.jsのポイント(例えば、mainWindowを呼び出した直後とか、app初期化時など)に配置して、クラッシュさせます。

以下は初期化が完了したあとにクラッシュさせるようにしています。

各モジュールの使い方

electron-logについて

エラーログの保存先

各OSによって、ログの出力先が異なります。今回はWindowsでテストしているので、Roaming以下のディレクトリにあるファイルを拾います。

  • Windows :C:\Users\AppData\Roaming\アプリの名前\logs\プロセスタイプ.log
  • macOS : ~/Library/Logs/アプリの名前/プロセスタイプ.log
  • Linux : ~/.config/アプリの名前/logs/プロセスタイプ.log

このエラーログのファイル名を予め指定しておいて、出力する事で後で調べるときにより便利になるので、以下のコードをクラッシュ検知の前に用意しておきます。以下のコードで、例:20220512.logというファイル名でファイルが出力されます。

log.transports.file.resolvePathで任意のフォルダに出力できます。またファイル名だけを変えたい場合には、log.transports.file.fileNameで変更可能。

クラッシュ検知をさせてログを出力する

例外を投げてエラーをわざと引き起こして、エラートラップさせます。エラーを取得したら、log.error(err)にて、electron-logにログ出力をさせます。

出力された内容は以下のように出力されて、同じファイル名のファイルが有った場合には、追記の形で書き込みがされます。

エラーログを送信

エラーログをメールで送ってしまう

electron-logはログを出力して仕事は終了です。しかし、開発者としてはそのログを速攻で送ってもらったほうがありがたいので、メールで送って欲しいのですがその為の仕組みとしては、WindowsならばElectronからVBS叩いて送ってしまったほうがどんな環境でも動作するので楽です。以下はVBSに引数でログファイルのパスを渡して、メールに添付して送りつけるという手法です。

VBSと連携するElectronアプリを作る

Outlookを使ってVBSにて送信する

Electronからは生成したログのフルパスを引数としてVBS側に渡すだけ。返り値が3ならば成功、1ならばエラーとして判定して処理をすれば良い。

Electron側でVBSを呼び出すコード

  • VBS側に引数でログファイルのフルパスを送りつけています
  • cscript.exeで実行するVBSファイルとフルパスを基に実行しています。実行が完了するまで待機します。

Power Automateに送りつける

生成されたログをOutlookで送るという手段は今風ではないのと、VBSでメールにて送信という手段故に、社内のメールフィルタに阻害される可能性もあるため、これをPower Automateに用意したフローで受け取り、Teams通知⇒OneDrive Businessに保存という手段を構築したいと思います。尚、ファイル名が同じ場合には上書きされるので、ファイル名の付け方には注意が必要です(特に複数名いる場合には、日付だけだと重複する可能性があるので日時秒まで入れてみるとか、ユーザ名を入れてみるとか)

Power Automate側

まずは、エラーログを受け取るフローを作成します。エラー内容のテキストはJSONで送られてくるので、それをパースして、ファイルにして保存するまでのフローです。

  1. Power Automateにてインスタントクラウドフローを作成する
  2. トリガーはHTTP要求の受信時を選択し、作成をクリック
  3. 詳細オプションを開き、MethodはPOSTを選択
  4. JSONスキーマは以下のようなものを入れておきます。

    errorがエラー内容、nameがファイル名としてElectronから送信します。
  5. 続けて、データ操作で検索して、作成コネクタを追加します
  6. 作成の入力は、2.のフローのerrorを選びます
  7. 次に、OneDrive Businessで検索して、ファイルの作成コネクタを選びます。
  8. フォルダのパスは保存先のフォルダを選んでおきます
  9. ファイル名は2.のフローのnameを選びます
  10. ファイルコンテンツは、5.のフローの出力を選びます
  11. 続けて、Teamsで検索し、「チャットまたはチャンネルでメッセージを投稿する」コネクタを選択します。
  12. 投稿者、投稿先、チーム、チャンネルを選択し、件名を入力します。
  13. メッセージ本文は自分は以下のようなものを利用しています。直接リンクからファイルを開ける用に、予め自分のドメインでのOneDriveのそのファイルへのリンクを基に、7.のパスを利用して構築しています。

    ドメインは自社ドメイン、ユーザ名は自分のメアド、そこにパスのコネクタをつなげて、最後にcsf=以下をつなげたものをURLとして、ハイパーリンクとしています。csf=以下が無いとダウンロードになります。
  14. 最後に、トリガーとなったHTTP要求の受信時コネクタに生成されたURLをコピーしておきます。これをElectron側で利用します。

図:プレミアムコネクタを利用します

図:Teamsに通知が飛んできた

図:OneDriveに自動生成されたファイル

図:後半のフロー全体図

Electron側

Electron側は、前項の「クラッシュ検知をさせてログを出力する」の項目にて、利用したトラップの関数内にnode-fetchを利用してPOSTでerror.logを添付して送るようにしています。

  • 生成されたファイルの内容をfs.readFileSyncにて読み取ります。
  • filenameは予め日付とユーザ名を組み合わせたものを用意しておきます。
  • node-fetchにてPOSTにて送信します。この時papointに前項で取得したHTTP要求の受信時のURLを入れておきます。
  • agentはProxy経由する場合に必要なものなので、不要であれば削除します。
  • リクエストが成功すると、Power Automate側からは、202コードが返ってきます。
  • 送信したら、その旨のダイアログを表示するようにしています。

関連リンク

共有してみる:

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください