package logging import ( native `log` `os` `path` sysd `github.com/coreos/go-systemd/journal` `r00t2.io/goutils/bitmask` `r00t2.io/sysutils/paths` ) var ( _ = sysd.Enabled() _ = native.Logger{} _ = os.Interrupt ) /* GetLogger returns an instance of Logger that best suits your system's capabilities. If enableDebug is true, debug messages (which according to your program may or may not contain sensitive data) are rendered and written. If prefix is "\x00" (a null byte), then the default logging prefix will be used. If anything else, even an empty string, is specified then that will be used instead for the prefix. logConfigFlags is the corresponding flag(s) OR'd for StdLogger.LogFlags / FileLogger.StdLogger.LogFlags if either is selected. See StdLogger.LogFlags and https://pkg.go.dev/log#pkg-constants for details. logPaths is an (optional) list of strings to use as paths to test for writing. If the file can be created/written to, it will be used (assuming you have no higher-level loggers available). Only the first logPaths entry that "works" will be used, later entries will be ignored. If you want to log to multiple files simultaneously, use a MultiLogger instead. If you call GetLogger, you will only get a single ("best") logger your system supports. If you want to log to multiple Logger destinations at once (or want to log to an explicit Logger type), use GetMultiLogger. */ func GetLogger(enableDebug bool, prefix string, logConfigFlags int, logPaths ...string) (logger Logger, err error) { var logPath string var logFlags bitmask.MaskBit var currentPrefix string // Configure system-supported logger(s). if sysd.Enabled() { // Use Journald. logFlags.AddFlag(LogJournald) } else { // If we can detect syslog, use that. If not, try to use a file logger (+ stdout). // Last ditch, stdout. var hasSyslog bool var stat os.FileInfo var devlogPath string = devlog if hasSyslog, stat, err = paths.RealPathExistsStat(&devlogPath); hasSyslog && err != nil { return } if hasSyslog && !stat.Mode().IsRegular() { logFlags.AddFlag(LogSyslog) } else { var exists bool var success bool var ckLogPaths []string logFlags.AddFlag(LogStdout) ckLogPaths = defLogPaths if logPaths != nil { ckLogPaths = logPaths } for _, p := range ckLogPaths { if exists, _ = paths.RealPathExists(&p); exists { if success, err = testOpen(p); err != nil { continue } else if !success { continue } logFlags.AddFlag(LogFile) logPath = p break } else { dirPath := path.Dir(p) if err = paths.MakeDirIfNotExist(dirPath); err != nil { continue } if success, err = testOpen(p); err != nil { continue } else if !success { continue } logFlags.AddFlag(LogFile) logPath = p break } } } } if logFlags.HasFlag(LogJournald) { logger = &SystemDLogger{ Prefix: logPrefix, EnableDebug: enableDebug, } } else { if logFlags.HasFlag(LogSyslog) { logger = &SyslogLogger{ Prefix: logPrefix, EnableDebug: enableDebug, } } else { if logFlags.HasFlag(LogFile) { logger = &FileLogger{ StdLogger: StdLogger{ Prefix: logPrefix, EnableDebug: enableDebug, LogFlags: logConfigFlags, }, Path: logPath, } } else { logger = &StdLogger{ Prefix: logPrefix, EnableDebug: enableDebug, LogFlags: logConfigFlags, } } } } if prefix != "\x00" { if err = logger.SetPrefix(prefix); err != nil { return } } if err = logger.Setup(); err != nil { return } if currentPrefix, err = logger.GetPrefix(); err != nil { return } logger.Debug("logger initialized of type %T with prefix %v", logger, currentPrefix) return }