embed: support multiple log outputs for structured logging

Zap support multi-writer by default.

Signed-off-by: Gyuho Lee <gyuhox@gmail.com>
This commit is contained in:
Gyuho Lee
2018-04-17 11:27:08 -07:00
parent 406f23ce17
commit f6f1e0cb65

View File

@ -23,6 +23,7 @@ import (
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
"sort"
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
@ -394,7 +395,17 @@ func (cfg *Config) setupLogging() error {
} }
case "zap": case "zap":
// TODO: make this more configurable if cfg.LogOutput == "" {
cfg.LogOutput = DefaultLogOutput
}
outputs := strings.Split(cfg.LogOutput, ",")
for _, v := range outputs {
if v == DefaultLogOutput {
panic(fmt.Errorf("multi logoutput for %q is not supported yet", DefaultLogOutput))
}
}
// TODO: use zapcore to support more features?
lcfg := zap.Config{ lcfg := zap.Config{
Level: zap.NewAtomicLevelAt(zap.InfoLevel), Level: zap.NewAtomicLevelAt(zap.InfoLevel),
Development: false, Development: false,
@ -404,35 +415,50 @@ func (cfg *Config) setupLogging() error {
}, },
Encoding: "json", Encoding: "json",
EncoderConfig: zap.NewProductionEncoderConfig(), EncoderConfig: zap.NewProductionEncoderConfig(),
OutputPaths: make([]string, 0),
ErrorOutputPaths: make([]string, 0),
} }
switch cfg.LogOutput { outputPaths, errOutputPaths := make(map[string]struct{}), make(map[string]struct{})
case DefaultLogOutput: for _, v := range outputs {
if syscall.Getppid() == 1 { switch v {
// capnslog initially SetFormatter(NewDefaultFormatter(os.Stderr)) case DefaultLogOutput:
// where "NewDefaultFormatter" returns "NewJournaldFormatter" if syscall.Getppid() == 1 {
// when syscall.Getppid() == 1, specify 'stdout' or 'stderr' to // capnslog initially SetFormatter(NewDefaultFormatter(os.Stderr))
// skip journald logging even when running under systemd // where "NewDefaultFormatter" returns "NewJournaldFormatter"
fmt.Println("running under init, which may be systemd!") // when syscall.Getppid() == 1, specify 'stdout' or 'stderr' to
// TODO: capnlog.NewJournaldFormatter() // skip journald logging even when running under systemd
lcfg.OutputPaths = []string{"stderr"} // TODO: capnlog.NewJournaldFormatter()
lcfg.ErrorOutputPaths = []string{"stderr"} fmt.Println("running under init, which may be systemd!")
} else { outputPaths["stderr"] = struct{}{}
lcfg.OutputPaths = []string{"stderr"} errOutputPaths["stderr"] = struct{}{}
lcfg.ErrorOutputPaths = []string{"stderr"} continue
}
outputPaths["stderr"] = struct{}{}
errOutputPaths["stderr"] = struct{}{}
case "stderr":
outputPaths["stderr"] = struct{}{}
errOutputPaths["stderr"] = struct{}{}
case "stdout":
outputPaths["stdout"] = struct{}{}
errOutputPaths["stdout"] = struct{}{}
default:
outputPaths[v] = struct{}{}
errOutputPaths[v] = struct{}{}
} }
case "stderr":
lcfg.OutputPaths = []string{"stderr"}
lcfg.ErrorOutputPaths = []string{"stderr"}
case "stdout":
lcfg.OutputPaths = []string{"stdout"}
lcfg.ErrorOutputPaths = []string{"stdout"}
default:
lcfg.OutputPaths = []string{cfg.LogOutput}
lcfg.ErrorOutputPaths = []string{cfg.LogOutput}
} }
for v := range outputPaths {
lcfg.OutputPaths = append(lcfg.OutputPaths, v)
}
for v := range errOutputPaths {
lcfg.ErrorOutputPaths = append(lcfg.ErrorOutputPaths, v)
}
sort.Strings(lcfg.OutputPaths)
sort.Strings(lcfg.ErrorOutputPaths)
if cfg.Debug { if cfg.Debug {
lcfg.Level = zap.NewAtomicLevelAt(zap.DebugLevel) lcfg.Level = zap.NewAtomicLevelAt(zap.DebugLevel)