i think logging is done

This commit is contained in:
brent s. 2021-02-26 20:27:35 -05:00
parent d085d0f3ee
commit fe378850af
Signed by: bts
GPG Key ID: 8C004C2F93481F6B
9 changed files with 589 additions and 24 deletions

3
logging/TODO Normal file
View File

@ -0,0 +1,3 @@
- Implement code line/func/etc. (only for debug?):
https://stackoverflow.com/a/24809646
https://golang.org/pkg/runtime/#Caller

View File

@ -1,6 +1,7 @@
package logging package logging


import ( import (
`log/syslog`
`os` `os`


`r00t2.io/goutils/types` `r00t2.io/goutils/types`
@ -9,6 +10,9 @@ import (
const ( const (
devlog string = "/dev/log" devlog string = "/dev/log"
logPerm os.FileMode = 0600 logPerm os.FileMode = 0600
logPrefix string = "GOLANG PROGRAM"
appendFlags int = os.O_APPEND|os.O_CREATE|os.O_WRONLY
syslogFacility syslog.Priority = syslog.LOG_USER
) )


// Flags for logger configuration // Flags for logger configuration

View File

@ -4,7 +4,6 @@ import (
native `log` native `log`
`os` `os`
`path` `path`
`strings`


"r00t2.io/goutils/types" "r00t2.io/goutils/types"


@ -16,10 +15,15 @@ var (
_ = sysd.Enabled() _ = sysd.Enabled()
_ = native.Logger{} _ = native.Logger{}
_ = os.Interrupt _ = os.Interrupt
_ = types.Env{}
) )


func GetLogger(enableDebug bool, prefix string) (logger Logger, err error) { // 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 logPath string
var logflags types.MaskBit var logflags types.MaskBit
@ -40,8 +44,13 @@ func GetLogger(enableDebug bool, prefix string) (logger Logger, err error) {
if hasSyslog && !stat.Mode().IsRegular() {logflags.AddFlag(LogSyslog)} else { if hasSyslog && !stat.Mode().IsRegular() {logflags.AddFlag(LogSyslog)} else {
var exists bool var exists bool
var success bool var success bool
var ckLogPaths []string
logflags.AddFlag(LogStdout) logflags.AddFlag(LogStdout)
for _, p := range defLogPaths { ckLogPaths = defLogPaths
if logpaths != nil {
ckLogPaths = logpaths
}
for _, p := range ckLogPaths {
if exists, _ = paths.RealPathExists(&p); exists { if exists, _ = paths.RealPathExists(&p); exists {
if success, err = testOpen(p); err != nil { if success, err = testOpen(p); err != nil {
continue continue
@ -72,30 +81,34 @@ func GetLogger(enableDebug bool, prefix string) (logger Logger, err error) {
if logflags.HasFlag(LogJournald) { if logflags.HasFlag(LogJournald) {
logger = &SystemDLogger{ logger = &SystemDLogger{
Prefix: logPrefix, Prefix: logPrefix,
EnableDebug: enableDebug,
} }
} else { } else {
if logflags.HasFlag(LogSyslog) { if logflags.HasFlag(LogSyslog) {
logger = &SyslogLogger{ logger = &SyslogLogger{
Prefix: logPrefix, Prefix: logPrefix,
EnableDebug: enableDebug,
} }
} else { } else {
if logflags.HasFlag(LogFile) { if logflags.HasFlag(LogFile) {
logger = &FileLogger{ logger = &FileLogger{
StdLogger: StdLogger{ StdLogger: StdLogger{
Prefix: logPrefix, Prefix: logPrefix,
EnableDebug: enableDebug,
}, },
Path: logPath, Path: logPath,
} }
} else { } else {
logger = &StdLogger{ logger = &StdLogger{
Prefix: logPrefix, Prefix: logPrefix,
EnableDebug: enableDebug,
} }
} }
} }
} }


logger.doDebug(enableDebug) logger.Setup()
if strings.TrimSpace(prefix) != "" { if prefix != "\x00" {
logger.setPrefix(prefix) logger.setPrefix(prefix)
} }


@ -106,7 +119,7 @@ func testOpen(path string) (success bool, err error) {
var f *os.File var f *os.File


// Example #2, https://golang.org/pkg/os/#OpenFile // Example #2, https://golang.org/pkg/os/#OpenFile
if f, err = os.OpenFile(path, os.O_RDWR | os.O_CREATE, logPerm); err != nil { if f, err = os.OpenFile(path, appendFlags, logPerm); err != nil {
return return
} }
defer f.Close() defer f.Close()

View File

@ -1,41 +1,176 @@
package logging package logging


import (
`fmt`
`io`
`log`
`os`
)

func (l *FileLogger) Setup() {

var err error

l.Logger = log.Default()
l.Logger.SetPrefix(l.Prefix)
if l.writer, err = os.OpenFile(l.Path, appendFlags, logPerm); err != nil {
log.Panicf("could not open log file \"%v\" for writing: %v\n", l.Path, err)
}
// https://stackoverflow.com/a/36719588/733214
multi := io.MultiWriter(os.Stdout, l.writer)
l.Logger.SetOutput(multi)
}

func (l *FileLogger) Shutdown() {

var err error

if err = l.writer.Close(); err != nil {
log.Panicf("could not close log file \"%v\": %v\n", l.Path, err)
}

}

func (l *FileLogger) doDebug(d bool) { func (l *FileLogger) doDebug(d bool) {
l.EnableDebug = d l.EnableDebug = d
} }


func (l *FileLogger) setPrefix(prefix string) { func (l *FileLogger) setPrefix(prefix string) {
l.Prefix = prefix l.Prefix = prefix
l.Logger.SetPrefix(prefix)
} }


func (l *FileLogger) Alert(s string, v ...interface{}) (err error) { func (l *FileLogger) Alert(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "ALERT")

return return
} }


func (l *FileLogger) Crit(s string, v ...interface{}) (err error) { func (l *FileLogger) Crit(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "CRITICAL")

return return
} }


func (l *FileLogger) Debug(s string, v ...interface{}) (err error) { func (l *FileLogger) Debug(s string, v ...interface{}) (err error) {

if !l.EnableDebug {
return
}

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "DEBUG")

return return
} }


func (l *FileLogger) Emerg(s string, v ...interface{}) (err error) { func (l *FileLogger) Emerg(s string, v ...interface{}) (err error) {


var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "EMERGENCY")

return return
} }


func (l *FileLogger) Err(s string, v ...interface{}) (err error) { func (l *FileLogger) Err(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "ERROR")

return return
} }


func (l *FileLogger) Info(s string, v ...interface{}) (err error) { func (l *FileLogger) Info(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "INFO")

return return
} }


func (l *FileLogger) Notice(s string, v ...interface{}) (err error) { func (l *FileLogger) Notice(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "NOTICE")

return return
} }


func (l *FileLogger) Warning(s string, v ...interface{}) (err error) { func (l *FileLogger) Warning(s string, v ...interface{}) (err error) {


var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "WARNING")

return
}

func (l *FileLogger) renderWrite(msg, prio string) {

s := fmt.Sprintf("[%v] %v", prio, msg)

l.Logger.Println(s)

return return
} }

View File

@ -1,41 +1,163 @@
package logging package logging


import (
`fmt`
`log`
)

func (l *StdLogger) Setup() {

l.Logger = log.Default()
l.Logger.SetPrefix(l.Prefix)
}

func (l *StdLogger) Shutdown() {

// NOOP
_ = ""

}

func (l *StdLogger) doDebug(d bool) { func (l *StdLogger) doDebug(d bool) {
l.EnableDebug = d l.EnableDebug = d
} }


func (l *StdLogger) setPrefix(prefix string) { func (l *StdLogger) setPrefix(prefix string) {
l.Prefix = prefix l.Prefix = prefix
l.Logger.SetPrefix(prefix)
} }


func (l *StdLogger) Alert(s string, v ...interface{}) (err error) { func (l *StdLogger) Alert(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "ALERT")

return return
} }


func (l *StdLogger) Crit(s string, v ...interface{}) (err error) { func (l *StdLogger) Crit(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "CRITICAL")

return return
} }


func (l *StdLogger) Debug(s string, v ...interface{}) (err error) { func (l *StdLogger) Debug(s string, v ...interface{}) (err error) {

if !l.EnableDebug {
return
}

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "DEBUG")

return return
} }


func (l *StdLogger) Emerg(s string, v ...interface{}) (err error) { func (l *StdLogger) Emerg(s string, v ...interface{}) (err error) {


var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "EMERGENCY")

return return
} }


func (l *StdLogger) Err(s string, v ...interface{}) (err error) { func (l *StdLogger) Err(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "ERROR")

return return
} }


func (l *StdLogger) Info(s string, v ...interface{}) (err error) { func (l *StdLogger) Info(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "INFO")

return return
} }


func (l *StdLogger) Notice(s string, v ...interface{}) (err error) { func (l *StdLogger) Notice(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "NOTICE")

return return
} }


