1
0
mirror of https://github.com/rancher/os.git synced 2025-06-28 15:56:58 +00:00
os/log/log.go
2018-04-16 11:30:08 +08:00

259 lines
6.5 KiB
Go

package log
import (
"fmt"
"io"
"log/syslog"
"os"
"path/filepath"
"strings"
"github.com/Sirupsen/logrus"
lsyslog "github.com/Sirupsen/logrus/hooks/syslog"
"github.com/rancher/os/config/cmdline"
)
var logFile *os.File
var userHook *ShowuserlogHook
var defaultLogLevel logrus.Level
var debugThisLogger = false
type Fields logrus.Fields
type Level logrus.Level
type Logger logrus.Logger
const (
// PanicLevel level, highest level of severity. Logs and then calls panic with the
// message passed to Debug, Info, ...
PanicLevel Level = iota
// FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
// logging level is set to Panic.
FatalLevel
// ErrorLevel level. Logs. Used for errors that should definitely be noted.
// Commonly used for hooks to send errors to an error tracking service.
ErrorLevel
// WarnLevel level. Non-critical entries that deserve eyes.
WarnLevel
// InfoLevel level. General operational entries about what's going on inside the
// application.
InfoLevel
// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
DebugLevel
)
func SetOutput(out io.Writer) {
logrus.SetOutput(out)
}
func SetDefaultLevel(level Level) {
defaultLogLevel = logrus.Level(level)
}
func SetLevel(level Level) {
if userHook != nil {
userHook.Level = logrus.Level(level)
} else {
logrus.SetLevel(logrus.Level(level))
}
}
func GetLevel() Level {
if userHook != nil {
return Level(userHook.Level)
}
return Level(logrus.GetLevel())
}
func Debugf(format string, args ...interface{}) {
logrus.Debugf(format, args...)
}
func Infof(format string, args ...interface{}) {
logrus.Infof(format, args...)
}
func Printf(format string, args ...interface{}) {
logrus.Printf(format, args...)
}
func Warnf(format string, args ...interface{}) {
logrus.Warnf(format, args...)
}
func Warningf(format string, args ...interface{}) {
logrus.Warningf(format, args...)
}
func Errorf(format string, args ...interface{}) {
logrus.Errorf(format, args...)
}
func Fatalf(format string, args ...interface{}) {
logrus.Fatalf(format, args...)
}
func Panicf(format string, args ...interface{}) {
logrus.Panicf(format, args...)
}
func Debug(args ...interface{}) {
logrus.Debug(args...)
}
func Info(args ...interface{}) {
logrus.Info(args...)
}
func Print(args ...interface{}) {
logrus.Print(args...)
}
func Warn(args ...interface{}) {
logrus.Warn(args...)
}
func Warning(args ...interface{}) {
logrus.Warning(args...)
}
func Error(args ...interface{}) {
logrus.Error(args...)
}
func Fatal(args ...interface{}) {
logrus.Fatal(args...)
}
func Panic(args ...interface{}) {
logrus.Panic(args...)
}
func WithField(key string, value interface{}) *logrus.Entry {
return logrus.WithField(key, value)
}
func WithFields(fields Fields) *logrus.Entry {
return logrus.WithFields(logrus.Fields(fields))
}
// InitLogger sets up Logging to log to /dev/kmsg and to Syslog
func InitLogger() {
if logTheseApps() {
innerInit(false)
FsReady()
AddRSyslogHook()
pwd, err := os.Getwd()
if err != nil {
logrus.Error(err)
}
logrus.Debugf("START: %v in %s", os.Args, pwd)
}
}
func logTheseApps() bool {
// TODO: mmm, not very functional.
if filepath.Base(os.Args[0]) == "ros" ||
// filepath.Base(os.Args[0]) == "system-docker" ||
filepath.Base(os.Args[0]) == "host_ros" {
return false
}
return true
}
// InitDeferedLogger stores the log messages until FsReady() is called
// TODO: actually store them :)
// TODO: need to work out how to pass entries from a binary run before we switchfs back to init and have it store and write it later
func InitDeferedLogger() {
if logTheseApps() {
innerInit(true)
//logrus.SetOutput(ioutil.Discard)
// write to dmesg until we can write to file. (maybe we can do this if rancher.debug=true?)
f, err := os.OpenFile("/dev/kmsg", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
if err == nil {
logFile = f
logrus.SetOutput(logFile)
}
pwd, err := os.Getwd()
if err != nil {
logrus.Error(err)
}
logrus.Debugf("START: %v in %s", os.Args, pwd)
}
}
func innerInit(deferedHook bool) {
if userHook != nil {
return // we've already initialised it
}
// All logs go through the Hooks, and they choose what to do with them.
logrus.StandardLogger().Level = logrus.DebugLevel
if logTheseApps() {
AddUserHook(deferedHook)
}
}
// AddRSyslogHook only needs to be called separately when using the InitDeferedLogger
// init.Main can't read /proc/cmdline at start.
// and then fails due to the network not being up
// TODO: create a "defered SyslogHook that always gets initialised, but if it fails to connect, stores the logs
// and retries connecting every time its triggered....
func AddRSyslogHook() {
val := cmdline.GetCmdline("netconsole")
netconsole := val.(string)
if netconsole != "" {
// "loglevel=8 netconsole=9999@10.0.2.14/,514@192.168.33.148/"
// 192.168.33.148:514
n := strings.Split(netconsole, ",")
if len(n) == 2 {
d := strings.Split(n[1], "@")
if len(d) == 2 {
netconsoleDestination := fmt.Sprintf("%s:%s", strings.TrimRight(d[1], "/"), d[0])
hook, err := lsyslog.NewSyslogHook("udp", netconsoleDestination, syslog.LOG_DEBUG, "")
if err == nil {
logrus.StandardLogger().Hooks.Add(hook)
Infof("Sending RancherOS Logs to: %s", netconsoleDestination)
} else {
Errorf("Error creating SyslogHook: %s", err)
}
}
}
}
}
func FsReady() {
filename := "/var/log/boot/" + filepath.Base(os.Args[0]) + ".log"
if err := os.MkdirAll(filepath.Dir(filename), os.ModeDir|0755); debugThisLogger && err != nil {
logrus.Errorf("FsReady mkdir(%s): %s", filename, err)
}
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
if err != nil {
if debugThisLogger {
logrus.Errorf("FsReady opening %s: %s", filename, err)
}
} else {
if debugThisLogger {
logrus.Infof("Setting log output for %s to: %s", os.Args[0], filename)
}
logFile = f
logrus.SetOutput(logFile)
}
}
// AddUserHook is used to filter what log messages are written to the screen
func AddUserHook(deferedHook bool) error {
if userHook != nil {
return nil
}
printLogLevel := logrus.InfoLevel
uh, err := NewShowuserlogHook(printLogLevel, filepath.Base(os.Args[0]))
if err != nil {
logrus.Errorf("error creating userHook(%s): %s", os.Args[0], err)
return err
}
userHook = uh
logrus.StandardLogger().Hooks.Add(uh)
if debugThisLogger {
if deferedHook {
logrus.Debugf("------------info Starting defered User Hook (%s)", os.Args[0])
} else {
logrus.Debugf("------------info Starting User Hook (%s)", os.Args[0])
}
}
return nil
}