2021-02-26 15:52:29 -05:00
package logging
import (
2021-02-27 00:51:58 -05:00
native "log"
"os"
"path"
2021-02-26 15:52:29 -05:00
"r00t2.io/goutils/types"
2021-02-27 00:51:58 -05:00
sysd "github.com/coreos/go-systemd/journal"
"r00t2.io/sysutils/paths"
2021-02-26 15:52:29 -05:00
)
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
2021-02-27 00:51:58 -05:00
if hasSyslog , stat , err = paths . RealPathExistsStat ( & devlogPath ) ; hasSyslog && err != nil {
return
}
2021-02-26 15:52:29 -05:00
2021-02-27 00:51:58 -05:00
if hasSyslog && ! stat . Mode ( ) . IsRegular ( ) {
logflags . AddFlag ( LogSyslog )
} else {
2021-02-26 15:52:29 -05:00
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 {
2021-02-27 00:51:58 -05:00
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 {
2021-02-27 00:51:58 -05:00
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 {
2021-02-27 00:51:58 -05:00
Prefix : logPrefix ,
2021-02-26 20:27:35 -05:00
EnableDebug : enableDebug ,
2021-02-26 15:52:29 -05:00
} ,
2021-02-27 00:51:58 -05:00
Path : logPath ,
2021-02-26 15:52:29 -05:00
}
} else {
logger = & StdLogger {
2021-02-27 00:51:58 -05:00
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-03-27 10:29:41 -04:00
logger . SetPrefix ( prefix )
2021-02-26 15:52:29 -05:00
}
2021-02-27 00:51:58 -05:00
logger . Info ( "logger initialized of type %T with prefix %v" , logger , logger . GetPrefix ( ) )
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
}