-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor configuring logging into a reusable component so that it can be nicely used in both main() and init process init() Co-authored-by: Georgi Sabev <[email protected]> Co-authored-by: Giuseppe Capizzi <[email protected]> Co-authored-by: Claudia Beresford <[email protected]>
- Loading branch information
1 parent
e4ca720
commit 1fdc31f
Showing
11 changed files
with
381 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
package logs | ||
|
||
import ( | ||
"bufio" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"os" | ||
"strconv" | ||
|
||
"github.com/sirupsen/logrus" | ||
) | ||
|
||
// loggingConfigured will be set once logging has been configured via invoking `ConfigureLogging`. | ||
// Subsequent invocations of `ConfigureLogging` would be no-op | ||
var loggingConfigured = false | ||
|
||
type LoggingConfiguration struct { | ||
IsDebug bool | ||
LogFormat string | ||
LogFilePath string | ||
LogPipeFd string | ||
} | ||
|
||
func ForwardLogs(logPipe io.Reader) { | ||
type jsonLog struct { | ||
Level string `json:"level"` | ||
Msg string `json:"msg"` | ||
} | ||
|
||
lineReader := bufio.NewReader(logPipe) | ||
for { | ||
line, err := lineReader.ReadBytes('\n') | ||
if len(line) > 0 { | ||
processEntry(line) | ||
} | ||
if err == io.EOF { | ||
logrus.Debugf("log pipe has been closed: %+v", err) | ||
return | ||
} | ||
if err != nil { | ||
logrus.Errorf("log pipe read error: %+v", err) | ||
} | ||
} | ||
} | ||
|
||
func processEntry(text []byte) { | ||
type jsonLog struct { | ||
Level string `json:"level"` | ||
Msg string `json:"msg"` | ||
} | ||
|
||
var jl jsonLog | ||
if err := json.Unmarshal(text, &jl); err != nil { | ||
logrus.Errorf("failed to decode %q to json: %+v", text, err) | ||
return | ||
} | ||
|
||
lvl, err := logrus.ParseLevel(jl.Level) | ||
if err != nil { | ||
logrus.Errorf("failed to parse log level %q: %v\n", jl.Level, err) | ||
return | ||
} | ||
log(lvl, jl.Msg) | ||
} | ||
|
||
func log(level logrus.Level, args ...interface{}) { | ||
switch level { | ||
case logrus.PanicLevel: | ||
logrus.Panic(args...) | ||
case logrus.FatalLevel: | ||
logrus.Fatal(args...) | ||
case logrus.ErrorLevel: | ||
logrus.Error(args...) | ||
case logrus.WarnLevel: | ||
logrus.Warn(args...) | ||
case logrus.InfoLevel: | ||
logrus.Info(args...) | ||
case logrus.DebugLevel: | ||
logrus.Debug(args...) | ||
default: | ||
logrus.Warnf("Unsupported log level %v while trying to log '%#v'", level, args) | ||
} | ||
} | ||
|
||
func ConfigureLogging(loggingConfig *LoggingConfiguration) error { | ||
if loggingConfigured { | ||
logrus.Debug("logging has been already configured") | ||
return nil | ||
} | ||
|
||
configureLogLevel(loggingConfig) | ||
if err := configureLogOutput(loggingConfig); err != nil { | ||
return err | ||
} | ||
if err := configureLogFormat(loggingConfig); err != nil { | ||
return err | ||
} | ||
|
||
loggingConfigured = true | ||
return nil | ||
} | ||
|
||
func configureLogLevel(loggingConfig *LoggingConfiguration) { | ||
if loggingConfig.IsDebug { | ||
logrus.SetLevel(logrus.DebugLevel) | ||
} | ||
} | ||
|
||
func configureLogOutput(loggingConfig *LoggingConfiguration) error { | ||
if loggingConfig.LogFilePath != "" { | ||
return configureLogFileOutput(loggingConfig.LogFilePath) | ||
} | ||
|
||
if loggingConfig.LogPipeFd != "" { | ||
logPipeFdInt, err := strconv.Atoi(loggingConfig.LogPipeFd) | ||
if err != nil { | ||
return fmt.Errorf("failed to convert _LIBCONTAINER_LOGPIPE environment variable value %q to int: %v", loggingConfig.LogPipeFd, err) | ||
} | ||
configureLogPipeOutput(logPipeFdInt) | ||
return nil | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func configureLogPipeOutput(logPipeFd int) { | ||
logrus.SetOutput(os.NewFile(uintptr(logPipeFd), "logpipe")) | ||
} | ||
|
||
func configureLogFileOutput(logFilePath string) error { | ||
f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0644) | ||
if err != nil { | ||
return err | ||
} | ||
logrus.SetOutput(f) | ||
return nil | ||
} | ||
|
||
func configureLogFormat(loggingConfig *LoggingConfiguration) error { | ||
switch loggingConfig.LogFormat { | ||
case "text": | ||
// retain logrus's default. | ||
case "json": | ||
logrus.SetFormatter(new(logrus.JSONFormatter)) | ||
default: | ||
return fmt.Errorf("unknown log-format %q", loggingConfig.LogFormat) | ||
} | ||
return nil | ||
} |
Oops, something went wrong.