func (l *StdLogger) Warning(s string, v ...interface{}) (err error) { func (l *StdLogger) Warning(s string, v ...interface{}) (err error) {


var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, "WARNING")

return
}

func (l *StdLogger) renderWrite(msg, prio string) {

s := fmt.Sprintf("[%v] %v", prio, msg)

l.Logger.Println(s)

return return
} }

View File

@ -1,5 +1,26 @@
package logging package logging


import (
`fmt`
`log`

`github.com/coreos/go-systemd/journal`
)

func (l *SystemDLogger) Setup() {

// NOOP
_ = ""

}

func (l *SystemDLogger) Shutdown() {

// NOOP
_ = ""

}

func (l *SystemDLogger) doDebug(d bool) { func (l *SystemDLogger) doDebug(d bool) {
l.EnableDebug = d l.EnableDebug = d
} }
@ -9,33 +30,146 @@ func (l *SystemDLogger) setPrefix(prefix string) {
} }


func (l *SystemDLogger) Alert(s string, v ...interface{}) (err error) { func (l *SystemDLogger) Alert(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, journal.PriAlert)

return return
} }


func (l *SystemDLogger) Crit(s string, v ...interface{}) (err error) { func (l *SystemDLogger) Crit(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, journal.PriCrit)

return return
} }


