package logging import ( native `log` `os` `path` "r00t2.io/goutils/types" sysd `github.com/coreos/go-systemd/journal` `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. // 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. func GetLogger(enableDebug bool, prefix string, logpaths ...string) (logger Logger, err error) { var logPath string var logflags types.MaskBit // 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, }, Path: logPath, } } else { logger = &StdLogger{ Prefix: logPrefix, EnableDebug: enableDebug, } } } } logger.Setup() if prefix != "\x00" { logger.setPrefix(prefix) } logger.Info("logger initialized of type %T with prefix %v", logger, logger.Prefix) return } func testOpen(path string) (success bool, err error) { var f *os.File // Example #2, https://golang.org/pkg/os/#OpenFile if f, err = os.OpenFile(path, appendFlags, logPerm); err != nil { return } defer f.Close() success = true return }