Finalizing for 1.2.0
This commit is contained in:
parent
39e0a1fd43
commit
d98363c0d7
1
.gitignore
vendored
1
.gitignore
vendored
@ -31,6 +31,7 @@
|
||||
# But DO include the actual tests.
|
||||
!_test.go
|
||||
!*_test.go
|
||||
!*_test_*.go
|
||||
!*_test/
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
|
@ -1,10 +1,11 @@
|
||||
- Implement code line/func/etc. (only for debug?):
|
||||
https://stackoverflow.com/a/24809646
|
||||
https://golang.org/pkg/runtime/#Caller
|
||||
-- log.LlongFile and log.Lshortfile flags don't currently work properly for StdLogger/FileLogger; they refer to the file in logging package rather than the caller.
|
||||
|
||||
- Suport remote loggers? (eventlog, syslog, systemd)
|
||||
|
||||
- JSON logger? YAML logger? XML logger?
|
||||
|
||||
- DOCS.
|
||||
-- Done, but flesh out.
|
||||
|
||||
- Unit/Integration tests.
|
||||
|
39
logging/consts_test.go
Normal file
39
logging/consts_test.go
Normal file
@ -0,0 +1,39 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
`log`
|
||||
)
|
||||
|
||||
/*
|
||||
The following are strings written to the Logger in the various tests.
|
||||
The %v is populated with the name of the type of Logger.
|
||||
*/
|
||||
const (
|
||||
testAlert string = "This is a test ALERT-priority log message for logger %v."
|
||||
testCrit string = "This is a test CRITICAL-priority (CRIT) log message for logger %v."
|
||||
testDebug string = "This is a test DEBUG-priority log message for logger %v."
|
||||
testEmerg string = "This is a test EMERGENCY-priority (EMERG) log message for logger %v."
|
||||
testErr string = "This is a test ERROR-priority (ERR) log message for logger %v."
|
||||
testInfo string = "This is a test INFO-priority log message for logger %v."
|
||||
testNotice string = "This is a test NOTICE-priority log message for logger %v."
|
||||
testWarning string = "This is a test WARNING-priority log message for logger %v."
|
||||
)
|
||||
|
||||
// Prefixes to use for tests.
|
||||
const (
|
||||
// TestLogPrefix is used as the initial prefix.
|
||||
TestLogPrefix string = "LOGGING_TESTRUN"
|
||||
// TestLogAltPrefix is used as the alternative prefix to Logger.SetPrefix.
|
||||
TestLogAltPrefix string = "LOGGING_TESTRUN_ALT"
|
||||
)
|
||||
|
||||
const (
|
||||
// EnvVarKeepLog is the env var key/var name to use to suppress removal of FileLogger.Path after tests complete.
|
||||
EnvVarKeepLog string = "LOGGING_KEEP_TEMPLOG"
|
||||
)
|
||||
|
||||
const (
|
||||
// logFlags are used to set the log flags for StdLogger (and FileLogger.StdLogger).
|
||||
// logFlags int = log.Ldate | log.Lmicroseconds | log.Llongfile | log.LUTC
|
||||
logFlags int = log.Ldate | log.Lmicroseconds | log.Lshortfile | log.LUTC
|
||||
)
|
@ -55,7 +55,7 @@ var DefaultEventID *WinEventID = &WinEventID{
|
||||
Warning: EventWarning,
|
||||
}
|
||||
|
||||
// Default Event IDs for WinEventID.
|
||||
// Default Event IDs for WinEventID (DefaultEventID, specifically).
|
||||
const (
|
||||
EventAlert uint32 = 1 << iota
|
||||
EventCrit
|
||||
|
@ -35,11 +35,11 @@ Note that in the case of a MultiLogger, err (if not nil) will be a (r00t2.io/gou
|
||||
|
||||
logging.Logger types also have the following methods:
|
||||
|
||||
DoDebug(d bool)
|
||||
SetPrefix(p string)
|
||||
GetPrefix() (p string)
|
||||
Setup()
|
||||
Shutdown()
|
||||
DoDebug(d bool) (err error)
|
||||
SetPrefix(p string) (err error)
|
||||
GetPrefix() (p string, err error)
|
||||
Setup() (err error)
|
||||
Shutdown() (err error)
|
||||
|
||||
In some cases, Logger.Setup and Logger.Shutdown are no-ops. In other cases, they perform necessary initialization/cleanup and closing of the logger.
|
||||
It is recommended to *always* run Setup and Shutdown before and after using, respectively, regardless of the actual logging.Logger type.
|
||||
|
@ -6,7 +6,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrBadBinPath is returned if installing a binary-registered Event Log source instead of using EventCreate.exe.
|
||||
ErrBadBinPath error = errors.New("evaluated binary path does not actually exist")
|
||||
ErrBadPerms error = errors.New("access denied when attempting to register Event Log source")
|
||||
ErrBadEid error = errors.New(fmt.Sprintf("event IDs must be between %v and %v inclusive", EIDMin, EIDMax))
|
||||
// ErrBadPerms is returned if an access denied error is received when attempting to register, write to, close, etc. a source without proper perms.
|
||||
ErrBadPerms error = errors.New("access denied when attempting to register Event Log source")
|
||||
// ErrBadEid is returned if an event ID is within an invalid range.
|
||||
ErrBadEid error = errors.New(fmt.Sprintf("event IDs must be between %v and %v inclusive", EIDMin, EIDMax))
|
||||
)
|
||||
|
@ -6,13 +6,16 @@ import (
|
||||
|
||||
// testOpen attempts to open a file for writing to test for suitability as a LogFile path.
|
||||
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()
|
||||
if err = f.Close(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
success = true
|
||||
|
||||
|
@ -3,7 +3,6 @@ package logging
|
||||
import (
|
||||
`errors`
|
||||
"fmt"
|
||||
"io"
|
||||
`io/fs`
|
||||
"log"
|
||||
"os"
|
||||
@ -13,8 +12,6 @@ import (
|
||||
// Setup sets up/configures a FileLogger and prepares it for use.
|
||||
func (l *FileLogger) Setup() (err error) {
|
||||
|
||||
var multi io.Writer
|
||||
|
||||
// This uses a shared handle across the import. We don't want that.
|
||||
// l.Logger = log.Default()
|
||||
if l.Prefix != "" {
|
||||
@ -25,19 +22,7 @@ func (l *FileLogger) Setup() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/36719588/733214
|
||||
switch {
|
||||
case l.EnableStdErr && l.EnableStdOut:
|
||||
multi = io.MultiWriter(os.Stdout, os.Stderr, l.writer)
|
||||
case l.EnableStdErr:
|
||||
multi = io.MultiWriter(os.Stderr, l.writer)
|
||||
case l.EnableStdOut:
|
||||
multi = io.MultiWriter(os.Stdout, l.writer)
|
||||
default:
|
||||
multi = l.writer
|
||||
}
|
||||
|
||||
l.Logger = log.New(multi, l.Prefix, l.LogFlags)
|
||||
l.Logger = log.New(l.writer, l.Prefix, l.LogFlags)
|
||||
// l.Logger.SetOutput(multi)
|
||||
|
||||
return
|
||||
@ -50,6 +35,8 @@ func (l *FileLogger) Shutdown() (err error) {
|
||||
if !errors.Is(err, fs.ErrClosed) {
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
|
270
logging/funcs_linux_test.go
Normal file
270
logging/funcs_linux_test.go
Normal file
@ -0,0 +1,270 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
`fmt`
|
||||
`os`
|
||||
`testing`
|
||||
)
|
||||
|
||||
/*
|
||||
TestSysDLogger tests functionality for SystemDLogger.
|
||||
*/
|
||||
func TestSysDLogger(t *testing.T) {
|
||||
|
||||
var l *SystemDLogger
|
||||
var ltype string = "SystemDLogger"
|
||||
var prefix string
|
||||
var err error
|
||||
|
||||
l = &SystemDLogger{
|
||||
EnableDebug: true,
|
||||
Prefix: TestLogPrefix,
|
||||
}
|
||||
|
||||
if err = l.Setup(); err != nil {
|
||||
t.Fatalf("error when running Setup: %v", err.Error())
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed Setup. Logger: %#v", ltype, l)
|
||||
|
||||
if err = l.Alert(testAlert, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Crit(testCrit, ltype); err != nil {
|
||||
t.Fatalf("error for Crit: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Debug(testDebug, ltype); err != nil {
|
||||
t.Fatalf("error for Debug: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Emerg(testEmerg, ltype); err != nil {
|
||||
t.Fatalf("error for Emerg: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Err(testErr, ltype); err != nil {
|
||||
t.Fatalf("error for Err: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Info(testInfo, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Notice(testNotice, ltype); err != nil {
|
||||
t.Fatalf("error for Notice: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Warning(testWarning, ltype); err != nil {
|
||||
t.Fatalf("error for Warning: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix, err = l.GetPrefix(); err != nil {
|
||||
t.Fatalf("error when fetching prefix: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix != TestLogPrefix {
|
||||
t.Fatalf("true prefix ('%v') does not match TestLogPrefix ('%v')", prefix, TestLogPrefix)
|
||||
}
|
||||
if err = l.SetPrefix(TestLogAltPrefix); err != nil {
|
||||
t.Fatalf("error when setting prefix to %v: %v", TestLogAltPrefix, err.Error())
|
||||
} else {
|
||||
_ = l.SetPrefix(TestLogPrefix)
|
||||
}
|
||||
|
||||
if err = l.DoDebug(false); err != nil {
|
||||
t.Fatalf("error when changing debug to false: %v", err.Error())
|
||||
} else if l.EnableDebug {
|
||||
t.Fatalf("did not properly set Debug filter state")
|
||||
} else {
|
||||
_ = l.DoDebug(true)
|
||||
}
|
||||
|
||||
if err = l.Shutdown(); err != nil {
|
||||
t.Fatalf("Error when running Shutdown: %v", err.Error())
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed all logging targets.", ltype)
|
||||
}
|
||||
|
||||
/*
|
||||
TestSyslogLogger tests functionality for SyslogLogger.
|
||||
*/
|
||||
func TestSyslogLogger(t *testing.T) {
|
||||
|
||||
var l *SyslogLogger
|
||||
var ltype string = "SyslogLogger"
|
||||
var prefix string
|
||||
var err error
|
||||
|
||||
l = &SyslogLogger{
|
||||
EnableDebug: true,
|
||||
Prefix: TestLogPrefix,
|
||||
}
|
||||
|
||||
if err = l.Setup(); err != nil {
|
||||
t.Fatalf("error when running Setup: %v", err.Error())
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed Setup. Logger: %#v", ltype, l)
|
||||
|
||||
if err = l.Alert(testAlert, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Crit(testCrit, ltype); err != nil {
|
||||
t.Fatalf("error for Crit: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Debug(testDebug, ltype); err != nil {
|
||||
t.Fatalf("error for Debug: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Emerg(testEmerg, ltype); err != nil {
|
||||
t.Fatalf("error for Emerg: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Err(testErr, ltype); err != nil {
|
||||
t.Fatalf("error for Err: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Info(testInfo, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Notice(testNotice, ltype); err != nil {
|
||||
t.Fatalf("error for Notice: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Warning(testWarning, ltype); err != nil {
|
||||
t.Fatalf("error for Warning: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix, err = l.GetPrefix(); err != nil {
|
||||
t.Fatalf("error when fetching prefix: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix != TestLogPrefix {
|
||||
t.Fatalf("true prefix ('%v') does not match TestLogPrefix ('%v')", prefix, TestLogPrefix)
|
||||
}
|
||||
if err = l.SetPrefix(TestLogAltPrefix); err != nil {
|
||||
t.Fatalf("error when setting prefix to %v: %v", TestLogAltPrefix, err.Error())
|
||||
} else {
|
||||
_ = l.SetPrefix(TestLogPrefix)
|
||||
}
|
||||
|
||||
if err = l.DoDebug(false); err != nil {
|
||||
t.Fatalf("error when changing debug to false: %v", err.Error())
|
||||
} else if l.EnableDebug {
|
||||
t.Fatalf("did not properly set Debug filter state")
|
||||
} else {
|
||||
_ = l.DoDebug(true)
|
||||
}
|
||||
|
||||
if err = l.Shutdown(); err != nil {
|
||||
t.Fatalf("Error when running Shutdown: %v", err.Error())
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed all logging targets.", ltype)
|
||||
}
|
||||
|
||||
// TestDefaultLogger tests GetLogger.
|
||||
func TestDefaultLogger(t *testing.T) {
|
||||
|
||||
var l Logger
|
||||
var tempfile *os.File
|
||||
var tempfilePath string
|
||||
var keepLog bool
|
||||
var ltype string
|
||||
var prefix string
|
||||
var testPrefix string
|
||||
var err error
|
||||
|
||||
if tempfile, err = os.CreateTemp("", ".LOGGINGTEST_*"); err != nil {
|
||||
t.Fatalf("error when creating temporary log file '%v': %v", tempfile.Name(), err.Error())
|
||||
}
|
||||
tempfilePath = tempfile.Name()
|
||||
// We can close the handler immediately; we don't need it since the FileLogger opens its own.
|
||||
if err = tempfile.Close(); err != nil {
|
||||
t.Fatalf("error when closing handler for temporary log file '%v': %v", tempfile.Name(), err.Error())
|
||||
}
|
||||
|
||||
if l, err = GetLogger(true, TestLogPrefix, logFlags, tempfilePath); err != nil {
|
||||
t.Fatalf("error when spawning default Linux logger via GetLogger: %v", err.Error())
|
||||
}
|
||||
|
||||
ltype = fmt.Sprintf("%T", l)
|
||||
|
||||
t.Logf("Logger %v passed Setup. Logger: %#v", ltype, l)
|
||||
|
||||
if err = l.Alert(testAlert, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Crit(testCrit, ltype); err != nil {
|
||||
t.Fatalf("error for Crit: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Debug(testDebug, ltype); err != nil {
|
||||
t.Fatalf("error for Debug: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Emerg(testEmerg, ltype); err != nil {
|
||||
t.Fatalf("error for Emerg: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Err(testErr, ltype); err != nil {
|
||||
t.Fatalf("error for Err: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Info(testInfo, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Notice(testNotice, ltype); err != nil {
|
||||
t.Fatalf("error for Notice: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Warning(testWarning, ltype); err != nil {
|
||||
t.Fatalf("error for Warning: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix, err = l.GetPrefix(); err != nil {
|
||||
t.Fatalf("error when fetching prefix: %v", err.Error())
|
||||
}
|
||||
|
||||
if ltype == "StdLogger" || ltype == "FileLogger" { // StdLogger (and thus FileLogger) adds a space at the end.
|
||||
testPrefix = TestLogPrefix + " "
|
||||
} else {
|
||||
testPrefix = TestLogPrefix
|
||||
}
|
||||
|
||||
if prefix != testPrefix {
|
||||
t.Fatalf("true prefix ('%v') does not match TestLogPrefix ('%v')", prefix, TestLogPrefix)
|
||||
}
|
||||
if err = l.SetPrefix(TestLogAltPrefix); err != nil {
|
||||
t.Fatalf("error when setting prefix to %v: %v", TestLogAltPrefix, err.Error())
|
||||
} else {
|
||||
_ = l.SetPrefix(TestLogPrefix)
|
||||
}
|
||||
|
||||
if err = l.DoDebug(false); err != nil {
|
||||
t.Fatalf("error when changing debug to false: %v", err.Error())
|
||||
} else {
|
||||
_ = l.DoDebug(true)
|
||||
}
|
||||
|
||||
if err = l.Shutdown(); err != nil {
|
||||
t.Fatalf("Error when running Shutdown: %v", err.Error())
|
||||
}
|
||||
|
||||
_, keepLog = os.LookupEnv(EnvVarKeepLog)
|
||||
|
||||
if !keepLog {
|
||||
if err = os.Remove(tempfilePath); err != nil {
|
||||
t.Fatalf("error when removing temporary log file '%v': %v", tempfilePath, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed all logging targets.", ltype)
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
`errors`
|
||||
`fmt`
|
||||
`sync`
|
||||
|
||||
`r00t2.io/goutils/multierr`
|
||||
@ -12,16 +14,17 @@ func (m *MultiLogger) Setup() (err error) {
|
||||
var wg sync.WaitGroup
|
||||
var errs *multierr.MultiError = multierr.NewMultiError(nil)
|
||||
|
||||
for _, l := range m.Loggers {
|
||||
for logName, l := range m.Loggers {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
go func(logger Logger, lName string) {
|
||||
var err2 error
|
||||
defer wg.Done()
|
||||
if err2 = l.Setup(); err2 != nil {
|
||||
if err2 = logger.Setup(); err2 != nil {
|
||||
errs.AddError(errors.New(fmt.Sprintf("error on Setup for logger %v; follows (may be out of order):", lName)))
|
||||
errs.AddError(err2)
|
||||
err2 = nil
|
||||
}
|
||||
}()
|
||||
}(l, logName)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@ -40,16 +43,17 @@ func (m *MultiLogger) Shutdown() (err error) {
|
||||
var wg sync.WaitGroup
|
||||
var errs *multierr.MultiError = multierr.NewMultiError(nil)
|
||||
|
||||
for _, l := range m.Loggers {
|
||||
for logName, l := range m.Loggers {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
go func(logger Logger, lName string) {
|
||||
var err2 error
|
||||
defer wg.Done()
|
||||
if err2 = l.Shutdown(); err2 != nil {
|
||||
if err2 = logger.Shutdown(); err2 != nil {
|
||||
errs.AddError(errors.New(fmt.Sprintf("error on Shutdown for logger %v; follows (may be out of order):", lName)))
|
||||
errs.AddError(err2)
|
||||
err2 = nil
|
||||
}
|
||||
}()
|
||||
}(l, logName)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@ -87,16 +91,17 @@ func (m *MultiLogger) DoDebug(d bool) (err error) {
|
||||
|
||||
m.EnableDebug = d
|
||||
|
||||
for _, l := range m.Loggers {
|
||||
for logName, l := range m.Loggers {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
go func(logger Logger, lName string) {
|
||||
var err2 error
|
||||
defer wg.Done()
|
||||
if err2 = l.DoDebug(d); err2 != nil {
|
||||
errs.AddError(errors.New(fmt.Sprintf("error on DoDebug for logger %v; follows (may be out of order):", lName)))
|
||||
errs.AddError(err2)
|
||||
err2 = nil
|
||||
}
|
||||
}()
|
||||
}(l, logName)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@ -121,16 +126,17 @@ func (m *MultiLogger) SetPrefix(prefix string) (err error) {
|
||||
|
||||
m.Prefix = prefix
|
||||
|
||||
for _, l := range m.Loggers {
|
||||
for logName, l := range m.Loggers {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
go func(logger Logger, lName string) {
|
||||
var err2 error
|
||||
defer wg.Done()
|
||||
if err2 = l.SetPrefix(prefix); err != nil {
|
||||
errs.AddError(errors.New(fmt.Sprintf("error on SetPrefix for logger %v; follows (may be out of order):", lName)))
|
||||
errs.AddError(err2)
|
||||
err2 = nil
|
||||
}
|
||||
}()
|
||||
}(l, logName)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@ -149,15 +155,16 @@ func (m *MultiLogger) Alert(s string, v ...interface{}) (err error) {
|
||||
var wg sync.WaitGroup
|
||||
var e *multierr.MultiError = multierr.NewMultiError(nil)
|
||||
|
||||
for _, l := range m.Loggers {
|
||||
for logName, l := range m.Loggers {
|
||||
wg.Add(1)
|
||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||
go func(logObj Logger, msg, lName string, rplc ...interface{}) {
|
||||
defer wg.Done()
|
||||
if err = logObj.Alert(msg, rplc...); err != nil {
|
||||
e.AddError(errors.New(fmt.Sprintf("error on Alert for logger %v; follows (may be out of order):", lName)))
|
||||
e.AddError(err)
|
||||
err = nil
|
||||
}
|
||||
}(l, s, v...)
|
||||
}(l, s, logName, v...)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@ -175,15 +182,16 @@ func (m *MultiLogger) Crit(s string, v ...interface{}) (err error) {
|
||||
var wg sync.WaitGroup
|
||||
var e *multierr.MultiError = multierr.NewMultiError(nil)
|
||||
|
||||
for _, l := range m.Loggers {
|
||||
for logName, l := range m.Loggers {
|
||||
wg.Add(1)
|
||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||
go func(logObj Logger, msg, lName string, rplc ...interface{}) {
|
||||
defer wg.Done()
|
||||
if err = logObj.Crit(msg, rplc...); err != nil {
|
||||
e.AddError(errors.New(fmt.Sprintf("error on Crit for logger %v; follows (may be out of order):", lName)))
|
||||
e.AddError(err)
|
||||
err = nil
|
||||
}
|
||||
}(l, s, v...)
|
||||
}(l, s, logName, v...)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@ -201,15 +209,16 @@ func (m *MultiLogger) Debug(s string, v ...interface{}) (err error) {
|
||||
var wg sync.WaitGroup
|
||||
var e *multierr.MultiError = multierr.NewMultiError(nil)
|
||||
|
||||
for _, l := range m.Loggers {
|
||||
for logName, l := range m.Loggers {
|
||||
wg.Add(1)
|
||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||
go func(logObj Logger, msg, lName string, rplc ...interface{}) {
|
||||
defer wg.Done()
|
||||
if err = logObj.Debug(msg, rplc...); err != nil {
|
||||
e.AddError(errors.New(fmt.Sprintf("error on Debug for logger %v; follows (may be out of order):", lName)))
|
||||
e.AddError(err)
|
||||
err = nil
|
||||
}
|
||||
}(l, s, v...)
|
||||
}(l, s, logName, v...)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@ -226,15 +235,16 @@ func (m *MultiLogger) Emerg(s string, v ...interface{}) (err error) {
|
||||
var wg sync.WaitGroup
|
||||
var e *multierr.MultiError = multierr.NewMultiError(nil)
|
||||
|
||||
for _, l := range m.Loggers {
|
||||
for logName, l := range m.Loggers {
|
||||
wg.Add(1)
|
||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||
go func(logObj Logger, msg, lName string, rplc ...interface{}) {
|
||||
defer wg.Done()
|
||||
if err = logObj.Emerg(msg, rplc...); err != nil {
|
||||
e.AddError(errors.New(fmt.Sprintf("error on Emerg for logger %v; follows (may be out of order):", lName)))
|
||||
e.AddError(err)
|
||||
err = nil
|
||||
}
|
||||
}(l, s, v...)
|
||||
}(l, s, logName, v...)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@ -251,15 +261,16 @@ func (m *MultiLogger) Err(s string, v ...interface{}) (err error) {
|
||||
var wg sync.WaitGroup
|
||||
var e *multierr.MultiError = multierr.NewMultiError(nil)
|
||||
|
||||
for _, l := range m.Loggers {
|
||||
for logName, l := range m.Loggers {
|
||||
wg.Add(1)
|
||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||
go func(logObj Logger, msg, lName string, rplc ...interface{}) {
|
||||
defer wg.Done()
|
||||
if err = logObj.Err(msg, rplc...); err != nil {
|
||||
e.AddError(errors.New(fmt.Sprintf("error on Err for logger %v; follows (may be out of order):", lName)))
|
||||
e.AddError(err)
|
||||
err = nil
|
||||
}
|
||||
}(l, s, v...)
|
||||
}(l, s, logName, v...)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@ -277,15 +288,16 @@ func (m *MultiLogger) Info(s string, v ...interface{}) (err error) {
|
||||
var wg sync.WaitGroup
|
||||
var e *multierr.MultiError = multierr.NewMultiError(nil)
|
||||
|
||||
for _, l := range m.Loggers {
|
||||
for logName, l := range m.Loggers {
|
||||
wg.Add(1)
|
||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||
go func(logObj Logger, msg, lName string, rplc ...interface{}) {
|
||||
defer wg.Done()
|
||||
if err = logObj.Info(msg, rplc...); err != nil {
|
||||
e.AddError(errors.New(fmt.Sprintf("error on Info for logger %v; follows (may be out of order):", lName)))
|
||||
e.AddError(err)
|
||||
err = nil
|
||||
}
|
||||
}(l, s, v...)
|
||||
}(l, s, logName, v...)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@ -303,15 +315,16 @@ func (m *MultiLogger) Notice(s string, v ...interface{}) (err error) {
|
||||
var wg sync.WaitGroup
|
||||
var e *multierr.MultiError = multierr.NewMultiError(nil)
|
||||
|
||||
for _, l := range m.Loggers {
|
||||
for logName, l := range m.Loggers {
|
||||
wg.Add(1)
|
||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||
go func(logObj Logger, msg, lName string, rplc ...interface{}) {
|
||||
defer wg.Done()
|
||||
if err = logObj.Notice(msg, rplc...); err != nil {
|
||||
e.AddError(errors.New(fmt.Sprintf("error on Notice for logger %v; follows (may be out of order):", lName)))
|
||||
e.AddError(err)
|
||||
err = nil
|
||||
}
|
||||
}(l, s, v...)
|
||||
}(l, s, logName, v...)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@ -329,15 +342,16 @@ func (m *MultiLogger) Warning(s string, v ...interface{}) (err error) {
|
||||
var wg sync.WaitGroup
|
||||
var e *multierr.MultiError = multierr.NewMultiError(nil)
|
||||
|
||||
for _, l := range m.Loggers {
|
||||
for logName, l := range m.Loggers {
|
||||
wg.Add(1)
|
||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||
go func(logObj Logger, msg, lName string, rplc ...interface{}) {
|
||||
defer wg.Done()
|
||||
if err = logObj.Warning(msg, rplc...); err != nil {
|
||||
e.AddError(errors.New(fmt.Sprintf("error on Warning for logger %v; follows (may be out of order):", lName)))
|
||||
e.AddError(err)
|
||||
err = nil
|
||||
}
|
||||
}(l, s, v...)
|
||||
}(l, s, logName, v...)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
@ -37,9 +37,15 @@ func GetMultiLogger(enableDebug bool, prefix string) (m *MultiLogger) {
|
||||
identifier is a string to use to identify the added StdLogger in MultiLogger.Loggers.
|
||||
If empty, one will be automatically generated.
|
||||
|
||||
enableStdOut indicates that messages should be logged to STDOUT;
|
||||
it is *strongly encouraged* to set at least one of enableStdOut or enableStdErr to true.
|
||||
|
||||
enableStdErr indicates that messages should be logged to STDERR;
|
||||
it is *strongly encouraged* to set at least one of enableStdErr or enableStdOut to true.
|
||||
|
||||
See GetLogger's logConfigFlags argument and StdLogger.LogFlags for details on logFlags.
|
||||
*/
|
||||
func (m *MultiLogger) AddStdLogger(identifier string, logFlags int) (err error) {
|
||||
func (m *MultiLogger) AddStdLogger(identifier string, enableStdOut, enableStdErr bool, logFlags int) (err error) {
|
||||
|
||||
var exists bool
|
||||
var prefix string
|
||||
@ -54,10 +60,12 @@ func (m *MultiLogger) AddStdLogger(identifier string, logFlags int) (err error)
|
||||
}
|
||||
|
||||
m.Loggers[identifier] = &StdLogger{
|
||||
Logger: nil,
|
||||
EnableDebug: m.EnableDebug,
|
||||
Prefix: m.Prefix,
|
||||
LogFlags: logFlags,
|
||||
Logger: nil,
|
||||
EnableDebug: m.EnableDebug,
|
||||
Prefix: m.Prefix,
|
||||
LogFlags: logFlags,
|
||||
EnableStdOut: enableStdOut,
|
||||
EnableStdErr: enableStdErr,
|
||||
}
|
||||
if err = m.Loggers[identifier].Setup(); err != nil {
|
||||
return
|
||||
@ -80,7 +88,7 @@ func (m *MultiLogger) AddStdLogger(identifier string, logFlags int) (err error)
|
||||
|
||||
logfilePath is a string for the path to the desired logfile.
|
||||
*/
|
||||
func (m *MultiLogger) AddFileLogger(identifier string, enableStdOut, enableStdErr bool, logFlags int, logfilePath string) (err error) {
|
||||
func (m *MultiLogger) AddFileLogger(identifier string, logFlags int, logfilePath string) (err error) {
|
||||
|
||||
var exists bool
|
||||
var success bool
|
||||
@ -122,9 +130,7 @@ func (m *MultiLogger) AddFileLogger(identifier string, enableStdOut, enableStdEr
|
||||
Prefix: m.Prefix,
|
||||
LogFlags: logFlags,
|
||||
},
|
||||
Path: logfilePath,
|
||||
EnableStdOut: enableStdOut,
|
||||
EnableStdErr: enableStdErr,
|
||||
Path: logfilePath,
|
||||
}
|
||||
if err = m.Loggers[identifier].Setup(); err != nil {
|
||||
return
|
||||
|
@ -65,7 +65,7 @@ func (m *MultiLogger) AddDefaultLogger(identifier string, eventIDs *WinEventID,
|
||||
|
||||
See GetLogger for details.
|
||||
*/
|
||||
func (m *MultiLogger) AddWinLogger(identifier, source string, eventIDs *WinEventID) (err error) {
|
||||
func (m *MultiLogger) AddWinLogger(identifier string, eventIDs *WinEventID) (err error) {
|
||||
|
||||
var exists bool
|
||||
var prefix string
|
||||
@ -84,9 +84,9 @@ func (m *MultiLogger) AddWinLogger(identifier, source string, eventIDs *WinEvent
|
||||
}
|
||||
|
||||
m.Loggers[identifier] = &WinLogger{
|
||||
Prefix: source,
|
||||
Prefix: m.Prefix,
|
||||
EnableDebug: m.EnableDebug,
|
||||
eids: eventIDs,
|
||||
EIDs: eventIDs,
|
||||
}
|
||||
if err = m.Loggers[identifier].Setup(); err != nil {
|
||||
return
|
||||
|
@ -2,6 +2,7 @@ package logging
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
`io`
|
||||
`log`
|
||||
`os`
|
||||
`strings`
|
||||
@ -13,14 +14,34 @@ import (
|
||||
*/
|
||||
func (l *StdLogger) Setup() (err error) {
|
||||
|
||||
var multi io.Writer
|
||||
|
||||
// This uses a shared handle across the import. We don't want that.
|
||||
// l.Logger = log.Default()
|
||||
if l.Prefix != "" {
|
||||
l.Prefix = strings.TrimRight(l.Prefix, " ") + " "
|
||||
// l.Logger.SetPrefix(l.Prefix)
|
||||
}
|
||||
// (stdlib).log.std is returned by log.Default(), which uses os.Stderr.
|
||||
l.Logger = log.New(os.Stderr, l.Prefix, l.LogFlags)
|
||||
// (stdlib).log.std is returned by log.Default(), which uses os.Stderr but we have flags for that.
|
||||
// https://stackoverflow.com/a/36719588/733214
|
||||
switch {
|
||||
case l.EnableStdErr && l.EnableStdOut:
|
||||
multi = io.MultiWriter(os.Stdout, os.Stderr)
|
||||
case l.EnableStdErr:
|
||||
multi = os.Stderr
|
||||
case l.EnableStdOut:
|
||||
multi = os.Stdout
|
||||
default:
|
||||
multi = nil
|
||||
}
|
||||
if multi != nil {
|
||||
l.Logger = log.New(multi, l.Prefix, l.LogFlags)
|
||||
} else {
|
||||
// This honestly should throw an error.
|
||||
l.Logger = &log.Logger{}
|
||||
l.Logger.SetPrefix(l.Prefix)
|
||||
l.Logger.SetFlags(l.LogFlags)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -1 +1,196 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
`os`
|
||||
`testing`
|
||||
)
|
||||
|
||||
/*
|
||||
TestStdLogger tests functionality for StdLogger.
|
||||
*/
|
||||
func TestStdLogger(t *testing.T) {
|
||||
|
||||
var l *StdLogger
|
||||
var ltype string = "StdLogger"
|
||||
var prefix string
|
||||
var err error
|
||||
|
||||
l = &StdLogger{
|
||||
EnableDebug: true,
|
||||
Prefix: TestLogPrefix,
|
||||
LogFlags: logFlags,
|
||||
EnableStdOut: false,
|
||||
EnableStdErr: true,
|
||||
}
|
||||
|
||||
if err = l.Setup(); err != nil {
|
||||
t.Fatalf("error when running Setup: %v", err.Error())
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed Setup. Logger: %#v", ltype, l)
|
||||
|
||||
if err = l.Alert(testAlert, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Crit(testCrit, ltype); err != nil {
|
||||
t.Fatalf("error for Crit: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Debug(testDebug, ltype); err != nil {
|
||||
t.Fatalf("error for Debug: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Emerg(testEmerg, ltype); err != nil {
|
||||
t.Fatalf("error for Emerg: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Err(testErr, ltype); err != nil {
|
||||
t.Fatalf("error for Err: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Info(testInfo, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Notice(testNotice, ltype); err != nil {
|
||||
t.Fatalf("error for Notice: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Warning(testWarning, ltype); err != nil {
|
||||
t.Fatalf("error for Warning: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix, err = l.GetPrefix(); err != nil {
|
||||
t.Fatalf("error when fetching prefix: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix != (TestLogPrefix + " ") { // StdLogger adds a space at the end.
|
||||
t.Fatalf("true prefix ('%v') does not match TestLogPrefix ('%v')", prefix, TestLogPrefix)
|
||||
}
|
||||
if err = l.SetPrefix(TestLogAltPrefix); err != nil {
|
||||
t.Fatalf("error when setting prefix to %v: %v", TestLogAltPrefix, err.Error())
|
||||
} else {
|
||||
_ = l.SetPrefix(TestLogPrefix)
|
||||
}
|
||||
|
||||
if err = l.DoDebug(false); err != nil {
|
||||
t.Fatalf("error when changing debug to false: %v", err.Error())
|
||||
} else if l.EnableDebug {
|
||||
t.Fatalf("did not properly set Debug filter state")
|
||||
} else {
|
||||
_ = l.DoDebug(true)
|
||||
}
|
||||
|
||||
if err = l.Shutdown(); err != nil {
|
||||
t.Fatalf("Error when running Shutdown: %v", err.Error())
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed all logging targets.", ltype)
|
||||
}
|
||||
|
||||
/*
|
||||
TestFileLogger tests functionality for FileLogger.
|
||||
If the appropriate env var is set (see the EnvVarKeepLog constant), the temporary log file that is created will not be cleaned up.
|
||||
*/
|
||||
func TestFileLogger(t *testing.T) {
|
||||
|
||||
var l *FileLogger
|
||||
var ltype string = "FileLogger"
|
||||
var prefix string
|
||||
var tempfile *os.File
|
||||
var tempfilePath string
|
||||
var keepLog bool
|
||||
var err error
|
||||
|
||||
if tempfile, err = os.CreateTemp("", ".LOGGINGTEST_*"); err != nil {
|
||||
t.Fatalf("error when creating temporary log file '%v': %v", tempfile.Name(), err.Error())
|
||||
}
|
||||
tempfilePath = tempfile.Name()
|
||||
// We can close the handler immediately; we don't need it since the FileLogger opens its own.
|
||||
if err = tempfile.Close(); err != nil {
|
||||
t.Fatalf("error when closing handler for temporary log file '%v': %v", tempfile.Name(), err.Error())
|
||||
}
|
||||
|
||||
l = &FileLogger{
|
||||
StdLogger: StdLogger{
|
||||
EnableDebug: true,
|
||||
Prefix: TestLogPrefix,
|
||||
LogFlags: logFlags,
|
||||
},
|
||||
Path: tempfilePath,
|
||||
}
|
||||
|
||||
if err = l.Setup(); err != nil {
|
||||
t.Fatalf("error when running Setup: %v", err.Error())
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed Setup. Logger: %#v", ltype, l)
|
||||
|
||||
if err = l.Alert(testAlert, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Crit(testCrit, ltype); err != nil {
|
||||
t.Fatalf("error for Crit: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Debug(testDebug, ltype); err != nil {
|
||||
t.Fatalf("error for Debug: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Emerg(testEmerg, ltype); err != nil {
|
||||
t.Fatalf("error for Emerg: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Err(testErr, ltype); err != nil {
|
||||
t.Fatalf("error for Err: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Info(testInfo, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Notice(testNotice, ltype); err != nil {
|
||||
t.Fatalf("error for Notice: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Warning(testWarning, ltype); err != nil {
|
||||
t.Fatalf("error for Warning: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix, err = l.GetPrefix(); err != nil {
|
||||
t.Fatalf("error when fetching prefix: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix != (TestLogPrefix + " ") { // StdLogger (and thus FileLogger) adds a space at the end.
|
||||
t.Fatalf("true prefix ('%v') does not match TestLogPrefix ('%v')", prefix, TestLogPrefix)
|
||||
}
|
||||
if err = l.SetPrefix(TestLogAltPrefix); err != nil {
|
||||
t.Fatalf("error when setting prefix to %v: %v", TestLogAltPrefix, err.Error())
|
||||
} else {
|
||||
_ = l.SetPrefix(TestLogPrefix)
|
||||
}
|
||||
|
||||
if err = l.DoDebug(false); err != nil {
|
||||
t.Fatalf("error when changing debug to false: %v", err.Error())
|
||||
} else if l.EnableDebug {
|
||||
t.Fatalf("did not properly set Debug filter state")
|
||||
} else {
|
||||
_ = l.DoDebug(true)
|
||||
}
|
||||
|
||||
if err = l.Shutdown(); err != nil {
|
||||
t.Fatalf("Error when running Shutdown: %v", err.Error())
|
||||
}
|
||||
|
||||
_, keepLog = os.LookupEnv(EnvVarKeepLog)
|
||||
|
||||
if !keepLog {
|
||||
if err = os.Remove(tempfilePath); err != nil {
|
||||
t.Fatalf("error when removing temporary log file '%v': %v", tempfilePath, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed all logging targets.", ltype)
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ func GetLogger(enableDebug bool, source string, eventIDs *WinEventID, logConfigF
|
||||
logger = &WinLogger{
|
||||
Prefix: source,
|
||||
EnableDebug: enableDebug,
|
||||
eids: eventIDs,
|
||||
EIDs: eventIDs,
|
||||
}
|
||||
} else {
|
||||
if logFlags.HasFlag(LogFile) {
|
||||
|
205
logging/funcs_windows_test.go
Normal file
205
logging/funcs_windows_test.go
Normal file
@ -0,0 +1,205 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
`fmt`
|
||||
`os`
|
||||
`testing`
|
||||
)
|
||||
|
||||
/*
|
||||
TestWinLogger tests functionality for WinLogger.
|
||||
You will probably need to run it with an Administrator shell.
|
||||
*/
|
||||
func TestWinLogger(t *testing.T) {
|
||||
|
||||
var l *WinLogger
|
||||
var ltype string = "WinLogger"
|
||||
var prefix string
|
||||
var exists bool
|
||||
var err error
|
||||
|
||||
l = &WinLogger{
|
||||
EnableDebug: true,
|
||||
Prefix: TestLogPrefix,
|
||||
RemoveOnClose: true,
|
||||
EIDs: DefaultEventID,
|
||||
}
|
||||
|
||||
if exists, err = l.Exists(); err != nil {
|
||||
t.Fatalf("error when checking for existence of registered Event Log source '%v': %v", TestLogPrefix, err.Error())
|
||||
} else {
|
||||
t.Logf("Prefix (source) '%v' exists before setup: %v", TestLogPrefix, exists)
|
||||
}
|
||||
|
||||
if err = l.Setup(); err != nil {
|
||||
t.Fatalf("error when running Setup: %v", err.Error())
|
||||
}
|
||||
|
||||
if exists, err = l.Exists(); err != nil {
|
||||
t.Fatalf("error when checking for existence of registered Event Log source '%v': %v", TestLogPrefix, err.Error())
|
||||
} else {
|
||||
t.Logf("Prefix (source) '%v' exists after setup: %v", TestLogPrefix, exists)
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed Setup. Logger: %#v", ltype, l)
|
||||
|
||||
if err = l.Alert(testAlert, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Crit(testCrit, ltype); err != nil {
|
||||
t.Fatalf("error for Crit: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Debug(testDebug, ltype); err != nil {
|
||||
t.Fatalf("error for Debug: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Emerg(testEmerg, ltype); err != nil {
|
||||
t.Fatalf("error for Emerg: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Err(testErr, ltype); err != nil {
|
||||
t.Fatalf("error for Err: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Info(testInfo, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Notice(testNotice, ltype); err != nil {
|
||||
t.Fatalf("error for Notice: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Warning(testWarning, ltype); err != nil {
|
||||
t.Fatalf("error for Warning: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix, err = l.GetPrefix(); err != nil {
|
||||
t.Fatalf("error when fetching prefix: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix != TestLogPrefix {
|
||||
t.Fatalf("true prefix ('%v') does not match TestLogPrefix ('%v')", prefix, TestLogPrefix)
|
||||
}
|
||||
if err = l.SetPrefix(TestLogAltPrefix); err != nil {
|
||||
t.Fatalf("error when setting prefix to %v: %v", TestLogAltPrefix, err.Error())
|
||||
} else {
|
||||
_ = l.SetPrefix(TestLogPrefix)
|
||||
}
|
||||
|
||||
if err = l.DoDebug(false); err != nil {
|
||||
t.Fatalf("error when changing debug to false: %v", err.Error())
|
||||
} else if l.EnableDebug {
|
||||
t.Fatalf("did not properly set Debug filter state")
|
||||
} else {
|
||||
_ = l.DoDebug(true)
|
||||
}
|
||||
|
||||
if err = l.Shutdown(); err != nil {
|
||||
t.Fatalf("Error when running Shutdown: %v", err.Error())
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed all logging targets.", ltype)
|
||||
}
|
||||
|
||||
// TestDefaultLogger tests GetLogger.
|
||||
func TestDefaultLogger(t *testing.T) {
|
||||
|
||||
var l Logger
|
||||
var tempfile *os.File
|
||||
var tempfilePath string
|
||||
var keepLog bool
|
||||
var ltype string
|
||||
var prefix string
|
||||
var testPrefix string
|
||||
var err error
|
||||
|
||||
if tempfile, err = os.CreateTemp("", ".LOGGINGTEST_*"); err != nil {
|
||||
t.Fatalf("error when creating temporary log file '%v': %v", tempfile.Name(), err.Error())
|
||||
}
|
||||
tempfilePath = tempfile.Name()
|
||||
// We can close the handler immediately; we don't need it since the FileLogger opens its own.
|
||||
if err = tempfile.Close(); err != nil {
|
||||
t.Fatalf("error when closing handler for temporary log file '%v': %v", tempfile.Name(), err.Error())
|
||||
}
|
||||
|
||||
if l, err = GetLogger(true, TestLogPrefix, DefaultEventID, logFlags, tempfilePath); err != nil {
|
||||
t.Fatalf("error when spawning default Windows logger via GetLogger: %v", err.Error())
|
||||
}
|
||||
|
||||
ltype = fmt.Sprintf("%T", l)
|
||||
|
||||
t.Logf("Logger %v passed Setup. Logger: %#v", ltype, l)
|
||||
|
||||
if err = l.Alert(testAlert, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Crit(testCrit, ltype); err != nil {
|
||||
t.Fatalf("error for Crit: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Debug(testDebug, ltype); err != nil {
|
||||
t.Fatalf("error for Debug: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Emerg(testEmerg, ltype); err != nil {
|
||||
t.Fatalf("error for Emerg: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Err(testErr, ltype); err != nil {
|
||||
t.Fatalf("error for Err: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Info(testInfo, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Notice(testNotice, ltype); err != nil {
|
||||
t.Fatalf("error for Notice: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Warning(testWarning, ltype); err != nil {
|
||||
t.Fatalf("error for Warning: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix, err = l.GetPrefix(); err != nil {
|
||||
t.Fatalf("error when fetching prefix: %v", err.Error())
|
||||
}
|
||||
|
||||
if ltype == "StdLogger" || ltype == "FileLogger" { // StdLogger (and thus FileLogger) adds a space at the end.
|
||||
testPrefix = TestLogPrefix + " "
|
||||
} else {
|
||||
testPrefix = TestLogPrefix
|
||||
}
|
||||
|
||||
if prefix != testPrefix {
|
||||
t.Fatalf("true prefix ('%v') does not match TestLogPrefix ('%v')", prefix, TestLogPrefix)
|
||||
}
|
||||
if err = l.SetPrefix(TestLogAltPrefix); err != nil {
|
||||
t.Fatalf("error when setting prefix to %v: %v", TestLogAltPrefix, err.Error())
|
||||
} else {
|
||||
_ = l.SetPrefix(TestLogPrefix)
|
||||
}
|
||||
|
||||
if err = l.DoDebug(false); err != nil {
|
||||
t.Fatalf("error when changing debug to false: %v", err.Error())
|
||||
} else {
|
||||
_ = l.DoDebug(true)
|
||||
}
|
||||
|
||||
if err = l.Shutdown(); err != nil {
|
||||
t.Fatalf("Error when running Shutdown: %v", err.Error())
|
||||
}
|
||||
|
||||
_, keepLog = os.LookupEnv(EnvVarKeepLog)
|
||||
|
||||
if !keepLog {
|
||||
if err = os.Remove(tempfilePath); err != nil {
|
||||
t.Fatalf("error when removing temporary log file '%v': %v", tempfilePath, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed all logging targets.", ltype)
|
||||
}
|
@ -29,14 +29,14 @@ func (l *WinLogger) Setup() (err error) {
|
||||
Since we use eventcreate, all Event IDs must be 1 <= eid <= 1000.
|
||||
*/
|
||||
for _, eid := range []uint32{
|
||||
l.eids.Alert,
|
||||
l.eids.Crit,
|
||||
l.eids.Debug,
|
||||
l.eids.Emerg,
|
||||
l.eids.Err,
|
||||
l.eids.Info,
|
||||
l.eids.Notice,
|
||||
l.eids.Warning,
|
||||
l.EIDs.Alert,
|
||||
l.EIDs.Crit,
|
||||
l.EIDs.Debug,
|
||||
l.EIDs.Emerg,
|
||||
l.EIDs.Err,
|
||||
l.EIDs.Info,
|
||||
l.EIDs.Notice,
|
||||
l.EIDs.Warning,
|
||||
} {
|
||||
if !((eid <= EIDMax) && (EIDMin <= eid)) {
|
||||
err = ErrBadEid
|
||||
@ -204,7 +204,7 @@ func (l *WinLogger) Alert(s string, v ...interface{}) (err error) {
|
||||
}
|
||||
|
||||
// Treat ALERT as Warning
|
||||
err = l.elog.Warning(l.eids.Alert, msg)
|
||||
err = l.elog.Warning(l.EIDs.Alert, msg)
|
||||
|
||||
return
|
||||
}
|
||||
@ -221,7 +221,7 @@ func (l *WinLogger) Crit(s string, v ...interface{}) (err error) {
|
||||
}
|
||||
|
||||
// Treat CRIT as Error
|
||||
err = l.elog.Error(l.eids.Crit, msg)
|
||||
err = l.elog.Error(l.EIDs.Crit, msg)
|
||||
|
||||
return
|
||||
}
|
||||
@ -242,7 +242,7 @@ func (l *WinLogger) Debug(s string, v ...interface{}) (err error) {
|
||||
}
|
||||
|
||||
// Treat DEBUG as Info
|
||||
err = l.elog.Info(l.eids.Debug, msg)
|
||||
err = l.elog.Info(l.EIDs.Debug, msg)
|
||||
|
||||
return
|
||||
|
||||
@ -260,7 +260,7 @@ func (l *WinLogger) Emerg(s string, v ...interface{}) (err error) {
|
||||
}
|
||||
|
||||
// Treat EMERG as Error
|
||||
err = l.elog.Error(l.eids.Emerg, msg)
|
||||
err = l.elog.Error(l.EIDs.Emerg, msg)
|
||||
|
||||
return
|
||||
|
||||
@ -277,7 +277,7 @@ func (l *WinLogger) Err(s string, v ...interface{}) (err error) {
|
||||
msg = s
|
||||
}
|
||||
|
||||
err = l.elog.Error(l.eids.Err, msg)
|
||||
err = l.elog.Error(l.EIDs.Err, msg)
|
||||
|
||||
return
|
||||
|
||||
@ -294,7 +294,7 @@ func (l *WinLogger) Info(s string, v ...interface{}) (err error) {
|
||||
msg = s
|
||||
}
|
||||
|
||||
err = l.elog.Info(l.eids.Info, msg)
|
||||
err = l.elog.Info(l.EIDs.Info, msg)
|
||||
|
||||
return
|
||||
|
||||
@ -312,7 +312,7 @@ func (l *WinLogger) Notice(s string, v ...interface{}) (err error) {
|
||||
}
|
||||
|
||||
// Treat NOTICE as Info
|
||||
err = l.elog.Info(l.eids.Notice, msg)
|
||||
err = l.elog.Info(l.EIDs.Notice, msg)
|
||||
|
||||
return
|
||||
|
||||
@ -329,7 +329,7 @@ func (l *WinLogger) Warning(s string, v ...interface{}) (err error) {
|
||||
msg = s
|
||||
}
|
||||
|
||||
err = l.elog.Warning(l.eids.Warning, msg)
|
||||
err = l.elog.Warning(l.EIDs.Warning, msg)
|
||||
|
||||
return
|
||||
|
||||
|
121
logging/muiltilogger_linux_test.go
Normal file
121
logging/muiltilogger_linux_test.go
Normal file
@ -0,0 +1,121 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
`os`
|
||||
`testing`
|
||||
)
|
||||
|
||||
// TestMultiLogger tests GetMultiLogger and MultiLogger methods.
|
||||
func TestMultiLogger(t *testing.T) {
|
||||
|
||||
var l *MultiLogger
|
||||
var tempfile *os.File
|
||||
var tempfilePath string
|
||||
var keepLog bool
|
||||
var ltype string = "MultiLogger"
|
||||
var prefix string
|
||||
var testPrefix string
|
||||
var err error
|
||||
|
||||
if tempfile, err = os.CreateTemp("", ".LOGGINGTEST_*"); err != nil {
|
||||
t.Fatalf("error when creating temporary log file '%v': %v", tempfile.Name(), err.Error())
|
||||
}
|
||||
tempfilePath = tempfile.Name()
|
||||
// We can close the handler immediately; we don't need it since the FileLogger opens its own.
|
||||
if err = tempfile.Close(); err != nil {
|
||||
t.Fatalf("error when closing handler for temporary log file '%v': %v", tempfile.Name(), err.Error())
|
||||
}
|
||||
|
||||
l = GetMultiLogger(true, TestLogPrefix)
|
||||
|
||||
if err = l.AddStdLogger("StdLogger", false, true, logFlags); err != nil {
|
||||
t.Fatalf("error when adding StdLogger to MultiLogger: %v", err.Error())
|
||||
}
|
||||
if err = l.AddFileLogger("FileLogger", logFlags, tempfilePath); err != nil {
|
||||
t.Fatalf("error when adding FileLogger to MultiLogger: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.AddDefaultLogger("DefaultLogger", logFlags, tempfilePath); err != nil {
|
||||
t.Fatalf("error when adding default logger to MultiLogger: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.AddSysdLogger("SystemDLogger"); err != nil {
|
||||
t.Fatalf("error when adding SystemDLogger to MultiLogger: %v", err.Error())
|
||||
}
|
||||
if err = l.AddSyslogLogger("SyslogLogger"); err != nil {
|
||||
t.Fatalf("error when adding SyslogLogger to MultiLogger: %v", err.Error())
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed Setup. Logger: %#v", ltype, l)
|
||||
|
||||
if err = l.Alert(testAlert, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Crit(testCrit, ltype); err != nil {
|
||||
t.Fatalf("error for Crit: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Debug(testDebug, ltype); err != nil {
|
||||
t.Fatalf("error for Debug: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Emerg(testEmerg, ltype); err != nil {
|
||||
t.Fatalf("error for Emerg: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Err(testErr, ltype); err != nil {
|
||||
t.Fatalf("error for Err: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Info(testInfo, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Notice(testNotice, ltype); err != nil {
|
||||
t.Fatalf("error for Notice: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Warning(testWarning, ltype); err != nil {
|
||||
t.Fatalf("error for Warning: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix, err = l.GetPrefix(); err != nil {
|
||||
t.Fatalf("error when fetching prefix: %v", err.Error())
|
||||
}
|
||||
|
||||
if ltype == "StdLogger" || ltype == "FileLogger" { // StdLogger (and thus FileLogger) adds a space at the end.
|
||||
testPrefix = TestLogPrefix + " "
|
||||
} else {
|
||||
testPrefix = TestLogPrefix
|
||||
}
|
||||
|
||||
if prefix != testPrefix {
|
||||
t.Fatalf("true prefix ('%v') does not match TestLogPrefix ('%v')", prefix, TestLogPrefix)
|
||||
}
|
||||
if err = l.SetPrefix(TestLogAltPrefix); err != nil {
|
||||
t.Fatalf("error when setting prefix to %v: %v", TestLogAltPrefix, err.Error())
|
||||
} else {
|
||||
_ = l.SetPrefix(TestLogPrefix)
|
||||
}
|
||||
|
||||
if err = l.DoDebug(false); err != nil {
|
||||
t.Fatalf("error when changing debug to false: %v", err.Error())
|
||||
} else {
|
||||
_ = l.DoDebug(true)
|
||||
}
|
||||
|
||||
if err = l.Shutdown(); err != nil {
|
||||
t.Fatalf("Error when running Shutdown: %v", err.Error())
|
||||
}
|
||||
|
||||
_, keepLog = os.LookupEnv(EnvVarKeepLog)
|
||||
|
||||
if !keepLog {
|
||||
if err = os.Remove(tempfilePath); err != nil {
|
||||
t.Fatalf("error when removing temporary log file '%v': %v", tempfilePath, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed all logging targets.", ltype)
|
||||
}
|
118
logging/multilogger_windows_test.go
Normal file
118
logging/multilogger_windows_test.go
Normal file
@ -0,0 +1,118 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
`os`
|
||||
`testing`
|
||||
)
|
||||
|
||||
// TestMultiLogger tests GetMultiLogger and MultiLogger methods.
|
||||
func TestMultiLogger(t *testing.T) {
|
||||
|
||||
var l *MultiLogger
|
||||
var tempfile *os.File
|
||||
var tempfilePath string
|
||||
var keepLog bool
|
||||
var ltype string = "MultiLogger"
|
||||
var prefix string
|
||||
var testPrefix string
|
||||
var err error
|
||||
|
||||
if tempfile, err = os.CreateTemp("", ".LOGGINGTEST_*"); err != nil {
|
||||
t.Fatalf("error when creating temporary log file '%v': %v", tempfile.Name(), err.Error())
|
||||
}
|
||||
tempfilePath = tempfile.Name()
|
||||
// We can close the handler immediately; we don't need it since the FileLogger opens its own.
|
||||
if err = tempfile.Close(); err != nil {
|
||||
t.Fatalf("error when closing handler for temporary log file '%v': %v", tempfile.Name(), err.Error())
|
||||
}
|
||||
|
||||
l = GetMultiLogger(true, TestLogPrefix)
|
||||
|
||||
if err = l.AddStdLogger("StdLogger", false, true, logFlags); err != nil {
|
||||
t.Fatalf("error when adding StdLogger to MultiLogger: %v", err.Error())
|
||||
}
|
||||
if err = l.AddFileLogger("FileLogger", logFlags, tempfilePath); err != nil {
|
||||
t.Fatalf("error when adding FileLogger to MultiLogger: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.AddDefaultLogger("DefaultLogger", DefaultEventID, logFlags, tempfilePath); err != nil {
|
||||
t.Fatalf("error when adding default logger to MultiLogger: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.AddWinLogger("WinLogger", DefaultEventID); err != nil {
|
||||
t.Fatalf("error when adding WinLogger to MultiLogger: %v", err.Error())
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed Setup. Logger: %#v", ltype, l)
|
||||
|
||||
if err = l.Alert(testAlert, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Crit(testCrit, ltype); err != nil {
|
||||
t.Fatalf("error for Crit: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Debug(testDebug, ltype); err != nil {
|
||||
t.Fatalf("error for Debug: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Emerg(testEmerg, ltype); err != nil {
|
||||
t.Fatalf("error for Emerg: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Err(testErr, ltype); err != nil {
|
||||
t.Fatalf("error for Err: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Info(testInfo, ltype); err != nil {
|
||||
t.Fatalf("error for Alert: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Notice(testNotice, ltype); err != nil {
|
||||
t.Fatalf("error for Notice: %v", err.Error())
|
||||
}
|
||||
|
||||
if err = l.Warning(testWarning, ltype); err != nil {
|
||||
t.Fatalf("error for Warning: %v", err.Error())
|
||||
}
|
||||
|
||||
if prefix, err = l.GetPrefix(); err != nil {
|
||||
t.Fatalf("error when fetching prefix: %v", err.Error())
|
||||
}
|
||||
|
||||
if ltype == "StdLogger" || ltype == "FileLogger" { // StdLogger (and thus FileLogger) adds a space at the end.
|
||||
testPrefix = TestLogPrefix + " "
|
||||
} else {
|
||||
testPrefix = TestLogPrefix
|
||||
}
|
||||
|
||||
if prefix != testPrefix {
|
||||
t.Fatalf("true prefix ('%v') does not match TestLogPrefix ('%v')", prefix, TestLogPrefix)
|
||||
}
|
||||
if err = l.SetPrefix(TestLogAltPrefix); err != nil {
|
||||
t.Fatalf("error when setting prefix to %v: %v", TestLogAltPrefix, err.Error())
|
||||
} else {
|
||||
_ = l.SetPrefix(TestLogPrefix)
|
||||
}
|
||||
|
||||
if err = l.DoDebug(false); err != nil {
|
||||
t.Fatalf("error when changing debug to false: %v", err.Error())
|
||||
} else {
|
||||
_ = l.DoDebug(true)
|
||||
}
|
||||
|
||||
if err = l.Shutdown(); err != nil {
|
||||
t.Fatalf("Error when running Shutdown: %v", err.Error())
|
||||
}
|
||||
|
||||
_, keepLog = os.LookupEnv(EnvVarKeepLog)
|
||||
|
||||
if !keepLog {
|
||||
if err = os.Remove(tempfilePath); err != nil {
|
||||
t.Fatalf("error when removing temporary log file '%v': %v", tempfilePath, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Logger %v passed all logging targets.", ltype)
|
||||
}
|
@ -48,6 +48,26 @@ type StdLogger struct {
|
||||
You will need to run *StdLogger.Shutdown and then *StdLogger.Setup again if you wish to change this.
|
||||
*/
|
||||
LogFlags int
|
||||
/*
|
||||
EnableStdOut is true if the log will send to STDOUT.
|
||||
If false (default), no output will be written to STDOUT.
|
||||
You will need to run StdLogger.Shutdown and then StdLogger.Setup again if you wish to change this.
|
||||
|
||||
If EnableStdOut is false and EnableStdErr is false, no logging output will occur by default
|
||||
and StdLogger.Logger will be largely useless.
|
||||
It will be up to you to modify the underlying log.Logger to behave as you want.
|
||||
*/
|
||||
EnableStdOut bool
|
||||
/*
|
||||
EnableStdErr is true if the log will send to STDERR.
|
||||
If false (default), no output will be written to STDERR.
|
||||
You will need to run StdLogger.Shutdown and then StdLogger.Setup again if you wish to change this.
|
||||
|
||||
If EnableStdErr is false and EnableStdOut is false, no logging output will occur by default
|
||||
and StdLogger.Logger will be largely useless.
|
||||
It will be up to you to modify the underlying log.Logger to behave as you want.
|
||||
*/
|
||||
EnableStdErr bool
|
||||
}
|
||||
|
||||
/*
|
||||
@ -62,18 +82,6 @@ type FileLogger struct {
|
||||
StdLogger
|
||||
// Path is the path to the logfile.
|
||||
Path string
|
||||
/*
|
||||
EnableStdOut is true if the log will send to STDOUT as well as the file (and STDERR if FileLogger.EnableStdErr == true).
|
||||
If false (default), it will only (silently) write to the log file.
|
||||
You will need to run FileLogger.Shutdown and then FileLogger.Setup again if you wish to change this.
|
||||
*/
|
||||
EnableStdOut bool
|
||||
/*
|
||||
EnableStdErr is true if the log will send to STDERR as well as the file (and STDOUT if FileLogger.EnableStdOut == true).
|
||||
If false (default), it will only (silently) write to the log file.
|
||||
You will need to run *FileLogger.Shutdown and then *FileLogger.Setup again if you wish to change this.
|
||||
*/
|
||||
EnableStdErr bool
|
||||
// writer is used for the writing out of the log file.
|
||||
writer *os.File
|
||||
}
|
||||
|
@ -4,11 +4,15 @@ import (
|
||||
`log/syslog`
|
||||
)
|
||||
|
||||
/*
|
||||
SystemDLogger (yes, I'm aware it's actually written as "systemd") writes to journald on systemd-enabled systems.
|
||||
*/
|
||||
type SystemDLogger struct {
|
||||
EnableDebug bool
|
||||
Prefix string
|
||||
}
|
||||
|
||||
// SyslogLogger writes to syslog on syslog-enabled systems.
|
||||