func (l *SystemDLogger) Debug(s string, v ...interface{}) (err error) { func (l *SystemDLogger) Debug(s string, v ...interface{}) (err error) {

if !l.EnableDebug {
return
}

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, journal.PriDebug)

return return
} }


func (l *SystemDLogger) Emerg(s string, v ...interface{}) (err error) { func (l *SystemDLogger) Emerg(s string, v ...interface{}) (err error) {


var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, journal.PriEmerg)

return return
} }


func (l *SystemDLogger) Err(s string, v ...interface{}) (err error) { func (l *SystemDLogger) Err(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, journal.PriErr)

return return
} }


func (l *SystemDLogger) Info(s string, v ...interface{}) (err error) { func (l *SystemDLogger) Info(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, journal.PriInfo)

return return
} }


func (l *SystemDLogger) Notice(s string, v ...interface{}) (err error) { func (l *SystemDLogger) Notice(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, journal.PriNotice)

return return
} }


func (l *SystemDLogger) Warning(s string, v ...interface{}) (err error) { func (l *SystemDLogger) Warning(s string, v ...interface{}) (err error) {


var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

l.renderWrite(msg, journal.PriWarning)

return
}

func (l *SystemDLogger) renderWrite(msg string, prio journal.Priority) {
// TODO: implement code line, etc.
// https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html
// CODE_FILE=, CODE_LINE=, CODE_FUNC=
var err error

vars := map[string]string{
"DOCUMENTATION": "https://git.r00t2.io/Go_GoUtils/",
"SYSLOG_IDENTIFIER": l.Prefix,
"SYSLOG_FACILITY": "1", // USER
}

if err = journal.Send(msg, prio, vars); err != nil {
log.Panicln("could not send to Journald")
}

return return
} }

View File

@ -1,41 +1,198 @@
package logging package logging


import (
`fmt`
`log`
`log/syslog`
)

func (l *SyslogLogger) Setup() {

var err error

if l.alert, err = syslog.New(syslog.LOG_ALERT | syslogFacility, l.Prefix); err != nil {
log.Panicln("could not open log for Alert")
}
if l.crit, err = syslog.New(syslog.LOG_CRIT | syslogFacility, l.Prefix); err != nil {
log.Panicln("could not open log for Crit")
}
if l.debug, err = syslog.New(syslog.LOG_DEBUG | syslogFacility, l.Prefix); err != nil {
log.Panicln("could not open log for Debug")
}
if l.emerg, err = syslog.New(syslog.LOG_EMERG | syslogFacility, l.Prefix); err != nil {
log.Panicln("could not open log for Emerg")
}
if l.err, err = syslog.New(syslog.LOG_ERR | syslogFacility, l.Prefix); err != nil {
log.Panicln("could not open log for Err")
}
if l.info, err = syslog.New(syslog.LOG_INFO | syslogFacility, l.Prefix); err != nil {
log.Panicln("could not open log for Info")
}
if l.notice, err = syslog.New(syslog.LOG_NOTICE | syslogFacility, l.Prefix); err != nil {
log.Panicln("could not open log for Notice")
}
if l.warning, err = syslog.New(syslog.LOG_WARNING | syslogFacility, l.Prefix); err != nil {
log.Panicln("could not open log for Warning")
}

}

func (l *SyslogLogger) Shutdown() {

var err error

for _, i := range []*syslog.Writer{l.alert, l.crit, l.debug, l.emerg, l.err, l.info, l.notice, l.warning} {
if err = i.Close(); err != nil {
log.Panicf("could not close log %#v\n", i)
}
}

}

func (l *SyslogLogger) doDebug(d bool) { func (l *SyslogLogger) doDebug(d bool) {
l.EnableDebug = d l.EnableDebug = d
} }


