2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScript(Node.js)で標準出力をファイルにリダイレクトしている際、プログラム終了時にバッファに溜まったデータが出力されない問題を解決した話

Last updated at Posted at 2024-12-17

BayServerの実装時にハマった問題があったので備忘録。

以前から、TypeScript版BayServerに、「エラーが発生してプログラムが終了した場合に、原因となるエラーがログに吐き出されない」という問題があって、どうやったら直せるかずっと悩んでおりました。

これ、直さないと、ユーザーさんはエラーの報告できないですからね笑

で、直したので、BayServer 3.0 for TypeScrpt からは大丈夫ですよという話。

ちなみに、BayServerは、横浜ベイキット(https://baykit.yokohama/) で開発している、爆速WebServerです。RubyやらPHPやらいろんな言語で実装されています。

以下、コードは端折っています。

BayServerでは、設計ファイルでredirectFileを指定すると、ログは標準出力ではなくファイルに出力されます。内部的に何をやっているか説明します。

標準出力や標準エラーをリダイレクトする方法として、とりあえずcolsole.logとconsole.errorを書き換えます。オリジナルは別変数に保存しておきます。

   this.originalConsoleLog = console.log
   this.originalConsoleError = console.error

   this.logConsole = fs.createWriteStream(redirectFile)
   this.logConsole.on('open', () => {
        console.log = (...args: any[]) => {
            let message = args.join(' ');
            this.logConsole.write(message + '\n')
        };
        console.error = console.log
    })

redirectFileをオープンして、console.log関数を、オープンしたファイルに出力するように書き換えます。

console.errorはconsole.logと同じ動きになるように書き換えます。

後で戻せるように、元々のconsole.log, console.errorの実装は別の変数に保存しておきます。

さて、これでconsole.logやconsole.errorを呼んだ時のデータはファイルにリダイレクトされるわけですが、実はメソッドを呼んだ時点ではファイルに書き込まれず、バッファに溜まるだけなんですね。で、いつ書かれるかというと、Node.jsのイベントループで順番が回ってきた時に書かれます。

この挙動は通常あまり問題にならないですが、プログラム終了時に問題を起こします。

どんな問題かというと、プログラム終了直前に書こうとしたデータはバッファに残ったまま、ファイルに吐き出されずプログラムが終了してしまうんですね。

では、プログラム終了時に、次のようにendを呼べば良いと思うかも知れないが、残念ながらそれもダメ。

    this.logConsole.end()

chatGPT先生に聞いてみたが、何度もうまくいかず、何億回とやり取りして、結局、プログラム終了時に以下の2点を行うとうまくいきました。

  • console.log, console.error を元の実装に戻す
  • endメソッドを呼び、finishedイベントの発生をプロミス化して待つ

何故これでうまくいくのかは全然分かんないですが笑

    console.log = this.originalConsoleLog
    console.error = this.originalConsoleError

    this.logConsole.end()

    const finishedAsync = promisify(finished)
    finishedAsync(this.logConsole).then( () => {
    });

というわけで、BayServerをよろしくお願いします!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?