2021-02-26 15:52:29 -05:00
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
)
2021-02-26 20:27:35 -05:00
// 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 ) {
2021-02-26 15:52:29 -05:00
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
2021-02-26 20:27:35 -05:00
var ckLogPaths [ ] string
2021-02-26 15:52:29 -05:00
logflags . AddFlag ( LogStdout )
2021-02-26 20:27:35 -05:00
ckLogPaths = defLogPaths
if logpaths != nil {
ckLogPaths = logpaths
}
for _ , p := range ckLogPaths {
2021-02-26 15:52:29 -05:00
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 ,
2021-02-26 20:27:35 -05:00
EnableDebug : enableDebug ,
2021-02-26 15:52:29 -05:00
}
} else {
if logflags . HasFlag ( LogSyslog ) {
logger = & SyslogLogger {
Prefix : logPrefix ,
2021-02-26 20:27:35 -05:00
EnableDebug : enableDebug ,
2021-02-26 15:52:29 -05:00
}
} else {
if logflags . HasFlag ( LogFile ) {
logger = & FileLogger {
StdLogger : StdLogger {
Prefix : logPrefix ,
2021-02-26 20:27:35 -05:00
EnableDebug : enableDebug ,
2021-02-26 15:52:29 -05:00
} ,
Path : logPath ,
}
} else {
logger = & StdLogger {
Prefix : logPrefix ,
2021-02-26 20:27:35 -05:00
EnableDebug : enableDebug ,
2021-02-26 15:52:29 -05:00
}
}
}
}
2021-02-26 20:27:35 -05:00
logger . Setup ( )
if prefix != "\x00" {
2021-02-26 15:52:29 -05:00
logger . setPrefix ( prefix )
}
2021-02-27 00:38:54 -05:00
logger . Info ( "logger initialized of type %T with prefix %v" , logger , logger . Prefix )
2021-02-27 00:32:46 -05:00
2021-02-26 15:52:29 -05:00
return
}
func testOpen ( path string ) ( success bool , err error ) {
var f * os . File
// Example #2, https://golang.org/pkg/os/#OpenFile
2021-02-26 20:27:35 -05:00
if f , err = os . OpenFile ( path , appendFlags , logPerm ) ; err != nil {
2021-02-26 15:52:29 -05:00
return
}
defer f . Close ( )
success = true
return
}