Windows Event Log, error output
Adding more Event Log support, and modifying the loggers so they return errors in their operational functions.
This commit is contained in:
parent
3d0d420454
commit
39e0a1fd43
4
.gitignore
vendored
4
.gitignore
vendored
@ -28,6 +28,10 @@
|
|||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
# But DO include the actual tests.
|
||||||
|
!_test.go
|
||||||
|
!*_test.go
|
||||||
|
!*_test/
|
||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
*.out
|
*.out
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
https://stackoverflow.com/a/24809646
|
https://stackoverflow.com/a/24809646
|
||||||
https://golang.org/pkg/runtime/#Caller
|
https://golang.org/pkg/runtime/#Caller
|
||||||
|
|
||||||
- Support simultaneous writing to multiple Loggers.
|
|
||||||
|
|
||||||
- Suport remote loggers? (eventlog, syslog, systemd)
|
- Suport remote loggers? (eventlog, syslog, systemd)
|
||||||
|
|
||||||
- DOCS.
|
- DOCS.
|
||||||
|
-- Done, but flesh out.
|
||||||
|
|
||||||
- Unit/Integration tests.
|
- Unit/Integration tests.
|
||||||
|
@ -3,7 +3,6 @@ package logging
|
|||||||
import (
|
import (
|
||||||
`os`
|
`os`
|
||||||
`path/filepath`
|
`path/filepath`
|
||||||
`regexp`
|
|
||||||
|
|
||||||
`r00t2.io/goutils/bitmask`
|
`r00t2.io/goutils/bitmask`
|
||||||
)
|
)
|
||||||
@ -28,8 +27,21 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// ptrnSourceExists is a regex pattern to check for a registry entry (Event Log entry) already existing.
|
/*
|
||||||
var ptrnSourceExists *regexp.Regexp = regexp.MustCompile(`registry\skey\salready\sexists$`)
|
ptrnSourceExists is a regex pattern to check for a registry entry (Event Log entry) already existing.
|
||||||
|
|
||||||
|
Deprecated: this is handled differently now.
|
||||||
|
*/
|
||||||
|
// var ptrnSourceExists *regexp.Regexp = regexp.MustCompile(`registry\skey\salready\sexists$`)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EIDMin uint32 = 1
|
||||||
|
EIDMax uint32 = 1000
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
eventLogRegistryKey string = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application"
|
||||||
|
)
|
||||||
|
|
||||||
// Default WinEventID, (can be) used in GetLogger and MultiLogger.AddWinLogger.
|
// Default WinEventID, (can be) used in GetLogger and MultiLogger.AddWinLogger.
|
||||||
var DefaultEventID *WinEventID = &WinEventID{
|
var DefaultEventID *WinEventID = &WinEventID{
|
||||||
|
12
logging/errs_windows.go
Normal file
12
logging/errs_windows.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package logging
|
||||||
|
|
||||||
|
import (
|
||||||
|
`errors`
|
||||||
|
`fmt`
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
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))
|
||||||
|
)
|
@ -1,61 +1,96 @@
|
|||||||
package logging
|
package logging
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
`errors`
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
`io/fs`
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
`strings`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Setup sets up/configures a FileLogger and prepares it for use.
|
// Setup sets up/configures a FileLogger and prepares it for use.
|
||||||
func (l *FileLogger) Setup() {
|
func (l *FileLogger) Setup() (err error) {
|
||||||
|
|
||||||
var err error
|
|
||||||
var multi io.Writer
|
var multi io.Writer
|
||||||
|
|
||||||
l.Logger = log.Default()
|
// This uses a shared handle across the import. We don't want that.
|
||||||
l.Logger.SetPrefix(l.Prefix + " ")
|
// l.Logger = log.Default()
|
||||||
if l.writer, err = os.OpenFile(l.Path, appendFlags, logPerm); err != nil {
|
if l.Prefix != "" {
|
||||||
log.Panicf("could not open log file \"%v\" for writing: %v\n", l.Path, err)
|
l.Prefix = strings.TrimRight(l.Prefix, " ") + " "
|
||||||
|
// l.Logger.SetPrefix(l.Prefix)
|
||||||
}
|
}
|
||||||
|
if l.writer, err = os.OpenFile(l.Path, appendFlags, logPerm); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// https://stackoverflow.com/a/36719588/733214
|
// https://stackoverflow.com/a/36719588/733214
|
||||||
if l.EnableStdOut {
|
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)
|
multi = io.MultiWriter(os.Stdout, l.writer)
|
||||||
} else {
|
default:
|
||||||
multi = l.writer
|
multi = l.writer
|
||||||
}
|
}
|
||||||
l.Logger.SetOutput(multi)
|
|
||||||
|
l.Logger = log.New(multi, l.Prefix, l.LogFlags)
|
||||||
|
// l.Logger.SetOutput(multi)
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown cleanly shuts down a FileLogger.
|
// Shutdown cleanly shuts down a FileLogger.
|
||||||
func (l *FileLogger) Shutdown() {
|
func (l *FileLogger) Shutdown() (err error) {
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if err = l.writer.Close(); err != nil {
|
if err = l.writer.Close(); err != nil {
|
||||||
log.Panicf("could not close log file \"%v\": %v\n", l.Path, err)
|
if !errors.Is(err, fs.ErrClosed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPrefix returns the prefix used by this FileLogger.
|
/*
|
||||||
func (l *FileLogger) GetPrefix() string {
|
GetPrefix returns the prefix used by this FileLogger.
|
||||||
return l.Prefix
|
err will always be nil; it's there for interface-compat.
|
||||||
|
*/
|
||||||
|
func (l *FileLogger) GetPrefix() (prefix string, err error) {
|
||||||
|
|
||||||
|
prefix = l.Prefix
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
DoDebug sets the debug state of this FileLogger.
|
DoDebug sets the debug state of this FileLogger.
|
||||||
Note that this merely acts as a *safety filter* for debug messages to avoid sensitive information being written to the log.
|
Note that this merely acts as a *safety filter* for debug messages to avoid sensitive information being written to the log.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
*/
|
*/
|
||||||
func (l *FileLogger) DoDebug(d bool) {
|
func (l *FileLogger) DoDebug(d bool) (err error) {
|
||||||
|
|
||||||
l.EnableDebug = d
|
l.EnableDebug = d
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPrefix sets the prefix for this FileLogger.
|
/*
|
||||||
func (l *FileLogger) SetPrefix(prefix string) {
|
SetPrefix sets the prefix for this FileLogger.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
|
*/
|
||||||
|
func (l *FileLogger) SetPrefix(prefix string) (err error) {
|
||||||
|
|
||||||
l.Prefix = prefix + " "
|
l.Prefix = prefix
|
||||||
l.Logger.SetPrefix(prefix + " ")
|
if prefix != "" {
|
||||||
|
l.Prefix = strings.TrimRight(l.Prefix, " ") + " "
|
||||||
|
}
|
||||||
|
l.Logger.SetPrefix(l.Prefix)
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alert writes an ALERT-level message to this FileLogger.
|
// Alert writes an ALERT-level message to this FileLogger.
|
||||||
|
@ -24,6 +24,9 @@ var (
|
|||||||
If prefix is "\x00" (a null byte), then the default logging prefix will be used. If anything else, even an empty string,
|
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.
|
is specified then that will be used instead for the prefix.
|
||||||
|
|
||||||
|
logConfigFlags is the corresponding flag(s) OR'd for StdLogger.LogFlags / FileLogger.StdLogger.LogFlags if either is selected. See StdLogger.LogFlags and
|
||||||
|
https://pkg.go.dev/log#pkg-constants for details.
|
||||||
|
|
||||||
logPaths is an (optional) list of strings to use as paths to test for writing. If the file can be created/written to,
|
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.
|
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.
|
||||||
If you want to log to multiple files simultaneously, use a MultiLogger instead.
|
If you want to log to multiple files simultaneously, use a MultiLogger instead.
|
||||||
@ -32,10 +35,11 @@ var (
|
|||||||
If you want to log to multiple Logger destinations at once (or want to log to an explicit Logger type),
|
If you want to log to multiple Logger destinations at once (or want to log to an explicit Logger type),
|
||||||
use GetMultiLogger.
|
use GetMultiLogger.
|
||||||
*/
|
*/
|
||||||
func GetLogger(enableDebug bool, prefix string, logPaths ...string) (logger Logger, err error) {
|
func GetLogger(enableDebug bool, prefix string, logConfigFlags int, logPaths ...string) (logger Logger, err error) {
|
||||||
|
|
||||||
var logPath string
|
var logPath string
|
||||||
var logFlags bitmask.MaskBit
|
var logFlags bitmask.MaskBit
|
||||||
|
var currentPrefix string
|
||||||
|
|
||||||
// Configure system-supported logger(s).
|
// Configure system-supported logger(s).
|
||||||
if sysd.Enabled() {
|
if sysd.Enabled() {
|
||||||
@ -109,6 +113,7 @@ func GetLogger(enableDebug bool, prefix string, logPaths ...string) (logger Logg
|
|||||||
StdLogger: StdLogger{
|
StdLogger: StdLogger{
|
||||||
Prefix: logPrefix,
|
Prefix: logPrefix,
|
||||||
EnableDebug: enableDebug,
|
EnableDebug: enableDebug,
|
||||||
|
LogFlags: logConfigFlags,
|
||||||
},
|
},
|
||||||
Path: logPath,
|
Path: logPath,
|
||||||
}
|
}
|
||||||
@ -116,17 +121,26 @@ func GetLogger(enableDebug bool, prefix string, logPaths ...string) (logger Logg
|
|||||||
logger = &StdLogger{
|
logger = &StdLogger{
|
||||||
Prefix: logPrefix,
|
Prefix: logPrefix,
|
||||||
EnableDebug: enableDebug,
|
EnableDebug: enableDebug,
|
||||||
|
LogFlags: logConfigFlags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Setup()
|
|
||||||
if prefix != "\x00" {
|
if prefix != "\x00" {
|
||||||
logger.SetPrefix(prefix)
|
if err = logger.SetPrefix(prefix); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = logger.Setup(); err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("logger initialized of type %T with prefix %v", logger, logger.GetPrefix())
|
if currentPrefix, err = logger.GetPrefix(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debug("logger initialized of type %T with prefix %v", logger, currentPrefix)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -7,41 +7,70 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Setup sets up/configures a MultiLogger (and all its MultiLogger.Loggers) and prepares it for use.
|
// Setup sets up/configures a MultiLogger (and all its MultiLogger.Loggers) and prepares it for use.
|
||||||
func (m *MultiLogger) Setup() {
|
func (m *MultiLogger) Setup() (err error) {
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
var errs *multierr.MultiError = multierr.NewMultiError(nil)
|
||||||
|
|
||||||
for _, l := range m.Loggers {
|
for _, l := range m.Loggers {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
var err2 error
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
l.Setup()
|
if err2 = l.Setup(); err2 != nil {
|
||||||
|
errs.AddError(err2)
|
||||||
|
err2 = nil
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
|
if errs.Count() > 0 {
|
||||||
|
err = errs
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown cleanly shuts down a MultiLogger (and all its MultiLogger.Loggers).
|
// Shutdown cleanly shuts down a MultiLogger (and all its MultiLogger.Loggers).
|
||||||
func (m *MultiLogger) Shutdown() {
|
func (m *MultiLogger) Shutdown() (err error) {
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
var errs *multierr.MultiError = multierr.NewMultiError(nil)
|
||||||
|
|
||||||
for _, l := range m.Loggers {
|
for _, l := range m.Loggers {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
var err2 error
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
l.Shutdown()
|
if err2 = l.Shutdown(); err2 != nil {
|
||||||
|
errs.AddError(err2)
|
||||||
|
err2 = nil
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
|
if errs.Count() > 0 {
|
||||||
|
err = errs
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPrefix returns the prefix used by this MultiLogger (and all its MultiLogger.Loggers).
|
/*
|
||||||
func (m *MultiLogger) GetPrefix() string {
|
GetPrefix returns the prefix used by this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
|
*/
|
||||||
|
func (m *MultiLogger) GetPrefix() (prefix string, err error) {
|
||||||
|
|
||||||
return m.Prefix
|
prefix = m.Prefix
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,21 +80,33 @@ func (m *MultiLogger) GetPrefix() string {
|
|||||||
|
|
||||||
If you had a logger-specific EnableDebug set, you will need to re-set it to your desired state after running this method.
|
If you had a logger-specific EnableDebug set, you will need to re-set it to your desired state after running this method.
|
||||||
*/
|
*/
|
||||||
func (m *MultiLogger) DoDebug(d bool) {
|
func (m *MultiLogger) DoDebug(d bool) (err error) {
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
var errs *multierr.MultiError = multierr.NewMultiError(nil)
|
||||||
|
|
||||||
m.EnableDebug = d
|
m.EnableDebug = d
|
||||||
|
|
||||||
for _, l := range m.Loggers {
|
for _, l := range m.Loggers {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
var err2 error
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
l.DoDebug(d)
|
if err2 = l.DoDebug(d); err2 != nil {
|
||||||
|
errs.AddError(err2)
|
||||||
|
err2 = nil
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
|
if errs.Count() > 0 {
|
||||||
|
err = errs
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -73,21 +114,33 @@ func (m *MultiLogger) DoDebug(d bool) {
|
|||||||
|
|
||||||
If you had a logger-specific Prefix set, you will need to re-set it to your desired prefix after running this method.
|
If you had a logger-specific Prefix set, you will need to re-set it to your desired prefix after running this method.
|
||||||
*/
|
*/
|
||||||
func (m *MultiLogger) SetPrefix(prefix string) {
|
func (m *MultiLogger) SetPrefix(prefix string) (err error) {
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
var errs *multierr.MultiError = multierr.NewMultiError(nil)
|
||||||
|
|
||||||
m.Prefix = prefix
|
m.Prefix = prefix
|
||||||
|
|
||||||
for _, l := range m.Loggers {
|
for _, l := range m.Loggers {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
var err2 error
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
l.SetPrefix(prefix)
|
if err2 = l.SetPrefix(prefix); err != nil {
|
||||||
|
errs.AddError(err2)
|
||||||
|
err2 = nil
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
|
if errs.Count() > 0 {
|
||||||
|
err = errs
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alert writes an ALERT-level message to this MultiLogger (and all its MultiLogger.Loggers).
|
// Alert writes an ALERT-level message to this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
@ -100,16 +153,11 @@ func (m *MultiLogger) Alert(s string, v ...interface{}) (err error) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if rplc != nil {
|
if err = logObj.Alert(msg, rplc...); err != nil {
|
||||||
err = logObj.Alert(msg, rplc...)
|
|
||||||
} else {
|
|
||||||
err = logObj.Alert(msg)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
e.AddError(err)
|
e.AddError(err)
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
}(l, s, v)
|
}(l, s, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@ -131,16 +179,11 @@ func (m *MultiLogger) Crit(s string, v ...interface{}) (err error) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if rplc != nil {
|
if err = logObj.Crit(msg, rplc...); err != nil {
|
||||||
err = logObj.Crit(msg, rplc...)
|
|
||||||
} else {
|
|
||||||
err = logObj.Crit(msg)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
e.AddError(err)
|
e.AddError(err)
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
}(l, s, v)
|
}(l, s, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@ -162,16 +205,11 @@ func (m *MultiLogger) Debug(s string, v ...interface{}) (err error) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if rplc != nil {
|
if err = logObj.Debug(msg, rplc...); err != nil {
|
||||||
err = logObj.Debug(msg, rplc...)
|
|
||||||
} else {
|
|
||||||
err = logObj.Debug(msg)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
e.AddError(err)
|
e.AddError(err)
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
}(l, s, v)
|
}(l, s, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@ -192,16 +230,11 @@ func (m *MultiLogger) Emerg(s string, v ...interface{}) (err error) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if rplc != nil {
|
if err = logObj.Emerg(msg, rplc...); err != nil {
|
||||||
err = logObj.Emerg(msg, rplc...)
|
|
||||||
} else {
|
|
||||||
err = logObj.Emerg(msg)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
e.AddError(err)
|
e.AddError(err)
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
}(l, s, v)
|
}(l, s, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@ -222,16 +255,11 @@ func (m *MultiLogger) Err(s string, v ...interface{}) (err error) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if rplc != nil {
|
if err = logObj.Err(msg, rplc...); err != nil {
|
||||||
err = logObj.Err(msg, rplc...)
|
|
||||||
} else {
|
|
||||||
err = logObj.Err(msg)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
e.AddError(err)
|
e.AddError(err)
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
}(l, s, v)
|
}(l, s, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@ -253,16 +281,11 @@ func (m *MultiLogger) Info(s string, v ...interface{}) (err error) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if rplc != nil {
|
if err = logObj.Info(msg, rplc...); err != nil {
|
||||||
err = logObj.Info(msg, rplc...)
|
|
||||||
} else {
|
|
||||||
err = logObj.Info(msg)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
e.AddError(err)
|
e.AddError(err)
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
}(l, s, v)
|
}(l, s, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@ -284,16 +307,11 @@ func (m *MultiLogger) Notice(s string, v ...interface{}) (err error) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if rplc != nil {
|
if err = logObj.Notice(msg, rplc...); err != nil {
|
||||||
err = logObj.Notice(msg, rplc...)
|
|
||||||
} else {
|
|
||||||
err = logObj.Notice(msg)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
e.AddError(err)
|
e.AddError(err)
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
}(l, s, v)
|
}(l, s, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@ -315,16 +333,11 @@ func (m *MultiLogger) Warning(s string, v ...interface{}) (err error) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(logObj Logger, msg string, rplc ...interface{}) {
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if rplc != nil {
|
if err = logObj.Warning(msg, rplc...); err != nil {
|
||||||
err = logObj.Warning(msg, rplc...)
|
|
||||||
} else {
|
|
||||||
err = logObj.Warning(msg)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
e.AddError(err)
|
e.AddError(err)
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
}(l, s, v)
|
}(l, s, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
@ -21,7 +21,7 @@ func GetMultiLogger(enableDebug bool, prefix string) (m *MultiLogger) {
|
|||||||
|
|
||||||
m = &MultiLogger{
|
m = &MultiLogger{
|
||||||
EnableDebug: enableDebug,
|
EnableDebug: enableDebug,
|
||||||
Prefix: "",
|
Prefix: logPrefix,
|
||||||
Loggers: make(map[string]Logger),
|
Loggers: make(map[string]Logger),
|
||||||
}
|
}
|
||||||
if prefix != "\x00" {
|
if prefix != "\x00" {
|
||||||
@ -36,10 +36,13 @@ func GetMultiLogger(enableDebug bool, prefix string) (m *MultiLogger) {
|
|||||||
|
|
||||||
identifier is a string to use to identify the added StdLogger in MultiLogger.Loggers.
|
identifier is a string to use to identify the added StdLogger in MultiLogger.Loggers.
|
||||||
If empty, one will be automatically generated.
|
If empty, one will be automatically generated.
|
||||||
|
|
||||||
|
See GetLogger's logConfigFlags argument and StdLogger.LogFlags for details on logFlags.
|
||||||
*/
|
*/
|
||||||
func (m *MultiLogger) AddStdLogger(identifier string) (err error) {
|
func (m *MultiLogger) AddStdLogger(identifier string, logFlags int) (err error) {
|
||||||
|
|
||||||
var exists bool
|
var exists bool
|
||||||
|
var prefix string
|
||||||
|
|
||||||
if identifier == "" {
|
if identifier == "" {
|
||||||
identifier = uuid.New().String()
|
identifier = uuid.New().String()
|
||||||
@ -54,10 +57,17 @@ func (m *MultiLogger) AddStdLogger(identifier string) (err error) {
|
|||||||
Logger: nil,
|
Logger: nil,
|
||||||
EnableDebug: m.EnableDebug,
|
EnableDebug: m.EnableDebug,
|
||||||
Prefix: m.Prefix,
|
Prefix: m.Prefix,
|
||||||
|
LogFlags: logFlags,
|
||||||
|
}
|
||||||
|
if err = m.Loggers[identifier].Setup(); err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
m.Loggers[identifier].Setup()
|
|
||||||
|
|
||||||
m.Loggers[identifier].Info("logger initialized of type %T with prefix %v", m.Loggers[identifier], m.Loggers[identifier].GetPrefix())
|
if prefix, err = m.Loggers[identifier].GetPrefix(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Loggers[identifier].Debug("logger initialized of type %T with prefix %v", m.Loggers[identifier], prefix)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -70,11 +80,12 @@ func (m *MultiLogger) AddStdLogger(identifier string) (err error) {
|
|||||||
|
|
||||||
logfilePath is a string for the path to the desired logfile.
|
logfilePath is a string for the path to the desired logfile.
|
||||||
*/
|
*/
|
||||||
func (m *MultiLogger) AddFileLogger(identifier, logfilePath string) (err error) {
|
func (m *MultiLogger) AddFileLogger(identifier string, enableStdOut, enableStdErr bool, logFlags int, logfilePath string) (err error) {
|
||||||
|
|
||||||
var exists bool
|
var exists bool
|
||||||
var success bool
|
var success bool
|
||||||
var dirPath string
|
var dirPath string
|
||||||
|
var prefix string
|
||||||
|
|
||||||
if identifier == "" {
|
if identifier == "" {
|
||||||
identifier = uuid.New().String()
|
identifier = uuid.New().String()
|
||||||
@ -85,7 +96,9 @@ func (m *MultiLogger) AddFileLogger(identifier, logfilePath string) (err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists, _ = paths.RealPathExists(&logfilePath); !exists {
|
if exists, err = paths.RealPathExists(&logfilePath); err != nil {
|
||||||
|
return
|
||||||
|
} else if !exists {
|
||||||
if success, err = testOpen(logfilePath); err != nil {
|
if success, err = testOpen(logfilePath); err != nil {
|
||||||
return
|
return
|
||||||
} else if !success {
|
} else if !success {
|
||||||
@ -107,12 +120,21 @@ func (m *MultiLogger) AddFileLogger(identifier, logfilePath string) (err error)
|
|||||||
Logger: nil,
|
Logger: nil,
|
||||||
EnableDebug: m.EnableDebug,
|
EnableDebug: m.EnableDebug,
|
||||||
Prefix: m.Prefix,
|
Prefix: m.Prefix,
|
||||||
|
LogFlags: logFlags,
|
||||||
},
|
},
|
||||||
Path: logfilePath,
|
Path: logfilePath,
|
||||||
|
EnableStdOut: enableStdOut,
|
||||||
|
EnableStdErr: enableStdErr,
|
||||||
|
}
|
||||||
|
if err = m.Loggers[identifier].Setup(); err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
m.Loggers[identifier].Setup()
|
|
||||||
|
|
||||||
m.Loggers[identifier].Info("logger initialized of type %T with prefix %v", m.Loggers[identifier], m.Loggers[identifier].GetPrefix())
|
if prefix, err = m.Loggers[identifier].GetPrefix(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Loggers[identifier].Debug("logger initialized of type %T with prefix %v", m.Loggers[identifier], prefix)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,10 @@ import (
|
|||||||
|
|
||||||
identifier is a string to use to identify the added Logger in MultiLogger.Loggers.
|
identifier is a string to use to identify the added Logger in MultiLogger.Loggers.
|
||||||
If empty, one will be automatically generated.
|
If empty, one will be automatically generated.
|
||||||
|
|
||||||
|
See the documentation for GetLogger for details on other arguments.
|
||||||
*/
|
*/
|
||||||
func (m *MultiLogger) AddDefaultLogger(identifier string, logPaths ...string) (err error) {
|
func (m *MultiLogger) AddDefaultLogger(identifier string, logFlags int, logPaths ...string) (err error) {
|
||||||
|
|
||||||
var l Logger
|
var l Logger
|
||||||
var exists bool
|
var exists bool
|
||||||
@ -28,7 +30,7 @@ func (m *MultiLogger) AddDefaultLogger(identifier string, logPaths ...string) (e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if l, err = GetLogger(m.EnableDebug, m.Prefix, logPaths...); err != nil {
|
if l, err = GetLogger(m.EnableDebug, m.Prefix, logFlags, logPaths...); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +48,7 @@ func (m *MultiLogger) AddDefaultLogger(identifier string, logPaths ...string) (e
|
|||||||
func (m *MultiLogger) AddSysdLogger(identifier string) (err error) {
|
func (m *MultiLogger) AddSysdLogger(identifier string) (err error) {
|
||||||
|
|
||||||
var exists bool
|
var exists bool
|
||||||
|
var prefix string
|
||||||
|
|
||||||
if identifier == "" {
|
if identifier == "" {
|
||||||
identifier = uuid.New().String()
|
identifier = uuid.New().String()
|
||||||
@ -65,9 +68,15 @@ func (m *MultiLogger) AddSysdLogger(identifier string) (err error) {
|
|||||||
EnableDebug: m.EnableDebug,
|
EnableDebug: m.EnableDebug,
|
||||||
Prefix: m.Prefix,
|
Prefix: m.Prefix,
|
||||||
}
|
}
|
||||||
m.Loggers[identifier].Setup()
|
if err = m.Loggers[identifier].Setup(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
m.Loggers[identifier].Info("logger initialized of type %T with prefix %v", m.Loggers[identifier], m.Loggers[identifier].GetPrefix())
|
if prefix, err = m.Loggers[identifier].GetPrefix(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Loggers[identifier].Debug("logger initialized of type %T with prefix %v", m.Loggers[identifier], prefix)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -84,6 +93,7 @@ func (m *MultiLogger) AddSyslogLogger(identifier string) (err error) {
|
|||||||
var hasSyslog bool
|
var hasSyslog bool
|
||||||
var stat os.FileInfo
|
var stat os.FileInfo
|
||||||
var devlogPath string = devlog
|
var devlogPath string = devlog
|
||||||
|
var prefix string
|
||||||
|
|
||||||
if identifier == "" {
|
if identifier == "" {
|
||||||
identifier = uuid.New().String()
|
identifier = uuid.New().String()
|
||||||
@ -110,9 +120,15 @@ func (m *MultiLogger) AddSyslogLogger(identifier string) (err error) {
|
|||||||
EnableDebug: m.EnableDebug,
|
EnableDebug: m.EnableDebug,
|
||||||
Prefix: m.Prefix,
|
Prefix: m.Prefix,
|
||||||
}
|
}
|
||||||
m.Loggers[identifier].Setup()
|
if err = m.Loggers[identifier].Setup(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
m.Loggers[identifier].Info("logger initialized of type %T with prefix %v", m.Loggers[identifier], m.Loggers[identifier].GetPrefix())
|
if prefix, err = m.Loggers[identifier].GetPrefix(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Loggers[identifier].Debug("logger initialized of type %T with prefix %v", m.Loggers[identifier], prefix)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,12 @@ import (
|
|||||||
logPaths is an (optional) list of strings to use as paths to test for writing. If the file can be created/written to,
|
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).
|
it will be used (assuming you have no higher-level loggers available).
|
||||||
|
|
||||||
|
See the documentation for GetLogger for details on other arguments.
|
||||||
|
|
||||||
Only the first logPaths entry that "works" will be used, later entries will be ignored.
|
Only the first logPaths entry that "works" will be used, later entries will be ignored.
|
||||||
Currently this will almost always return a WinLogger.
|
Currently this will almost always return a WinLogger.
|
||||||
*/
|
*/
|
||||||
func (m *MultiLogger) AddDefaultLogger(identifier string, eventIDs *WinEventID, logPaths ...string) (err error) {
|
func (m *MultiLogger) AddDefaultLogger(identifier string, eventIDs *WinEventID, logFlags int, logPaths ...string) (err error) {
|
||||||
|
|
||||||
var l Logger
|
var l Logger
|
||||||
var exists bool
|
var exists bool
|
||||||
@ -34,9 +36,9 @@ func (m *MultiLogger) AddDefaultLogger(identifier string, eventIDs *WinEventID,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if logPaths != nil {
|
if logPaths != nil {
|
||||||
l, err = GetLogger(m.EnableDebug, m.Prefix, eventIDs, logPaths...);
|
l, err = GetLogger(m.EnableDebug, m.Prefix, eventIDs, logFlags, logPaths...)
|
||||||
} else {
|
} else {
|
||||||
l, err = GetLogger(m.EnableDebug, m.Prefix, eventIDs);
|
l, err = GetLogger(m.EnableDebug, m.Prefix, eventIDs, logFlags)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -66,6 +68,7 @@ func (m *MultiLogger) AddDefaultLogger(identifier string, eventIDs *WinEventID,
|
|||||||
func (m *MultiLogger) AddWinLogger(identifier, source string, eventIDs *WinEventID) (err error) {
|
func (m *MultiLogger) AddWinLogger(identifier, source string, eventIDs *WinEventID) (err error) {
|
||||||
|
|
||||||
var exists bool
|
var exists bool
|
||||||
|
var prefix string
|
||||||
|
|
||||||
if identifier == "" {
|
if identifier == "" {
|
||||||
identifier = uuid.New().String()
|
identifier = uuid.New().String()
|
||||||
@ -85,9 +88,15 @@ func (m *MultiLogger) AddWinLogger(identifier, source string, eventIDs *WinEvent
|
|||||||
EnableDebug: m.EnableDebug,
|
EnableDebug: m.EnableDebug,
|
||||||
eids: eventIDs,
|
eids: eventIDs,
|
||||||
}
|
}
|
||||||
m.Loggers[identifier].Setup()
|
if err = m.Loggers[identifier].Setup(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
m.Loggers[identifier].Info("logger initialized of type %T with prefix %v", m.Loggers[identifier], m.Loggers[identifier].GetPrefix())
|
if prefix, err = m.Loggers[identifier].GetPrefix(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Loggers[identifier].Info("logger initialized of type %T with prefix %v", m.Loggers[identifier], prefix)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -2,26 +2,45 @@ package logging
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
`log`
|
||||||
|
`os`
|
||||||
|
`strings`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Setup sets up/configures a StdLogger and prepares it for use.
|
/*
|
||||||
func (l *StdLogger) Setup() {
|
Setup sets up/configures a StdLogger and prepares it for use.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
|
*/
|
||||||
|
func (l *StdLogger) Setup() (err error) {
|
||||||
|
|
||||||
l.Logger = log.Default()
|
// This uses a shared handle across the import. We don't want that.
|
||||||
l.Logger.SetPrefix(l.Prefix + " ")
|
// 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)
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown cleanly shuts down a StdLogger.
|
/*
|
||||||
func (l *StdLogger) Shutdown() {
|
Shutdown cleanly shuts down a StdLogger.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
|
*/
|
||||||
|
func (l *StdLogger) Shutdown() (err error) {
|
||||||
|
|
||||||
// NOOP
|
// NOOP
|
||||||
_ = ""
|
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPrefix returns the prefix used by this StdLogger.
|
/*
|
||||||
func (l *StdLogger) GetPrefix() (prefix string) {
|
GetPrefix returns the prefix used by this StdLogger.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
|
*/
|
||||||
|
func (l *StdLogger) GetPrefix() (prefix string, err error) {
|
||||||
|
|
||||||
prefix = l.Prefix
|
prefix = l.Prefix
|
||||||
|
|
||||||
@ -31,15 +50,28 @@ func (l *StdLogger) GetPrefix() (prefix string) {
|
|||||||
/*
|
/*
|
||||||
DoDebug sets the debug state of this StdLogger.
|
DoDebug sets the debug state of this StdLogger.
|
||||||
Note that this merely acts as a *safety filter* for debug messages to avoid sensitive information being written to the log.
|
Note that this merely acts as a *safety filter* for debug messages to avoid sensitive information being written to the log.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
*/
|
*/
|
||||||
func (l *StdLogger) DoDebug(d bool) {
|
func (l *StdLogger) DoDebug(d bool) (err error) {
|
||||||
|
|
||||||
l.EnableDebug = d
|
l.EnableDebug = d
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPrefix sets the prefix for this StdLogger.
|
/*
|
||||||
func (l *StdLogger) SetPrefix(prefix string) {
|
SetPrefix sets the prefix for this StdLogger.
|
||||||
l.Prefix = prefix + " "
|
err will always be nil; it's there for interface-compat.
|
||||||
l.Logger.SetPrefix(prefix + " ")
|
*/
|
||||||
|
func (l *StdLogger) SetPrefix(prefix string) (err error) {
|
||||||
|
|
||||||
|
l.Prefix = prefix
|
||||||
|
if prefix != "" {
|
||||||
|
l.Prefix = strings.TrimRight(l.Prefix, " ") + " "
|
||||||
|
}
|
||||||
|
l.Logger.SetPrefix(l.Prefix)
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alert writes an ALERT-level message to this StdLogger.
|
// Alert writes an ALERT-level message to this StdLogger.
|
||||||
|
@ -7,24 +7,33 @@ import (
|
|||||||
"github.com/coreos/go-systemd/journal"
|
"github.com/coreos/go-systemd/journal"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Setup sets up/configures a SystemDLogger and prepares it for use.
|
/*
|
||||||
func (l *SystemDLogger) Setup() {
|
Setup sets up/configures a SystemDLogger and prepares it for use.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
|
*/
|
||||||
|
func (l *SystemDLogger) Setup() (err error) {
|
||||||
|
|
||||||
// NOOP
|
// NOOP
|
||||||
_ = ""
|
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown cleanly shuts down a SystemDLogger.
|
/*
|
||||||
func (l *SystemDLogger) Shutdown() {
|
Shutdown cleanly shuts down a SystemDLogger.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
|
*/
|
||||||
|
func (l *SystemDLogger) Shutdown() (err error) {
|
||||||
|
|
||||||
// NOOP
|
// NOOP
|
||||||
_ = ""
|
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPrefix returns the prefix used by this SystemDLogger.
|
/*
|
||||||
func (l *SystemDLogger) GetPrefix() (prefix string) {
|
GetPrefix returns the prefix used by this SystemDLogger.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
|
*/
|
||||||
|
func (l *SystemDLogger) GetPrefix() (prefix string, err error) {
|
||||||
|
|
||||||
prefix = l.Prefix
|
prefix = l.Prefix
|
||||||
|
|
||||||
@ -34,14 +43,24 @@ func (l *SystemDLogger) GetPrefix() (prefix string) {
|
|||||||
/*
|
/*
|
||||||
DoDebug sets the debug state of this SystemDLogger.
|
DoDebug sets the debug state of this SystemDLogger.
|
||||||
Note that this merely acts as a *safety filter* for debug messages to avoid sensitive information being written to the log.
|
Note that this merely acts as a *safety filter* for debug messages to avoid sensitive information being written to the log.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
*/
|
*/
|
||||||
func (l *SystemDLogger) DoDebug(d bool) {
|
func (l *SystemDLogger) DoDebug(d bool) (err error) {
|
||||||
|
|
||||||
l.EnableDebug = d
|
l.EnableDebug = d
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPrefix sets the prefix for this SystemDLogger.
|
/*
|
||||||
func (l *SystemDLogger) SetPrefix(prefix string) {
|
SetPrefix sets the prefix for this SystemDLogger.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
|
*/
|
||||||
|
func (l *SystemDLogger) SetPrefix(prefix string) (err error) {
|
||||||
|
|
||||||
l.Prefix = prefix
|
l.Prefix = prefix
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alert writes an ALERT-level message to this SystemDLogger.
|
// Alert writes an ALERT-level message to this SystemDLogger.
|
||||||
|
@ -4,55 +4,79 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"log/syslog"
|
"log/syslog"
|
||||||
|
|
||||||
|
`r00t2.io/goutils/multierr`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Setup sets up/configures a SyslogLogger and prepares it for use.
|
// Setup sets up/configures a SyslogLogger and prepares it for use.
|
||||||
func (l *SyslogLogger) Setup() {
|
func (l *SyslogLogger) Setup() (err error) {
|
||||||
|
|
||||||
var err error
|
var errs *multierr.MultiError = multierr.NewMultiError(nil)
|
||||||
|
|
||||||
if l.alert, err = syslog.New(syslog.LOG_ALERT|syslogFacility, l.Prefix); err != nil {
|
if l.alert, err = syslog.New(syslog.LOG_ALERT|syslogFacility, l.Prefix); err != nil {
|
||||||
log.Panicln("could not open log for Alert")
|
errs.AddError(err)
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
if l.crit, err = syslog.New(syslog.LOG_CRIT|syslogFacility, l.Prefix); err != nil {
|
if l.crit, err = syslog.New(syslog.LOG_CRIT|syslogFacility, l.Prefix); err != nil {
|
||||||
log.Panicln("could not open log for Crit")
|
errs.AddError(err)
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
if l.debug, err = syslog.New(syslog.LOG_DEBUG|syslogFacility, l.Prefix); err != nil {
|
if l.debug, err = syslog.New(syslog.LOG_DEBUG|syslogFacility, l.Prefix); err != nil {
|
||||||
log.Panicln("could not open log for Debug")
|
errs.AddError(err)
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
if l.emerg, err = syslog.New(syslog.LOG_EMERG|syslogFacility, l.Prefix); err != nil {
|
if l.emerg, err = syslog.New(syslog.LOG_EMERG|syslogFacility, l.Prefix); err != nil {
|
||||||
log.Panicln("could not open log for Emerg")
|
errs.AddError(err)
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
if l.err, err = syslog.New(syslog.LOG_ERR|syslogFacility, l.Prefix); err != nil {
|
if l.err, err = syslog.New(syslog.LOG_ERR|syslogFacility, l.Prefix); err != nil {
|
||||||
log.Panicln("could not open log for Err")
|
errs.AddError(err)
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
if l.info, err = syslog.New(syslog.LOG_INFO|syslogFacility, l.Prefix); err != nil {
|
if l.info, err = syslog.New(syslog.LOG_INFO|syslogFacility, l.Prefix); err != nil {
|
||||||
log.Panicln("could not open log for Info")
|
errs.AddError(err)
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
if l.notice, err = syslog.New(syslog.LOG_NOTICE|syslogFacility, l.Prefix); err != nil {
|
if l.notice, err = syslog.New(syslog.LOG_NOTICE|syslogFacility, l.Prefix); err != nil {
|
||||||
log.Panicln("could not open log for Notice")
|
errs.AddError(err)
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
if l.warning, err = syslog.New(syslog.LOG_WARNING|syslogFacility, l.Prefix); err != nil {
|
if l.warning, err = syslog.New(syslog.LOG_WARNING|syslogFacility, l.Prefix); err != nil {
|
||||||
log.Panicln("could not open log for Warning")
|
errs.AddError(err)
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if errs.Count() > 0 {
|
||||||
|
err = errs
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown cleanly shuts down a SyslogLogger.
|
// Shutdown cleanly shuts down a SyslogLogger.
|
||||||
func (l *SyslogLogger) Shutdown() {
|
func (l *SyslogLogger) Shutdown() (err error) {
|
||||||
|
|
||||||
var err error
|
var errs *multierr.MultiError = multierr.NewMultiError(nil)
|
||||||
|
|
||||||
for _, i := range []*syslog.Writer{l.alert, l.crit, l.debug, l.emerg, l.err, l.info, l.notice, l.warning} {
|
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 {
|
if err = i.Close(); err != nil {
|
||||||
log.Panicf("could not close log %#v\n", i)
|
errs.AddError(err)
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if errs.Count() > 0 {
|
||||||
|
err = errs
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPrefix returns the prefix used by this SyslogLogger.
|
/*
|
||||||
func (l *SyslogLogger) GetPrefix() (prefix string) {
|
GetPrefix returns the prefix used by this SyslogLogger.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
|
*/
|
||||||
|
func (l *SyslogLogger) GetPrefix() (prefix string, err error) {
|
||||||
|
|
||||||
prefix = l.Prefix
|
prefix = l.Prefix
|
||||||
|
|
||||||
@ -62,15 +86,30 @@ func (l *SyslogLogger) GetPrefix() (prefix string) {
|
|||||||
/*
|
/*
|
||||||
DoDebug sets the debug state of this SyslogLogger.
|
DoDebug sets the debug state of this SyslogLogger.
|
||||||
Note that this merely acts as a *safety filter* for debug messages to avoid sensitive information being written to the log.
|
Note that this merely acts as a *safety filter* for debug messages to avoid sensitive information being written to the log.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
*/
|
*/
|
||||||
func (l *SyslogLogger) DoDebug(d bool) {
|
func (l *SyslogLogger) DoDebug(d bool) (err error) {
|
||||||
|
|
||||||
l.EnableDebug = d
|
l.EnableDebug = d
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPrefix sets the prefix for this SyslogLogger.
|
// SetPrefix sets the prefix for this SyslogLogger.
|
||||||
func (l *SyslogLogger) SetPrefix(prefix string) {
|
func (l *SyslogLogger) SetPrefix(prefix string) (err error) {
|
||||||
|
|
||||||
l.Prefix = prefix
|
l.Prefix = prefix
|
||||||
l.Setup()
|
|
||||||
|
// We need to close the current loggers first.
|
||||||
|
if err = l.Shutdown(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = l.Setup(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alert writes an ALERT-level message to this SyslogLogger.
|
// Alert writes an ALERT-level message to this SyslogLogger.
|
||||||
|
1
logging/funcs_test.go
Normal file
1
logging/funcs_test.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package logging
|
@ -22,6 +22,9 @@ import (
|
|||||||
A pointer to a WinEventID struct may be specified for eventIDs to map extended logging levels (as Windows only supports three levels natively).
|
A pointer to a WinEventID struct may be specified for eventIDs to map extended logging levels (as Windows only supports three levels natively).
|
||||||
If it is nil, a default one (DefaultEventID) will be used.
|
If it is nil, a default one (DefaultEventID) will be used.
|
||||||
|
|
||||||
|
logConfigFlags is the corresponding flag(s) OR'd for StdLogger.LogFlags / FileLogger.StdLogger.LogFlags if either is selected. See StdLogger.LogFlags and
|
||||||
|
https://pkg.go.dev/log#pkg-constants for details.
|
||||||
|
|
||||||
logPaths is an (optional) list of strings to use as paths to test for writing. If the file can be created/written to,
|
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).
|
it will be used (assuming you have no higher-level loggers available).
|
||||||
|
|
||||||
@ -32,13 +35,14 @@ import (
|
|||||||
If you want to log to multiple Logger destinations at once (or want to log to an explicit Logger type),
|
If you want to log to multiple Logger destinations at once (or want to log to an explicit Logger type),
|
||||||
use GetMultiLogger.
|
use GetMultiLogger.
|
||||||
*/
|
*/
|
||||||
func GetLogger(enableDebug bool, source string, eventIDs *WinEventID, logPaths ...string) (logger Logger, err error) {
|
func GetLogger(enableDebug bool, source string, eventIDs *WinEventID, logConfigFlags int, logPaths ...string) (logger Logger, err error) {
|
||||||
|
|
||||||
var logPath string
|
var logPath string
|
||||||
var logFlags bitmask.MaskBit
|
var logFlags bitmask.MaskBit
|
||||||
var exists bool
|
var exists bool
|
||||||
var success bool
|
var success bool
|
||||||
var ckLogPaths []string
|
var ckLogPaths []string
|
||||||
|
var prefix string
|
||||||
|
|
||||||
if strings.TrimSpace(source) == "" {
|
if strings.TrimSpace(source) == "" {
|
||||||
err = errors.New("invalid source for Windows logging")
|
err = errors.New("invalid source for Windows logging")
|
||||||
@ -94,6 +98,7 @@ func GetLogger(enableDebug bool, source string, eventIDs *WinEventID, logPaths .
|
|||||||
StdLogger: StdLogger{
|
StdLogger: StdLogger{
|
||||||
Prefix: source,
|
Prefix: source,
|
||||||
EnableDebug: enableDebug,
|
EnableDebug: enableDebug,
|
||||||
|
LogFlags: logConfigFlags,
|
||||||
},
|
},
|
||||||
Path: logPath,
|
Path: logPath,
|
||||||
}
|
}
|
||||||
@ -101,13 +106,25 @@ func GetLogger(enableDebug bool, source string, eventIDs *WinEventID, logPaths .
|
|||||||
logger = &StdLogger{
|
logger = &StdLogger{
|
||||||
Prefix: source,
|
Prefix: source,
|
||||||
EnableDebug: enableDebug,
|
EnableDebug: enableDebug,
|
||||||
|
LogFlags: logConfigFlags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Setup()
|
if err = logger.Setup(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if source != "\x00" {
|
||||||
|
if err = logger.SetPrefix(source); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logger.Info("logger initialized of type %T with source %v", logger, logger.GetPrefix())
|
if prefix, err = logger.GetPrefix(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debug("logger initialized of type %T with source %v", logger, prefix)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -3,17 +3,29 @@ package logging
|
|||||||
import (
|
import (
|
||||||
`errors`
|
`errors`
|
||||||
`fmt`
|
`fmt`
|
||||||
|
`os`
|
||||||
|
`os/exec`
|
||||||
|
`syscall`
|
||||||
|
|
||||||
|
`golang.org/x/sys/windows/registry`
|
||||||
`golang.org/x/sys/windows/svc/eventlog`
|
`golang.org/x/sys/windows/svc/eventlog`
|
||||||
|
`r00t2.io/sysutils/paths`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Setup sets up/configures a WinLogger and prepares it for use.
|
/*
|
||||||
func (l *WinLogger) Setup() {
|
Setup sets up/configures a WinLogger and prepares it for use.
|
||||||
|
This will fail with an Access Denied (the first time, at least) unless running with elevated permissions unless WinLogger.Prefix is
|
||||||
|
a registered Event Log source.
|
||||||
|
|
||||||
var err error
|
If a failure occurs while trying to open the log with the given WinLogger.Prefix ("source"), a new Event Log source will be registered.
|
||||||
|
If WinLogger.Executable is not empty at the time of calling WinLogger.Setup (or WinLogger.ForceService is true),
|
||||||
|
eventlog.Install will be used (with the WinLogger.ExpandKey field).
|
||||||
|
Otherwise eventlog.InstallAsEventCreate will be used.
|
||||||
|
*/
|
||||||
|
func (l *WinLogger) Setup() (err error) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
First a sanity check on the EventIDs.
|
A sanity check on the EventIDs.
|
||||||
Since we use eventcreate, all Event IDs must be 1 <= eid <= 1000.
|
Since we use eventcreate, all Event IDs must be 1 <= eid <= 1000.
|
||||||
*/
|
*/
|
||||||
for _, eid := range []uint32{
|
for _, eid := range []uint32{
|
||||||
@ -26,45 +38,100 @@ func (l *WinLogger) Setup() {
|
|||||||
l.eids.Notice,
|
l.eids.Notice,
|
||||||
l.eids.Warning,
|
l.eids.Warning,
|
||||||
} {
|
} {
|
||||||
if !((eid <= 1000) && (1 <= eid)) {
|
if !((eid <= EIDMax) && (EIDMin <= eid)) {
|
||||||
err = errors.New("event IDs must be between 1 and 1000 inclusive")
|
err = ErrBadEid
|
||||||
panic(err)
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = eventlog.InstallAsEventCreate(l.Prefix, eventlog.Error|eventlog.Warning|eventlog.Info); err != nil {
|
if err = l.Install(); err != nil {
|
||||||
if idx := ptrnSourceExists.FindStringIndex(err.Error()); idx == nil {
|
return
|
||||||
// It's an error we want to panic on.
|
|
||||||
panic(err)
|
|
||||||
} else {
|
|
||||||
// It already exists, so ignore the error.
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.elog, err = eventlog.Open(l.Prefix); err != nil {
|
if l.elog, err = eventlog.Open(l.Prefix); err != nil {
|
||||||
panic(err)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install installs/registers the WinLogger Event Log interface. You most likely do not need to run this directly.
|
||||||
|
func (l *WinLogger) Install() (err error) {
|
||||||
|
|
||||||
|
var exists bool
|
||||||
|
var doNotCreate bool
|
||||||
|
var useEventCreate bool = true
|
||||||
|
|
||||||
|
if doNotCreate, err = l.Exists(); err != nil {
|
||||||
|
return
|
||||||
|
} else if !doNotCreate {
|
||||||
|
if l.Executable != "" {
|
||||||
|
if l.Executable, err = exec.LookPath(l.Executable); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
useEventCreate = false
|
||||||
|
} else if l.ForceService {
|
||||||
|
if l.Executable, err = exec.LookPath(os.Args[0]); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
useEventCreate = false
|
||||||
|
}
|
||||||
|
if !useEventCreate {
|
||||||
|
if exists, err = paths.RealPathExists(&l.Executable); err != nil {
|
||||||
|
return
|
||||||
|
} else if !exists {
|
||||||
|
err = ErrBadBinPath
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = eventlog.Install(l.Prefix, l.Executable, l.ExpandKey, eventlog.Error|eventlog.Warning|eventlog.Info); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err = eventlog.InstallAsEventCreate(l.Prefix, eventlog.Error|eventlog.Warning|eventlog.Info); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown cleanly shuts down a WinLogger.
|
// Remove uninstalls a registered WinLogger source.
|
||||||
func (l *WinLogger) Shutdown() {
|
func (l *WinLogger) Remove() (err error) {
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if err = l.elog.Close(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = eventlog.Remove(l.Prefix); err != nil {
|
if err = eventlog.Remove(l.Prefix); err != nil {
|
||||||
panic(err)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPrefix returns the prefix used by this WinLogger.
|
/*
|
||||||
func (l *WinLogger) GetPrefix() (prefix string) {
|
Shutdown cleanly shuts down a WinLogger but keep the source registered. Use WinLogger.Remove
|
||||||
|
(or set WinLogger.RemoveOnClose to true before calling WinLogger.Shutdown) to remove the registered source.
|
||||||
|
*/
|
||||||
|
func (l *WinLogger) Shutdown() (err error) {
|
||||||
|
|
||||||
|
if err = l.elog.Close(); err != nil {
|
||||||
|
// TODO: check for no access or file not exists syscall errors?
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if l.RemoveOnClose {
|
||||||
|
if err = l.Remove(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
GetPrefix returns the prefix used by this WinLogger.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
|
*/
|
||||||
|
func (l *WinLogger) GetPrefix() (prefix string, err error) {
|
||||||
|
|
||||||
prefix = l.Prefix
|
prefix = l.Prefix
|
||||||
|
|
||||||
@ -74,43 +141,55 @@ func (l *WinLogger) GetPrefix() (prefix string) {
|
|||||||
/*
|
/*
|
||||||
DoDebug sets the debug state of this WinLogger.
|
DoDebug sets the debug state of this WinLogger.
|
||||||
Note that this merely acts as a *safety filter* for debug messages to avoid sensitive information being written to the log.
|
Note that this merely acts as a *safety filter* for debug messages to avoid sensitive information being written to the log.
|
||||||
|
err will always be nil; it's there for interface-compat.
|
||||||
*/
|
*/
|
||||||
func (l *WinLogger) DoDebug(d bool) {
|
func (l *WinLogger) DoDebug(d bool) (err error) {
|
||||||
|
|
||||||
l.EnableDebug = d
|
l.EnableDebug = d
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPrefix sets the prefix for this WinLogger.
|
// SetPrefix sets the prefix for this WinLogger.
|
||||||
func (l *WinLogger) SetPrefix(prefix string) {
|
func (l *WinLogger) SetPrefix(prefix string) (err error) {
|
||||||
|
|
||||||
var err error
|
// To properly change the prefix, we need to tear down the old event log and create a new one.
|
||||||
|
if err = l.Shutdown(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
l.Prefix = prefix
|
l.Prefix = prefix
|
||||||
|
|
||||||
// To properly change the prefix, we need to tear down the old event log and create a new one.
|
if err = l.Setup(); err != nil {
|
||||||
if err = l.elog.Close(); err != nil {
|
return
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = eventlog.Remove(l.Prefix); err != nil {
|
return
|
||||||
panic(err)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if err = eventlog.InstallAsEventCreate(l.Prefix, eventlog.Error|eventlog.Warning|eventlog.Info); err != nil {
|
// Exists indicates if the WinLogger.Prefix is a registered source or not.
|
||||||
if idx := ptrnSourceExists.FindStringIndex(err.Error()); idx == nil {
|
func (l *WinLogger) Exists() (e bool, err error) {
|
||||||
// It's an error we want to panic on.
|
|
||||||
panic(err)
|
var regKey registry.Key
|
||||||
} else {
|
var subKey registry.Key
|
||||||
// It already exists, so ignore the error.
|
|
||||||
|
if regKey, err = registry.OpenKey(registry.LOCAL_MACHINE, eventLogRegistryKey, registry.READ); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer regKey.Close()
|
||||||
|
|
||||||
|
if subKey, err = registry.OpenKey(regKey, l.Prefix, registry.READ); err != nil {
|
||||||
|
if errors.Is(err, syscall.ERROR_FILE_NOT_FOUND) {
|
||||||
|
e = false
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
defer subKey.Close()
|
||||||
|
|
||||||
if l.elog, err = eventlog.Open(l.Prefix); err != nil {
|
e = true
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alert writes an ALERT-level message to this WinLogger.
|
// Alert writes an ALERT-level message to this WinLogger.
|
||||||
|
@ -17,11 +17,11 @@ type Logger interface {
|
|||||||
Info(s string, v ...interface{}) (err error)
|
Info(s string, v ...interface{}) (err error)
|
||||||
Notice(s string, v ...interface{}) (err error)
|
Notice(s string, v ...interface{}) (err error)
|
||||||
Warning(s string, v ...interface{}) (err error)
|
Warning(s string, v ...interface{}) (err error)
|
||||||
DoDebug(d bool)
|
DoDebug(d bool) (err error)
|
||||||
SetPrefix(p string)
|
SetPrefix(p string) (err error)
|
||||||
GetPrefix() (p string)
|
GetPrefix() (p string, err error)
|
||||||
Setup()
|
Setup() (err error)
|
||||||
Shutdown()
|
Shutdown() (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -38,20 +38,42 @@ type StdLogger struct {
|
|||||||
EnableDebug bool
|
EnableDebug bool
|
||||||
// Prefix indicates the prefix for log entries; in shared logs, this helps differentiate the source.
|
// Prefix indicates the prefix for log entries; in shared logs, this helps differentiate the source.
|
||||||
Prefix string
|
Prefix string
|
||||||
|
/*
|
||||||
|
LogFlags control some of the formatting options presented as an OR'd value.
|
||||||
|
See https://pkg.go.dev/log#pkg-constants for flag details.
|
||||||
|
e.g.:
|
||||||
|
*StdLogger.LogFlags = log.Ldate | log.Lmicroseconds | log.Llongfile | log.LUTC // a very detailed log output
|
||||||
|
*StdLogger.LogFlags = log.Ldate | log.Ltime // the flags used by log.Default() (also available as simply log.LstdFlags)
|
||||||
|
The default is 0; no flags (no output except prefix if non-empty and message).
|
||||||
|
You will need to run *StdLogger.Shutdown and then *StdLogger.Setup again if you wish to change this.
|
||||||
|
*/
|
||||||
|
LogFlags int
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileLogger uses a StdLogger with a file handle writer to write to the file given at Path.
|
/*
|
||||||
|
FileLogger uses a StdLogger with a file handle writer to write to the file given at Path.
|
||||||
|
|
||||||
|
NOTE: If you wish to change the FileLogger.StdLogger.LogFlags, do *not* run FileLogger.StdLogger.Setup after doing so as this
|
||||||
|
will instead create a logger detached from the file handler. Instead, be sure to call FileLogger.Setup.
|
||||||
|
(Alternatively, run FileLogger.Shutdown and replace your logger with a new FileLogger.)
|
||||||
|
*/
|
||||||
type FileLogger struct {
|
type FileLogger struct {
|
||||||
// StdLogger is used for the log formation and handling. See StdLogger for more details.
|
// StdLogger is used for the log formation and handling. See StdLogger for more details.
|
||||||
StdLogger
|
StdLogger
|
||||||
// Path is the path to the logfile.
|
// Path is the path to the logfile.
|
||||||
Path string
|
Path string
|
||||||
/*
|
/*
|
||||||
EnableStdOut is true if the log will send to STDOUT as well as the file.
|
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.
|
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.
|
You will need to run *FileLogger.Shutdown and then *FileLogger.Setup again if you wish to change this.
|
||||||
*/
|
*/
|
||||||
EnableStdOut bool
|
EnableStdErr bool
|
||||||
// writer is used for the writing out of the log file.
|
// writer is used for the writing out of the log file.
|
||||||
writer *os.File
|
writer *os.File
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,60 @@ import (
|
|||||||
`golang.org/x/sys/windows/svc/eventlog`
|
`golang.org/x/sys/windows/svc/eventlog`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// WinLogger is used for logging to the Windows Event Log. These entries are viewable in the Event Viewer application, under "Windows Logs > Application".
|
||||||
type WinLogger struct {
|
type WinLogger struct {
|
||||||
|
/*
|
||||||
|
EnableDebug indicates if the debug filter should be disabled (true) or if the filter should be enabled (false).
|
||||||
|
This prevents potential data leak of sensitive information, as some loggers (e.g. FileLogger) will otherwise write all messages.
|
||||||
|
*/
|
||||||
EnableDebug bool
|
EnableDebug bool
|
||||||
|
/*
|
||||||
|
Prefix is used as the Event Log "Source". It's named as Prefix to retain compatability with methods in the Logger interface.
|
||||||
|
*/
|
||||||
Prefix string
|
Prefix string
|
||||||
|
/*
|
||||||
|
Executable is used as the path for the executable implementing this logger.
|
||||||
|
If non-empty, it enables the "service" mode of Event Log (intended for "installed" software that's expected
|
||||||
|
to exist as a specific path reliably).
|
||||||
|
It can be a file within the PATHs or an absolute/relative path; an attempt to resolve the actual path will be made. If this fails or the file
|
||||||
|
does not exist, an error will be raised.
|
||||||
|
*/
|
||||||
|
Executable string
|
||||||
|
/*
|
||||||
|
ExpandKey is only used if Executable is non-empty and valid and/or ForceService is true.
|
||||||
|
If true, the WinLogger will be installed/registered with the REG_EXPAND_SZ mode - otherwise it will be installed as REG_SZ.
|
||||||
|
See the definition for the two at https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types for further details.
|
||||||
|
If you're unsure which you want, it's probably REG_SZ (WinLogger.ExpandKey == false), which is the default.
|
||||||
|
*/
|
||||||
|
ExpandKey bool
|
||||||
|
/*
|
||||||
|
ForceService, if true, will enforce WinLogger to be used as if Executable is populated and valid (it will use os.Args[0] as the Executable path).
|
||||||
|
If Executable is empty but ForceService is true and os.Args[0] is empty or invalid (not a real path, etc.), an error will be raised.
|
||||||
|
*/
|
||||||
|
ForceService bool
|
||||||
|
// RemoveOnClose should be true if the logger should be removed/unregistered from the Registry upon calling WinLogger.Shutdown.
|
||||||
|
RemoveOnClose bool
|
||||||
|
// elog is the actual writer to the Event Log.
|
||||||
elog *eventlog.Log
|
elog *eventlog.Log
|
||||||
|
// eids is used to look up what event ID to use when writing to a WinLogger.elog.
|
||||||
eids *WinEventID
|
eids *WinEventID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
WinEventID is a collection of Event IDs to use for a WinLogger.
|
||||||
|
Because Event Log only supports three entry types (informational, warning, or error),
|
||||||
|
these event IDs allow you to filter the messages in a slightly more granular way. They map to their corresponding method name/Logger level.
|
||||||
|
However, this means that a WinLogger does not support custom event IDs (and thus you cannot assign individual event IDs to specific errors).
|
||||||
|
This is the price of convenience.
|
||||||
|
|
||||||
|
An additional method set may be added in the future to support this, but this is currently an unplanned feature.
|
||||||
|
|
||||||
|
Event IDs *must* be between the constants EIDMin and EIDMax (inclusive) unless the WinLogger is used in "service" mode
|
||||||
|
(see WinLogger.Executable and WinLogger.ForceService).
|
||||||
|
|
||||||
|
If you need recommended defaults, you may want to use the Event* constants (e.g. EventAlert, EventDebug, etc.)
|
||||||
|
or even use the pre-populated DefaultEventID (which is assigned the above Event* constants).
|
||||||
|
*/
|
||||||
type WinEventID struct {
|
type WinEventID struct {
|
||||||
Alert,
|
Alert,
|
||||||
Crit,
|
Crit,
|
||||||
|
Loading…
Reference in New Issue
Block a user