mirror of
https://github.com/rancher/os.git
synced 2025-06-28 15:56:58 +00:00
259 lines
6.5 KiB
Go
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
|
|
}
|