func (l *SyslogLogger) setPrefix(prefix string) { func (l *SyslogLogger) setPrefix(prefix string) {
l.Prefix = prefix l.Prefix = prefix
l.Setup()
} }


func (l *SyslogLogger) Alert(s string, v ...interface{}) (err error) { func (l *SyslogLogger) Alert(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

if _, err = l.alert.Write([]byte(msg)); err != nil {
log.Panicf("could not write %v to syslog USER:ALERT facility/level", msg)
}

return return
} }


func (l *SyslogLogger) Crit(s string, v ...interface{}) (err error) { func (l *SyslogLogger) Crit(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

if _, err = l.crit.Write([]byte(msg)); err != nil {
log.Panicf("could not write %v to syslog USER:CRIT facility/level", msg)
}

return return
} }


func (l *SyslogLogger) Debug(s string, v ...interface{}) (err error) { func (l *SyslogLogger) Debug(s string, v ...interface{}) (err error) {

if !l.EnableDebug {
return
}

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

if _, err = l.debug.Write([]byte(msg)); err != nil {
log.Panicf("could not write %v to syslog USER:DEBUG facility/level", msg)
}

return return
} }


func (l *SyslogLogger) Emerg(s string, v ...interface{}) (err error) { func (l *SyslogLogger) Emerg(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

if _, err = l.emerg.Write([]byte(msg)); err != nil {
log.Panicf("could not write %v to syslog USER:EMERG facility/level", msg)
}

return return
} }


func (l *SyslogLogger) Err(s string, v ...interface{}) (err error) { func (l *SyslogLogger) Err(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

if _, err = l.err.Write([]byte(msg)); err != nil {
log.Panicf("could not write %v to syslog USER:ERR facility/level", msg)
}

return return
} }


func (l *SyslogLogger) Info(s string, v ...interface{}) (err error) { func (l *SyslogLogger) Info(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

if _, err = l.info.Write([]byte(msg)); err != nil {
log.Panicf("could not write %v to syslog USER:INFO facility/level", msg)
}

return return
} }


func (l *SyslogLogger) Notice(s string, v ...interface{}) (err error) { func (l *SyslogLogger) Notice(s string, v ...interface{}) (err error) {

var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

if _, err = l.notice.Write([]byte(msg)); err != nil {
log.Panicf("could not write %v to syslog USER:NOTICE facility/level", msg)
}

return return
} }


func (l *SyslogLogger) Warning(s string, v ...interface{}) (err error) { func (l *SyslogLogger) Warning(s string, v ...interface{}) (err error) {
var msg string

if v != nil {
msg = fmt.Sprintf(s, v...)
} else {
msg = s
}

if _, err = l.warning.Write([]byte(msg)); err != nil {
log.Panicf("could not write %v to syslog USER:WARNING facility/level", msg)
}

return return
} }

View File

@ -3,6 +3,7 @@ package logging
import ( import (
`log` `log`
`log/syslog` `log/syslog`
`os`
) )


type Logger interface { type Logger interface {
@ -16,6 +17,8 @@ type Logger interface {
Warning(string, ...interface{}) error Warning(string, ...interface{}) error
doDebug(bool) doDebug(bool)
setPrefix(string) setPrefix(string)
Setup()
Shutdown()
} }


type SystemDLogger struct { type SystemDLogger struct {
@ -24,21 +27,26 @@ type SystemDLogger struct {
} }


type SyslogLogger struct { type SyslogLogger struct {
syslog.Writer
EnableDebug bool EnableDebug bool
Prefix string Prefix string
alert,
crit,
debug,
emerg,
err,
info,
notice,
warning *syslog.Writer
} }


type StdLogger struct { type StdLogger struct {
log.Logger *log.Logger
EnableDebug bool EnableDebug bool
Prefix string Prefix string
} }


type FileLogger struct { type FileLogger struct {
log.Logger
StdLogger StdLogger
EnableDebug bool
Path string Path string
Prefix string writer *os.File
} }

View File

@ -10,17 +10,6 @@ type BitMask interface {
// BitMasks // BitMasks
type MaskBit uint8 type MaskBit uint8


// LDAP Connection flags
const (
LdapBindUndefined MaskBit = 1 << iota
LdapBindNone // GSSAPI via SASL or (TODO) Anonymous bind
LdapBindNet
LdapBindTls
LdapBindStartTls
LdapBindSasl
LdapBindNoPassword
)

func (f MaskBit) HasFlag(flag MaskBit) (r bool) { func (f MaskBit) HasFlag(flag MaskBit) (r bool) {
if f&flag != 0 { if f&flag != 0 {
r = true r = true