22

定期的にローテーションされるログ ファイルに出力を書き込むために、ロガー (実際にはカスタム ロガー) を使用する大規模な golang アプリケーションがあります。

ただし、アプリケーションがクラッシュしたり、panic() が発生すると、これらのメッセージは標準エラーに送られます。

ロガーを使用するためにパニック機能をオーバーライドする方法はありますか?

4

3 に答える 3

20

私の知る限り、パニックからの出力を標準エラーから、またはロガーにリダイレクトすることはできません。あなたができる最善のことは、標準エラーを外部またはプログラム内で実行できるファイルにリダイレクトすることです。

私のrcloneプログラムでは、標準エラーをリダイレクトして、オプションのすべてをファイルにキャプチャしましたが、残念ながら、クロスプラットフォームの方法では特に簡単ではありません。これが私が行った方法です(redirect*.goファイルを参照してください)

Linux/Unix の場合

// Log the panic under unix to the log file

//+build unix

package main

import (
    "log"
    "os"
    "syscall"
)

// redirectStderr to the file passed in
func redirectStderr(f *os.File) {
    err := syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd()))
    if err != nil {
        log.Fatalf("Failed to redirect stderr to file: %v", err)
    }
}

そして窓用

// Log the panic under windows to the log file
//
// Code from minix, via
//
// http://play.golang.org/p/kLtct7lSUg

//+build windows

package main

import (
    "log"
    "os"
    "syscall"
)

var (
    kernel32         = syscall.MustLoadDLL("kernel32.dll")
    procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
)

func setStdHandle(stdhandle int32, handle syscall.Handle) error {
    r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
    if r0 == 0 {
        if e1 != 0 {
            return error(e1)
        }
        return syscall.EINVAL
    }
    return nil
}

// redirectStderr to the file passed in
func redirectStderr(f *os.File) {
    err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
    if err != nil {
        log.Fatalf("Failed to redirect stderr to file: %v", err)
    }
    // SetStdHandle does not affect prior references to stderr
    os.Stderr = f
}
于 2016-01-13T18:06:39.743 に答える