finalizing logging and multierror
This commit is contained in:
parent
3975f8b11f
commit
0e01306637
4
go.mod
4
go.mod
@ -4,5 +4,7 @@ go 1.16
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||||
r00t2.io/sysutils v0.0.0-20210224054841-55ac47c86928
|
github.com/google/uuid v1.3.0
|
||||||
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
|
||||||
|
r00t2.io/sysutils v1.1.1
|
||||||
)
|
)
|
||||||
|
9
go.sum
9
go.sum
@ -1,5 +1,8 @@
|
|||||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
|
||||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/jszwec/csvutil v1.5.0/go.mod h1:Rpu7Uu9giO9subDyMCIQfHVDuLrcaC36UA4YcJjGBkg=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
r00t2.io/sysutils v0.0.0-20210224054841-55ac47c86928 h1:aYEn20eguqsmqT3J9VjkzdhyPwmOVDGzzffcEfV18a4=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
r00t2.io/sysutils v0.0.0-20210224054841-55ac47c86928/go.mod h1:XzJkBF6SHAODEszJlOcjtGoTHwYnZZNmseA6PyOujes=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||||
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
r00t2.io/sysutils v1.1.1 h1:q2P5u50HIIRk6muCPo1Gpapy6sNT4oaB1l2O/C/mi3A=
|
||||||
|
r00t2.io/sysutils v1.1.1/go.mod h1:Wlfi1rrJpoKBOjWiYM9rw2FaiZqraD6VpXyiHgoDo/o=
|
||||||
|
@ -5,7 +5,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// logPerm is the octal mode to use for testing the file.
|
||||||
logPerm os.FileMode = 0600
|
logPerm os.FileMode = 0600
|
||||||
|
// logPrefix is the default log prefix.
|
||||||
logPrefix string = "GOLANG PROGRAM"
|
logPrefix string = "GOLANG PROGRAM"
|
||||||
appendFlags int = os.O_APPEND|os.O_CREATE|os.O_WRONLY
|
// appendFlags are the flags used for testing the file (and opening/writing).
|
||||||
|
appendFlags int = os.O_APPEND | os.O_CREATE | os.O_WRONLY
|
||||||
)
|
)
|
||||||
|
@ -7,20 +7,28 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
devlog string = "/dev/log"
|
// devlog is the path to the syslog char device.
|
||||||
|
devlog string = "/dev/log"
|
||||||
|
// syslogFacility is the facility to use; it's a little like a context or scope if you think of it in those terms.
|
||||||
syslogFacility syslog.Priority = syslog.LOG_USER
|
syslogFacility syslog.Priority = syslog.LOG_USER
|
||||||
)
|
)
|
||||||
|
|
||||||
// Flags for logger configuration
|
// Flags for logger configuration. These are used internally.
|
||||||
const (
|
const (
|
||||||
|
// LogUndefined indicates an undefined Logger type.
|
||||||
LogUndefined bitmask.MaskBit = 1 << iota
|
LogUndefined bitmask.MaskBit = 1 << iota
|
||||||
|
// LogJournald flags a SystemDLogger Logger type.
|
||||||
LogJournald
|
LogJournald
|
||||||
|
// LogSyslog flags a SyslogLogger Logger type.
|
||||||
LogSyslog
|
LogSyslog
|
||||||
|
// LogFile flags a FileLogger Logger type.
|
||||||
LogFile
|
LogFile
|
||||||
|
// LogStdout flags a StdLogger Logger type.
|
||||||
LogStdout
|
LogStdout
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// defLogPaths indicates default log paths.
|
||||||
defLogPaths = []string{
|
defLogPaths = []string{
|
||||||
"/var/log/golang/program.log",
|
"/var/log/golang/program.log",
|
||||||
"~/.local/log/golang/program.log",
|
"~/.local/log/golang/program.log",
|
||||||
|
@ -6,24 +6,30 @@ import (
|
|||||||
`regexp`
|
`regexp`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Flags for logger configuration
|
// Flags for logger configuration. These are used internally.
|
||||||
const (
|
const (
|
||||||
|
// LogUndefined indicates an undefined Logger type.
|
||||||
LogUndefined types.MaskBit = 1 << iota
|
LogUndefined types.MaskBit = 1 << iota
|
||||||
|
// LogWinLogger indicates a WinLogger Logger type (Event Log).
|
||||||
LogWinLogger
|
LogWinLogger
|
||||||
|
// LogFile flags a FileLogger Logger type.
|
||||||
LogFile
|
LogFile
|
||||||
|
// LogStdout flags a StdLogger Logger type.
|
||||||
LogStdout
|
LogStdout
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// defLogPaths indicates default log paths.
|
||||||
defLogPaths = []string{
|
defLogPaths = []string{
|
||||||
filepath.Join(os.Getenv("ALLUSERSPROFILE"), "golang", "program.log"), // C:\ProgramData\log\golang\program.log
|
filepath.Join(os.Getenv("ALLUSERSPROFILE"), "golang", "program.log"), // C:\ProgramData\log\golang\program.log
|
||||||
filepath.Join(os.Getenv("LOCALAPPDATA"), "log", "golang", "program.log"), // C:\Users\<username>\AppData\Local\log\golang\program.log
|
filepath.Join(os.Getenv("LOCALAPPDATA"), "log", "golang", "program.log"), // C:\Users\<username>\AppData\Local\log\golang\program.log
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 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$`)
|
var ptrnSourceExists *regexp.Regexp = regexp.MustCompile(`registry\skey\salready\sexists$`)
|
||||||
|
|
||||||
// Default WinEventID
|
// Default WinEventID, (can be) used in GetLogger and MultiLogger.AddWinLogger.
|
||||||
var DefaultEventID *WinEventID = &WinEventID{
|
var DefaultEventID *WinEventID = &WinEventID{
|
||||||
Alert: EventAlert,
|
Alert: EventAlert,
|
||||||
Crit: EventCrit,
|
Crit: EventCrit,
|
||||||
|
43
logging/doc.go
Normal file
43
logging/doc.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
Package logging implements and presents various loggers under a unified interface, making them completely swappable.
|
||||||
|
|
||||||
|
These particular loggers (logging.Logger) available are:
|
||||||
|
|
||||||
|
StdLogger
|
||||||
|
FileLogger
|
||||||
|
SystemDLogger (Linux only)
|
||||||
|
SyslogLogger (Linux only)
|
||||||
|
WinLogger (Windows only)
|
||||||
|
|
||||||
|
There is a sixth type of logging.Logger, MultiLogger, that allows for multiple loggers to be written to with a single call.
|
||||||
|
|
||||||
|
Every logging.Logger type has the following methods that correspond to certain "levels".
|
||||||
|
|
||||||
|
Alert(s string, v ...interface{}) (err error)
|
||||||
|
Crit(s string, v ...interface{}) (err error)
|
||||||
|
Debug(s string, v ...interface{}) (err error)
|
||||||
|
Emerg(s string, v ...interface{}) (err error)
|
||||||
|
Err(s string, v ...interface{}) (err error)
|
||||||
|
Info(s string, v ...interface{}) (err error)
|
||||||
|
Notice(s string, v ...interface{}) (err error)
|
||||||
|
Warning(s string, v ...interface{}) (err error)
|
||||||
|
|
||||||
|
Not all loggers implement the concept of levels, so approximations are made when/where possible.
|
||||||
|
|
||||||
|
In each of the above methods, s is the message that is optionally in a fmt.Sprintf-compatible format.
|
||||||
|
If it is, the values to fmt.Sprintf can be passed as v.
|
||||||
|
|
||||||
|
Note that in the case of a MultiLogger, err (if not nil) will be a (r00t2.io/goutils/)multierr.MultiError.
|
||||||
|
|
||||||
|
logging.Logger types also have the following methods:
|
||||||
|
|
||||||
|
DoDebug(d bool)
|
||||||
|
SetPrefix(p string)
|
||||||
|
GetPrefix() (p string)
|
||||||
|
Setup()
|
||||||
|
Shutdown()
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
package logging
|
17
logging/errs.go
Normal file
17
logging/errs.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package logging
|
||||||
|
|
||||||
|
import (
|
||||||
|
`errors`
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrExistingLogger indicates that the user attempted to add a Logger to a MultiLogger using an already-existing identifier.
|
||||||
|
ErrExistingLogger error = errors.New("a Logger with that identifier already exists; please remove it first")
|
||||||
|
/*
|
||||||
|
ErrInvalidFile indicates that the user attempted to add a FileLogger to a MultiLogger but the file doesn't exist,
|
||||||
|
exists with too restrictive perms to write/append to, and/or could not be created.
|
||||||
|
*/
|
||||||
|
ErrInvalidFile error = errors.New("a FileLogger was requested but the file does not exist and cannot be created")
|
||||||
|
// ErrNoEntry indicates that the user attempted to MultiLogger.RemoveLogger a Logger but one by that identifier does not exist.
|
||||||
|
ErrNoEntry error = errors.New("the Logger specified to be removed does not exist")
|
||||||
|
)
|
18
logging/errs_linux.go
Normal file
18
logging/errs_linux.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package logging
|
||||||
|
|
||||||
|
import (
|
||||||
|
`errors`
|
||||||
|
`fmt`
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrNoSysD indicates that the user attempted to add a SystemDLogger to a MultiLogger but systemd is unavailable.
|
||||||
|
ErrNoSysD error = errors.New("a systemd (journald) Logger was requested but systemd is unavailable on this system")
|
||||||
|
// ErrNoSyslog indicates that the user attempted to add a SyslogLogger to a MultiLogger but syslog's logger device is unavailable.
|
||||||
|
ErrNoSyslog error = errors.New("a Syslog Logger was requested but Syslog is unavailable on this system")
|
||||||
|
/*
|
||||||
|
ErrInvalidDevLog indicates that the user attempted to add a SyslogLogger to a MultiLogger but
|
||||||
|
the Syslog char device file is... not actually a char device file.
|
||||||
|
*/
|
||||||
|
ErrInvalidDevLog error = errors.New(fmt.Sprintf("a Syslog Logger was requested but %v is not a valid logger handle", devlog))
|
||||||
|
)
|
@ -4,6 +4,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// testOpen attempts to open a file for writing to test for suitability as a LogFile path.
|
||||||
func testOpen(path string) (success bool, err error) {
|
func testOpen(path string) (success bool, err error) {
|
||||||
var f *os.File
|
var f *os.File
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Setup sets up/configures a FileLogger and prepares it for use.
|
||||||
func (l *FileLogger) Setup() {
|
func (l *FileLogger) Setup() {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -21,6 +22,7 @@ func (l *FileLogger) Setup() {
|
|||||||
l.Logger.SetOutput(multi)
|
l.Logger.SetOutput(multi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown cleanly shuts down a FileLogger.
|
||||||
func (l *FileLogger) Shutdown() {
|
func (l *FileLogger) Shutdown() {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -31,19 +33,26 @@ func (l *FileLogger) Shutdown() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPrefix returns the prefix used by this FileLogger.
|
||||||
func (l *FileLogger) GetPrefix() string {
|
func (l *FileLogger) GetPrefix() string {
|
||||||
return l.Prefix
|
return l.Prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
func (l *FileLogger) DoDebug(d bool) {
|
func (l *FileLogger) DoDebug(d bool) {
|
||||||
l.EnableDebug = d
|
l.EnableDebug = d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPrefix sets the prefix for this FileLogger.
|
||||||
func (l *FileLogger) SetPrefix(prefix string) {
|
func (l *FileLogger) SetPrefix(prefix string) {
|
||||||
l.Prefix = prefix
|
l.Prefix = prefix
|
||||||
l.Logger.SetPrefix(prefix)
|
l.Logger.SetPrefix(prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Alert writes an ALERT-level message to this FileLogger.
|
||||||
func (l *FileLogger) Alert(s string, v ...interface{}) (err error) {
|
func (l *FileLogger) Alert(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -59,6 +68,7 @@ func (l *FileLogger) Alert(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crit writes an CRITICAL-level message to this FileLogger.
|
||||||
func (l *FileLogger) Crit(s string, v ...interface{}) (err error) {
|
func (l *FileLogger) Crit(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -74,6 +84,7 @@ func (l *FileLogger) Crit(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug writes a DEBUG-level message to this FileLogger.
|
||||||
func (l *FileLogger) Debug(s string, v ...interface{}) (err error) {
|
func (l *FileLogger) Debug(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
if !l.EnableDebug {
|
if !l.EnableDebug {
|
||||||
@ -93,6 +104,7 @@ func (l *FileLogger) Debug(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emerg writes an EMERGENCY-level message to this FileLogger.
|
||||||
func (l *FileLogger) Emerg(s string, v ...interface{}) (err error) {
|
func (l *FileLogger) Emerg(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -108,6 +120,7 @@ func (l *FileLogger) Emerg(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Err writes an ERROR-level message to this FileLogger.
|
||||||
func (l *FileLogger) Err(s string, v ...interface{}) (err error) {
|
func (l *FileLogger) Err(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -123,6 +136,7 @@ func (l *FileLogger) Err(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info writes an INFO-level message to this FileLogger.
|
||||||
func (l *FileLogger) Info(s string, v ...interface{}) (err error) {
|
func (l *FileLogger) Info(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -138,6 +152,7 @@ func (l *FileLogger) Info(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notice writes a NOTICE-level message to this FileLogger.
|
||||||
func (l *FileLogger) Notice(s string, v ...interface{}) (err error) {
|
func (l *FileLogger) Notice(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -153,6 +168,7 @@ func (l *FileLogger) Notice(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Warning writes a WARNING/WARN-level message to this FileLogger.
|
||||||
func (l *FileLogger) Warning(s string, v ...interface{}) (err error) {
|
func (l *FileLogger) Warning(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -168,6 +184,7 @@ func (l *FileLogger) Warning(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renderWrite prepares/formats a log message to be written to this FileLogger.
|
||||||
func (l *FileLogger) renderWrite(msg, prio string) {
|
func (l *FileLogger) renderWrite(msg, prio string) {
|
||||||
|
|
||||||
s := fmt.Sprintf("[%v] %v", prio, msg)
|
s := fmt.Sprintf("[%v] %v", prio, msg)
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
`path`
|
`path`
|
||||||
|
|
||||||
sysd `github.com/coreos/go-systemd/journal`
|
sysd `github.com/coreos/go-systemd/journal`
|
||||||
|
`r00t2.io/goutils/bitmask`
|
||||||
`r00t2.io/sysutils/paths`
|
`r00t2.io/sysutils/paths`
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,16 +18,24 @@ var (
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
GetLogger returns an instance of Logger that best suits your system's capabilities.
|
GetLogger returns an instance of Logger that best suits your system's capabilities.
|
||||||
|
|
||||||
If enableDebug is true, debug messages (which according to your program may or may not contain sensitive data) are rendered and written.
|
If enableDebug is true, debug messages (which according to your program may or may not contain sensitive data) are rendered and written.
|
||||||
|
|
||||||
If prefix is "\x00" (a null byte), then the default logging prefix will be used. If anything else, even an empty string,
|
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.
|
||||||
|
|
||||||
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 call GetLogger, you will only get a single ("best") logger your system supports.
|
||||||
|
If you want to log to multiple Logger destinations at once (or want to log to an explicit Logger type),
|
||||||
|
use GetMultiLogger.
|
||||||
*/
|
*/
|
||||||
func GetLogger(enableDebug bool, prefix string, logPaths ...string) (logger Logger, err error) {
|
func GetLogger(enableDebug bool, prefix string, logPaths ...string) (logger Logger, err error) {
|
||||||
|
|
||||||
var logPath string
|
var logPath string
|
||||||
var logFlags types.MaskBit
|
var logFlags bitmask.MaskBit
|
||||||
|
|
||||||
// Configure system-supported logger(s).
|
// Configure system-supported logger(s).
|
||||||
if sysd.Enabled() {
|
if sysd.Enabled() {
|
||||||
@ -67,7 +76,7 @@ func GetLogger(enableDebug bool, prefix string, logPaths ...string) (logger Logg
|
|||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
dirPath := path.Dir(p)
|
dirPath := path.Dir(p)
|
||||||
if err = paths.MakeDirIfNotExist(&dirPath); err != nil {
|
if err = paths.MakeDirIfNotExist(dirPath); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if success, err = testOpen(p); err != nil {
|
if success, err = testOpen(p); err != nil {
|
||||||
|
275
logging/funcs_multilogger.go
Normal file
275
logging/funcs_multilogger.go
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
package logging
|
||||||
|
|
||||||
|
import (
|
||||||
|
`sync`
|
||||||
|
|
||||||
|
`r00t2.io/goutils/multierr`
|
||||||
|
)
|
||||||
|
|
||||||
|
// Setup sets up/configures a MultiLogger (and all its MultiLogger.Loggers) and prepares it for use.
|
||||||
|
func (m *MultiLogger) Setup() {
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
for _, l := range m.Loggers {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
l.Setup()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown cleanly shuts down a MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
func (m *MultiLogger) Shutdown() {
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
for _, l := range m.Loggers {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
l.Shutdown()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPrefix returns the prefix used by this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
func (m *MultiLogger) GetPrefix() string {
|
||||||
|
|
||||||
|
return m.Prefix
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
DoDebug sets the debug state of this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
Note that this merely acts as a *safety filter* for debug messages to avoid sensitive information being written to the log.
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
m.EnableDebug = d
|
||||||
|
|
||||||
|
for _, l := range m.Loggers {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
l.DoDebug(d)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
SetPrefix sets the prefix for this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
m.Prefix = prefix
|
||||||
|
|
||||||
|
for _, l := range m.Loggers {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
l.SetPrefix(prefix)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alert writes an ALERT-level message to this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
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 {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
|
if err = logObj.Alert(msg, rplc...); err != nil {
|
||||||
|
e.AddError(err)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
}(l, s, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
err = e
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crit writes an CRITICAL-level message to this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
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 {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
|
if err = logObj.Crit(msg, rplc...); err != nil {
|
||||||
|
e.AddError(err)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
}(l, s, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
err = e
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug writes a DEBUG-level message to this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
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 {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
|
if err = logObj.Debug(msg, rplc...); err != nil {
|
||||||
|
e.AddError(err)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
}(l, s, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
err = e
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emerg writes an EMERGENCY-level message to this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
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 {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
|
if err = logObj.Emerg(msg, rplc...); err != nil {
|
||||||
|
e.AddError(err)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
}(l, s, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
err = e
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Err writes an ERROR-level message to this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
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 {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
|
if err = logObj.Err(msg, rplc...); err != nil {
|
||||||
|
e.AddError(err)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
}(l, s, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
err = e
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info writes an INFO-level message to this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
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 {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
|
if err = logObj.Info(msg, rplc...); err != nil {
|
||||||
|
e.AddError(err)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
}(l, s, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
err = e
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notice writes a NOTICE-level message to this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
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 {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
|
if err = logObj.Notice(msg, rplc...); err != nil {
|
||||||
|
e.AddError(err)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
}(l, s, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
err = e
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warning writes a WARNING/WARN-level message to this MultiLogger (and all its MultiLogger.Loggers).
|
||||||
|
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 {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(logObj Logger, msg string, rplc ...interface{}) {
|
||||||
|
if err = logObj.Warning(msg, rplc...); err != nil {
|
||||||
|
e.AddError(err)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
}(l, s, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
err = e
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
133
logging/funcs_multilogger_mgr.go
Normal file
133
logging/funcs_multilogger_mgr.go
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
package logging
|
||||||
|
|
||||||
|
import (
|
||||||
|
`path`
|
||||||
|
|
||||||
|
`github.com/google/uuid`
|
||||||
|
`r00t2.io/sysutils/paths`
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
GetMultiLogger returns a MultiLogger.
|
||||||
|
If you call GetLogger, you will only get a single ("best") logger your system supports.
|
||||||
|
If you want to log to multiple Logger destinations at once (or want to log to an explicit Logger type),
|
||||||
|
use GetMultiLogger.
|
||||||
|
|
||||||
|
Remember to add at least one Logger (e.g. MultiLogger.AddStdLogger), otherwise no entries will actually be logged.
|
||||||
|
|
||||||
|
If you want to modify e.g. if debug is enabled for a specific Logger, reference the Logger directly (e.g. MultiLogger.Loggers[identifier].SetDebug(false)).
|
||||||
|
*/
|
||||||
|
func GetMultiLogger(enableDebug bool, prefix string) (m *MultiLogger) {
|
||||||
|
|
||||||
|
m = &MultiLogger{
|
||||||
|
EnableDebug: enableDebug,
|
||||||
|
Prefix: "",
|
||||||
|
Loggers: make(map[string]Logger),
|
||||||
|
}
|
||||||
|
if prefix != "\x00" {
|
||||||
|
m.Prefix = prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
AddStdLogger adds a StdLogger to a MultiLogger.
|
||||||
|
|
||||||
|
identifier is a string to use to identify the added StdLogger in MultiLogger.Loggers.
|
||||||
|
If empty, one will be automatically generated.
|
||||||
|
*/
|
||||||
|
func (m *MultiLogger) AddStdLogger(identifier string) (err error) {
|
||||||
|
|
||||||
|
var exists bool
|
||||||
|
|
||||||
|
if identifier == "" {
|
||||||
|
identifier = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists = m.Loggers[identifier]; exists {
|
||||||
|
err = ErrExistingLogger
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Loggers[identifier] = &StdLogger{
|
||||||
|
Logger: nil,
|
||||||
|
EnableDebug: m.EnableDebug,
|
||||||
|
Prefix: m.Prefix,
|
||||||
|
}
|
||||||
|
m.Loggers[identifier].Setup()
|
||||||
|
|
||||||
|
m.Loggers[identifier].Info("logger initialized of type %T with prefix %v", m.Loggers[identifier], m.Loggers[identifier].GetPrefix())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
AddFileLogger adds a FileLogger to a MultiLogger.
|
||||||
|
|
||||||
|
identifier is a string to use to identify the added FileLogger in MultiLogger.Loggers.
|
||||||
|
If empty, one will be automatically generated.
|
||||||
|
|
||||||
|
logfilePath is a string for the path to the desired logfile.
|
||||||
|
*/
|
||||||
|
func (m *MultiLogger) AddFileLogger(identifier, logfilePath string) (err error) {
|
||||||
|
|
||||||
|
var exists bool
|
||||||
|
var success bool
|
||||||
|
var dirPath string
|
||||||
|
|
||||||
|
if identifier == "" {
|
||||||
|
identifier = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists = m.Loggers[identifier]; exists {
|
||||||
|
err = ErrExistingLogger
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists, _ = paths.RealPathExists(&logfilePath); !exists {
|
||||||
|
if success, err = testOpen(logfilePath); err != nil {
|
||||||
|
return
|
||||||
|
} else if !success {
|
||||||
|
dirPath = path.Dir(logfilePath)
|
||||||
|
if err = paths.MakeDirIfNotExist(dirPath); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if success, err = testOpen(dirPath); err != nil {
|
||||||
|
return
|
||||||
|
} else if !success {
|
||||||
|
err = ErrInvalidFile
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Loggers[identifier] = &FileLogger{
|
||||||
|
StdLogger: StdLogger{
|
||||||
|
Logger: nil,
|
||||||
|
EnableDebug: m.EnableDebug,
|
||||||
|
Prefix: m.Prefix,
|
||||||
|
},
|
||||||
|
Path: logfilePath,
|
||||||
|
}
|
||||||
|
m.Loggers[identifier].Setup()
|
||||||
|
|
||||||
|
m.Loggers[identifier].Info("logger initialized of type %T with prefix %v", m.Loggers[identifier], m.Loggers[identifier].GetPrefix())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveLogger will let you remove a Logger from MultiLogger.Loggers.
|
||||||
|
func (m *MultiLogger) RemoveLogger(identifier string) (err error) {
|
||||||
|
|
||||||
|
var exists bool
|
||||||
|
|
||||||
|
if _, exists = m.Loggers[identifier]; !exists {
|
||||||
|
err = ErrNoEntry
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(m.Loggers, identifier)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
118
logging/funcs_multilogger_mgr_linux.go
Normal file
118
logging/funcs_multilogger_mgr_linux.go
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
package logging
|
||||||
|
|
||||||
|
import (
|
||||||
|
`os`
|
||||||
|
|
||||||
|
sysd `github.com/coreos/go-systemd/journal`
|
||||||
|
`github.com/google/uuid`
|
||||||
|
`r00t2.io/sysutils/paths`
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
AddDefaultLogger adds a default Logger (as would be determined by GetLogger) to a MultiLogger.
|
||||||
|
|
||||||
|
identifier is a string to use to identify the added Logger in MultiLogger.Loggers.
|
||||||
|
If empty, one will be automatically generated.
|
||||||
|
*/
|
||||||
|
func (m *MultiLogger) AddDefaultLogger(identifier string, logPaths ...string) (err error) {
|
||||||
|
|
||||||
|
var l Logger
|
||||||
|
var exists bool
|
||||||
|
|
||||||
|
if identifier == "" {
|
||||||
|
identifier = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists = m.Loggers[identifier]; exists {
|
||||||
|
err = ErrExistingLogger
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if l, err = GetLogger(m.EnableDebug, m.Prefix, logPaths...); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Loggers[identifier] = l
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
AddSysdLogger adds a SystemDLogger to a MultiLogger.
|
||||||
|
|
||||||
|
identifier is a string to use to identify the added SystemDLogger in MultiLogger.Loggers.
|
||||||
|
If empty, one will be automatically generated.
|
||||||
|
*/
|
||||||
|
func (m *MultiLogger) AddSysdLogger(identifier string) (err error) {
|
||||||
|
|
||||||
|
var exists bool
|
||||||
|
|
||||||
|
if identifier == "" {
|
||||||
|
identifier = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists = m.Loggers[identifier]; exists {
|
||||||
|
err = ErrExistingLogger
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !sysd.Enabled() {
|
||||||
|
err = ErrNoSysD
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Loggers[identifier] = &SystemDLogger{
|
||||||
|
EnableDebug: m.EnableDebug,
|
||||||
|
Prefix: m.Prefix,
|
||||||
|
}
|
||||||
|
m.Loggers[identifier].Setup()
|
||||||
|
|
||||||
|
m.Loggers[identifier].Info("logger initialized of type %T with prefix %v", m.Loggers[identifier], m.Loggers[identifier].GetPrefix())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
AddSyslogLogger adds a SyslogLogger to a MultiLogger.
|
||||||
|
|
||||||
|
identifier is a string to use to identify the added SyslogLogger in MultiLogger.Loggers.
|
||||||
|
If empty, one will be automatically generated.
|
||||||
|
*/
|
||||||
|
func (m *MultiLogger) AddSyslogLogger(identifier string) (err error) {
|
||||||
|
|
||||||
|
var exists bool
|
||||||
|
var hasSyslog bool
|
||||||
|
var stat os.FileInfo
|
||||||
|
var devlogPath string = devlog
|
||||||
|
|
||||||
|
if identifier == "" {
|
||||||
|
identifier = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists = m.Loggers[identifier]; exists {
|
||||||
|
err = ErrExistingLogger
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasSyslog, stat, err = paths.RealPathExistsStat(&devlogPath); hasSyslog && err != nil {
|
||||||
|
return
|
||||||
|
} else if !hasSyslog {
|
||||||
|
err = ErrNoSyslog
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if stat.Mode().IsRegular() {
|
||||||
|
err = ErrInvalidDevLog
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Loggers[identifier] = &SyslogLogger{
|
||||||
|
EnableDebug: m.EnableDebug,
|
||||||
|
Prefix: m.Prefix,
|
||||||
|
}
|
||||||
|
m.Loggers[identifier].Setup()
|
||||||
|
|
||||||
|
m.Loggers[identifier].Info("logger initialized of type %T with prefix %v", m.Loggers[identifier], m.Loggers[identifier].GetPrefix())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
84
logging/funcs_multilogger_mgr_windows.go
Normal file
84
logging/funcs_multilogger_mgr_windows.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package logging
|
||||||
|
|
||||||
|
/*
|
||||||
|
AddDefaultLogger adds a default Logger (as would be determined by GetLogger) to a MultiLogger.
|
||||||
|
|
||||||
|
identifier is a string to use to identify the added Logger in MultiLogger.Loggers.
|
||||||
|
If empty, one will be automatically generated.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
Currently this will almost always return a WinLogger.
|
||||||
|
*/
|
||||||
|
func (m *MultiLogger) AddDefaultLogger(identifier string, eventIDs *WinEventID) (err error) {
|
||||||
|
|
||||||
|
var l Logger
|
||||||
|
var exists bool
|
||||||
|
|
||||||
|
if identifier == "" {
|
||||||
|
identifier = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists = m.Loggers[identifier]; exists {
|
||||||
|
err = ErrExistingLogger
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if l, err = GetLogger(m.EnableDebug, m.Prefix, eventIDs, logPaths...); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Loggers[identifier] = l
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
AddWinLogger adds a WinLogger to a MultiLogger. Note that this is a VERY generalized interface to the Windows Event Log.
|
||||||
|
|
||||||
|
If you require more robust logging capabilities (e.g. custom event IDs per uniquely identifiable event),
|
||||||
|
you will want to set up your own logger (golang.org/x/sys/windows/svc/eventlog).
|
||||||
|
|
||||||
|
identifier is a string to use to identify the added WinLogger in MultiLogger.Loggers.
|
||||||
|
If empty, one will be automatically generated.
|
||||||
|
|
||||||
|
A blank source will return an error as it's used as the source name. Other functions, struct fields, etc. will refer to this as the "prefix".
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
See GetLogger for details.
|
||||||
|
*/
|
||||||
|
func (m *MultiLogger) AddWinLogger(identifier, source string, eventIDs *WinEventID) (err error) {
|
||||||
|
|
||||||
|
var exists bool
|
||||||
|
|
||||||
|
if identifier == "" {
|
||||||
|
identifier = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists = m.Loggers[identifier]; exists {
|
||||||
|
err = ErrExistingLogger
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if eventIDs == nil {
|
||||||
|
eventIDs = DefaultEventID
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Loggers[identifier] = &WinLogger{
|
||||||
|
Prefix: source,
|
||||||
|
EnableDebug: m.EnableDebug,
|
||||||
|
eids: eventIDs,
|
||||||
|
}
|
||||||
|
m.Loggers[identifier].Setup()
|
||||||
|
|
||||||
|
m.Loggers[identifier].Info("logger initialized of type %T with prefix %v", m.Loggers[identifier], m.Loggers[identifier].GetPrefix())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
@ -5,12 +5,14 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Setup sets up/configures a StdLogger and prepares it for use.
|
||||||
func (l *StdLogger) Setup() {
|
func (l *StdLogger) Setup() {
|
||||||
|
|
||||||
l.Logger = log.Default()
|
l.Logger = log.Default()
|
||||||
l.Logger.SetPrefix(l.Prefix)
|
l.Logger.SetPrefix(l.Prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown cleanly shuts down a StdLogger.
|
||||||
func (l *StdLogger) Shutdown() {
|
func (l *StdLogger) Shutdown() {
|
||||||
|
|
||||||
// NOOP
|
// NOOP
|
||||||
@ -18,15 +20,7 @@ func (l *StdLogger) Shutdown() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *StdLogger) DoDebug(d bool) {
|
// GetPrefix returns the prefix used by this StdLogger.
|
||||||
l.EnableDebug = d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *StdLogger) SetPrefix(prefix string) {
|
|
||||||
l.Prefix = prefix
|
|
||||||
l.Logger.SetPrefix(prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *StdLogger) GetPrefix() (prefix string) {
|
func (l *StdLogger) GetPrefix() (prefix string) {
|
||||||
|
|
||||||
prefix = l.Prefix
|
prefix = l.Prefix
|
||||||
@ -34,6 +28,21 @@ func (l *StdLogger) GetPrefix() (prefix string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
func (l *StdLogger) DoDebug(d bool) {
|
||||||
|
l.EnableDebug = d
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPrefix sets the prefix for this StdLogger.
|
||||||
|
func (l *StdLogger) SetPrefix(prefix string) {
|
||||||
|
l.Prefix = prefix
|
||||||
|
l.Logger.SetPrefix(prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alert writes an ALERT-level message to this StdLogger.
|
||||||
func (l *StdLogger) Alert(s string, v ...interface{}) (err error) {
|
func (l *StdLogger) Alert(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -49,6 +58,7 @@ func (l *StdLogger) Alert(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crit writes an CRITICAL-level message to this StdLogger.
|
||||||
func (l *StdLogger) Crit(s string, v ...interface{}) (err error) {
|
func (l *StdLogger) Crit(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -64,6 +74,7 @@ func (l *StdLogger) Crit(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug writes a DEBUG-level message to this StdLogger.
|
||||||
func (l *StdLogger) Debug(s string, v ...interface{}) (err error) {
|
func (l *StdLogger) Debug(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
if !l.EnableDebug {
|
if !l.EnableDebug {
|
||||||
@ -83,6 +94,7 @@ func (l *StdLogger) Debug(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emerg writes an EMERGENCY-level message to this StdLogger.
|
||||||
func (l *StdLogger) Emerg(s string, v ...interface{}) (err error) {
|
func (l *StdLogger) Emerg(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -98,6 +110,7 @@ func (l *StdLogger) Emerg(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Err writes an ERROR-level message to this StdLogger.
|
||||||
func (l *StdLogger) Err(s string, v ...interface{}) (err error) {
|
func (l *StdLogger) Err(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -113,6 +126,7 @@ func (l *StdLogger) Err(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info writes an INFO-level message to this StdLogger.
|
||||||
func (l *StdLogger) Info(s string, v ...interface{}) (err error) {
|
func (l *StdLogger) Info(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -128,6 +142,7 @@ func (l *StdLogger) Info(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notice writes a NOTICE-level message to this StdLogger.
|
||||||
func (l *StdLogger) Notice(s string, v ...interface{}) (err error) {
|
func (l *StdLogger) Notice(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -143,6 +158,7 @@ func (l *StdLogger) Notice(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Warning writes a WARNING/WARN-level message to this StdLogger.
|
||||||
func (l *StdLogger) Warning(s string, v ...interface{}) (err error) {
|
func (l *StdLogger) Warning(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -158,6 +174,7 @@ func (l *StdLogger) Warning(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renderWrite prepares/formats a log message to be written to this StdLogger.
|
||||||
func (l *StdLogger) renderWrite(msg, prio string) {
|
func (l *StdLogger) renderWrite(msg, prio string) {
|
||||||
|
|
||||||
s := fmt.Sprintf("[%v] %v", prio, msg)
|
s := fmt.Sprintf("[%v] %v", prio, msg)
|
||||||
|
@ -7,6 +7,7 @@ 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() {
|
func (l *SystemDLogger) Setup() {
|
||||||
|
|
||||||
// NOOP
|
// NOOP
|
||||||
@ -14,6 +15,7 @@ func (l *SystemDLogger) Setup() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown cleanly shuts down a SystemDLogger.
|
||||||
func (l *SystemDLogger) Shutdown() {
|
func (l *SystemDLogger) Shutdown() {
|
||||||
|
|
||||||
// NOOP
|
// NOOP
|
||||||
@ -21,14 +23,7 @@ func (l *SystemDLogger) Shutdown() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *SystemDLogger) DoDebug(d bool) {
|
// GetPrefix returns the prefix used by this SystemDLogger.
|
||||||
l.EnableDebug = d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *SystemDLogger) SetPrefix(prefix string) {
|
|
||||||
l.Prefix = prefix
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *SystemDLogger) GetPrefix() (prefix string) {
|
func (l *SystemDLogger) GetPrefix() (prefix string) {
|
||||||
|
|
||||||
prefix = l.Prefix
|
prefix = l.Prefix
|
||||||
@ -36,6 +31,20 @@ func (l *SystemDLogger) GetPrefix() (prefix string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
func (l *SystemDLogger) DoDebug(d bool) {
|
||||||
|
l.EnableDebug = d
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPrefix sets the prefix for this SystemDLogger.
|
||||||
|
func (l *SystemDLogger) SetPrefix(prefix string) {
|
||||||
|
l.Prefix = prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alert writes an ALERT-level message to this SystemDLogger.
|
||||||
func (l *SystemDLogger) Alert(s string, v ...interface{}) (err error) {
|
func (l *SystemDLogger) Alert(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -51,6 +60,7 @@ func (l *SystemDLogger) Alert(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crit writes an CRITICAL-level message to this SystemDLogger.
|
||||||
func (l *SystemDLogger) Crit(s string, v ...interface{}) (err error) {
|
func (l *SystemDLogger) Crit(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -66,6 +76,7 @@ func (l *SystemDLogger) Crit(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug writes a DEBUG-level message to this SystemDLogger.
|
||||||
func (l *SystemDLogger) Debug(s string, v ...interface{}) (err error) {
|
func (l *SystemDLogger) Debug(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
if !l.EnableDebug {
|
if !l.EnableDebug {
|
||||||
@ -85,6 +96,7 @@ func (l *SystemDLogger) Debug(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emerg writes an EMERGENCY-level message to this SystemDLogger.
|
||||||
func (l *SystemDLogger) Emerg(s string, v ...interface{}) (err error) {
|
func (l *SystemDLogger) Emerg(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -100,6 +112,7 @@ func (l *SystemDLogger) Emerg(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Err writes an ERROR-level message to this SystemDLogger.
|
||||||
func (l *SystemDLogger) Err(s string, v ...interface{}) (err error) {
|
func (l *SystemDLogger) Err(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -115,6 +128,7 @@ func (l *SystemDLogger) Err(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info writes an INFO-level message to this SystemDLogger.
|
||||||
func (l *SystemDLogger) Info(s string, v ...interface{}) (err error) {
|
func (l *SystemDLogger) Info(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -130,6 +144,7 @@ func (l *SystemDLogger) Info(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notice writes a NOTICE-level message to this SystemDLogger.
|
||||||
func (l *SystemDLogger) Notice(s string, v ...interface{}) (err error) {
|
func (l *SystemDLogger) Notice(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -145,6 +160,7 @@ func (l *SystemDLogger) Notice(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Warning writes a WARNING/WARN-level message to this SystemDLogger.
|
||||||
func (l *SystemDLogger) Warning(s string, v ...interface{}) (err error) {
|
func (l *SystemDLogger) Warning(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -160,6 +176,7 @@ func (l *SystemDLogger) Warning(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renderWrite prepares/formats a log message to be written to this SystemDLogger.
|
||||||
func (l *SystemDLogger) renderWrite(msg string, prio journal.Priority) {
|
func (l *SystemDLogger) renderWrite(msg string, prio journal.Priority) {
|
||||||
|
|
||||||
// TODO: implement code line, etc.
|
// TODO: implement code line, etc.
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"log/syslog"
|
"log/syslog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Setup sets up/configures a SyslogLogger and prepares it for use.
|
||||||
func (l *SyslogLogger) Setup() {
|
func (l *SyslogLogger) Setup() {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -37,6 +38,7 @@ func (l *SyslogLogger) Setup() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown cleanly shuts down a SyslogLogger.
|
||||||
func (l *SyslogLogger) Shutdown() {
|
func (l *SyslogLogger) Shutdown() {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -49,15 +51,7 @@ func (l *SyslogLogger) Shutdown() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *SyslogLogger) DoDebug(d bool) {
|
// GetPrefix returns the prefix used by this SyslogLogger.
|
||||||
l.EnableDebug = d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *SyslogLogger) SetPrefix(prefix string) {
|
|
||||||
l.Prefix = prefix
|
|
||||||
l.Setup()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *SyslogLogger) GetPrefix() (prefix string) {
|
func (l *SyslogLogger) GetPrefix() (prefix string) {
|
||||||
|
|
||||||
prefix = l.Prefix
|
prefix = l.Prefix
|
||||||
@ -65,6 +59,21 @@ func (l *SyslogLogger) GetPrefix() (prefix string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
func (l *SyslogLogger) DoDebug(d bool) {
|
||||||
|
l.EnableDebug = d
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPrefix sets the prefix for this SyslogLogger.
|
||||||
|
func (l *SyslogLogger) SetPrefix(prefix string) {
|
||||||
|
l.Prefix = prefix
|
||||||
|
l.Setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alert writes an ALERT-level message to this SyslogLogger.
|
||||||
func (l *SyslogLogger) Alert(s string, v ...interface{}) (err error) {
|
func (l *SyslogLogger) Alert(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -82,6 +91,7 @@ func (l *SyslogLogger) Alert(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crit writes an CRITICAL-level message to this SyslogLogger.
|
||||||
func (l *SyslogLogger) Crit(s string, v ...interface{}) (err error) {
|
func (l *SyslogLogger) Crit(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -99,6 +109,7 @@ func (l *SyslogLogger) Crit(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug writes a DEBUG-level message to this SyslogLogger.
|
||||||
func (l *SyslogLogger) Debug(s string, v ...interface{}) (err error) {
|
func (l *SyslogLogger) Debug(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
if !l.EnableDebug {
|
if !l.EnableDebug {
|
||||||
@ -120,6 +131,7 @@ func (l *SyslogLogger) Debug(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emerg writes an EMERGENCY-level message to this SyslogLogger.
|
||||||
func (l *SyslogLogger) Emerg(s string, v ...interface{}) (err error) {
|
func (l *SyslogLogger) Emerg(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -137,6 +149,7 @@ func (l *SyslogLogger) Emerg(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Err writes an ERROR-level message to this SyslogLogger.
|
||||||
func (l *SyslogLogger) Err(s string, v ...interface{}) (err error) {
|
func (l *SyslogLogger) Err(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -154,6 +167,7 @@ func (l *SyslogLogger) Err(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info writes an INFO-level message to this SyslogLogger.
|
||||||
func (l *SyslogLogger) Info(s string, v ...interface{}) (err error) {
|
func (l *SyslogLogger) Info(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -171,6 +185,7 @@ func (l *SyslogLogger) Info(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notice writes a NOTICE-level message to this SyslogLogger.
|
||||||
func (l *SyslogLogger) Notice(s string, v ...interface{}) (err error) {
|
func (l *SyslogLogger) Notice(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -188,6 +203,7 @@ func (l *SyslogLogger) Notice(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Warning writes a WARNING/WARN-level message to this SyslogLogger.
|
||||||
func (l *SyslogLogger) Warning(s string, v ...interface{}) (err error) {
|
func (l *SyslogLogger) Warning(s string, v ...interface{}) (err error) {
|
||||||
var msg string
|
var msg string
|
||||||
|
|
||||||
|
@ -7,21 +7,31 @@ import (
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
GetLogger returns an instance of Logger that best suits your system's capabilities. Note that this is a VERY generalized interface to the Windows Event Log.
|
GetLogger returns an instance of Logger that best suits your system's capabilities. Note that this is a VERY generalized interface to the Windows Event Log.
|
||||||
|
|
||||||
If you require more robust logging capabilities (e.g. custom event IDs per uniquely identifiable event),
|
If you require more robust logging capabilities (e.g. custom event IDs per uniquely identifiable event),
|
||||||
you will want to set up your own logger (golang.org/x/sys/windows/svc/eventlog).
|
you will want to set up your own logger (golang.org/x/sys/windows/svc/eventlog).
|
||||||
|
|
||||||
If enableDebug is true, debug messages (which according to your program may or may not contain sensitive data) are rendered and written (otherwise they are ignored).
|
If enableDebug is true, debug messages (which according to your program may or may not contain sensitive data) are rendered and written (otherwise they are ignored).
|
||||||
|
|
||||||
A blank source will return an error as it's used as the source name. Other functions, struct fields, etc. will refer to this as the "prefix".
|
A blank source will return an error as it's used as the source name. Other functions, struct fields, etc. will refer to this as the "prefix".
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
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).
|
||||||
|
|
||||||
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 until multiple logging destination support is added.
|
Currently this will almost always return a WinLogger.
|
||||||
|
|
||||||
|
If you call GetLogger, you will only get a single ("best") logger your system supports.
|
||||||
|
If you want to log to multiple Logger destinations at once (or want to log to an explicit Logger type),
|
||||||
|
use GetMultiLogger.
|
||||||
*/
|
*/
|
||||||
func GetLogger(enableDebug bool, source string, eventIDs *WinEventID, logPaths ...string) (logger Logger, err error) {
|
func GetLogger(enableDebug bool, source string, eventIDs *WinEventID, logPaths ...string) (logger Logger, err error) {
|
||||||
|
|
||||||
var logPath string
|
var logPath string
|
||||||
var logFlags types.MaskBit
|
var logFlags bitmask.MaskBit
|
||||||
var exists bool
|
var exists bool
|
||||||
var success bool
|
var success bool
|
||||||
var ckLogPaths []string
|
var ckLogPaths []string
|
||||||
@ -53,7 +63,7 @@ func GetLogger(enableDebug bool, source string, eventIDs *WinEventID, logPaths .
|
|||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
dirPath := path.Dir(p)
|
dirPath := path.Dir(p)
|
||||||
if err = paths.MakeDirIfNotExist(&dirPath); err != nil {
|
if err = paths.MakeDirIfNotExist(dirPath); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if success, err = testOpen(p); err != nil {
|
if success, err = testOpen(p); err != nil {
|
||||||
|
@ -2,8 +2,11 @@ package logging
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
`errors`
|
`errors`
|
||||||
|
|
||||||
|
`golang.org/x/sys/windows/svc/eventlog`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Setup sets up/configures a WinLogger and prepares it for use.
|
||||||
func (l *WinLogger) Setup() {
|
func (l *WinLogger) Setup() {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -44,6 +47,7 @@ func (l *WinLogger) Setup() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown cleanly shuts down a WinLogger.
|
||||||
func (l *WinLogger) Shutdown() {
|
func (l *WinLogger) Shutdown() {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -58,12 +62,25 @@ func (l *WinLogger) Shutdown() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPrefix returns the prefix used by this WinLogger.
|
||||||
|
func (l *WinLogger) GetPrefix() (prefix string) {
|
||||||
|
|
||||||
|
prefix = l.Prefix
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
func (l *WinLogger) DoDebug(d bool) {
|
func (l *WinLogger) DoDebug(d bool) {
|
||||||
|
|
||||||
l.EnableDebug = d
|
l.EnableDebug = d
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPrefix sets the prefix for this WinLogger.
|
||||||
func (l *WinLogger) SetPrefix(prefix string) {
|
func (l *WinLogger) SetPrefix(prefix string) {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -95,13 +112,7 @@ func (l *WinLogger) SetPrefix(prefix string) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *WinLogger) GetPrefix() (prefix string) {
|
// Alert writes an ALERT-level message to this WinLogger.
|
||||||
|
|
||||||
prefix = l.Prefix
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *WinLogger) Alert(s string, v ...interface{}) (err error) {
|
func (l *WinLogger) Alert(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -118,6 +129,7 @@ func (l *WinLogger) Alert(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crit writes an CRITICAL-level message to this WinLogger.
|
||||||
func (l *WinLogger) Crit(s string, v ...interface{}) (err error) {
|
func (l *WinLogger) Crit(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -134,6 +146,7 @@ func (l *WinLogger) Crit(s string, v ...interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug writes a DEBUG-level message to this WinLogger.
|
||||||
func (l *WinLogger) Debug(s string, v ...interface{}) (err error) {
|
func (l *WinLogger) Debug(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
if !l.EnableDebug {
|
if !l.EnableDebug {
|
||||||
@ -155,6 +168,7 @@ func (l *WinLogger) Debug(s string, v ...interface{}) (err error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emerg writes an EMERGENCY-level message to this WinLogger.
|
||||||
func (l *WinLogger) Emerg(s string, v ...interface{}) (err error) {
|
func (l *WinLogger) Emerg(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -172,6 +186,7 @@ func (l *WinLogger) Emerg(s string, v ...interface{}) (err error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Err writes an ERROR-level message to this WinLogger.
|
||||||
func (l *WinLogger) Err(s string, v ...interface{}) (err error) {
|
func (l *WinLogger) Err(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -188,6 +203,7 @@ func (l *WinLogger) Err(s string, v ...interface{}) (err error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info writes an INFO-level message to this WinLogger.
|
||||||
func (l *WinLogger) Info(s string, v ...interface{}) (err error) {
|
func (l *WinLogger) Info(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -204,6 +220,7 @@ func (l *WinLogger) Info(s string, v ...interface{}) (err error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notice writes a NOTICE-level message to this WinLogger.
|
||||||
func (l *WinLogger) Notice(s string, v ...interface{}) (err error) {
|
func (l *WinLogger) Notice(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
@ -221,6 +238,7 @@ func (l *WinLogger) Notice(s string, v ...interface{}) (err error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Warning writes a WARNING/WARN-level message to this WinLogger.
|
||||||
func (l *WinLogger) Warning(s string, v ...interface{}) (err error) {
|
func (l *WinLogger) Warning(s string, v ...interface{}) (err error) {
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
|
@ -5,30 +5,60 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Logger is one of the various loggers offered by this module.
|
||||||
|
*/
|
||||||
type Logger interface {
|
type Logger interface {
|
||||||
Alert(string, ...interface{}) error
|
Alert(s string, v ...interface{}) (err error)
|
||||||
Crit(string, ...interface{}) error
|
Crit(s string, v ...interface{}) (err error)
|
||||||
Debug(string, ...interface{}) error
|
Debug(s string, v ...interface{}) (err error)
|
||||||
Emerg(string, ...interface{}) error
|
Emerg(s string, v ...interface{}) (err error)
|
||||||
Err(string, ...interface{}) error
|
Err(s string, v ...interface{}) (err error)
|
||||||
Info(string, ...interface{}) error
|
Info(s string, v ...interface{}) (err error)
|
||||||
Notice(string, ...interface{}) error
|
Notice(s string, v ...interface{}) (err error)
|
||||||
Warning(string, ...interface{}) error
|
Warning(s string, v ...interface{}) (err error)
|
||||||
DoDebug(bool)
|
DoDebug(d bool)
|
||||||
SetPrefix(string)
|
SetPrefix(p string)
|
||||||
GetPrefix() string
|
GetPrefix() (p string)
|
||||||
Setup()
|
Setup()
|
||||||
Shutdown()
|
Shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StdLogger uses the log package in stdlib to perform all logging.
|
||||||
type StdLogger struct {
|
type StdLogger struct {
|
||||||
|
// All log.Logger fields/methods are exposed.
|
||||||
*log.Logger
|
*log.Logger
|
||||||
|
/*
|
||||||
|
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 string
|
// Prefix indicates the prefix for log entries; in shared logs, this helps differentiate the source.
|
||||||
|
Prefix string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FileLogger uses a StdLogger with a file handle writer to write to the file given at Path.
|
||||||
type FileLogger struct {
|
type FileLogger struct {
|
||||||
|
// StdLogger is used for the log formation and handling.
|
||||||
StdLogger
|
StdLogger
|
||||||
Path string
|
// Path is the path to the logfile.
|
||||||
|
Path string
|
||||||
|
// writer is used for the writing out of the log file.
|
||||||
writer *os.File
|
writer *os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MultiLogger is used to contain one or more Loggers and present them all as a single Logger.
|
||||||
|
type MultiLogger 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
|
||||||
|
// Prefix indicates the prefix for log entries; in shared logs, this helps differentiate the source.
|
||||||
|
Prefix string
|
||||||
|
/*
|
||||||
|
Loggers contains a map of map[logname]Logger. It can be used to set log-specific options, or replace a Logger
|
||||||
|
with one of a different type or options.
|
||||||
|
*/
|
||||||
|
Loggers map[string]Logger
|
||||||
|
}
|
||||||
|
58
multierr/doc.go
Normal file
58
multierr/doc.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Package multierr provides a simple way of handling multiple errors and consolidating them into a single error.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
`r00t2.io/goutils/multierr`
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var errs []error
|
||||||
|
|
||||||
|
errs = make([]error, 0)
|
||||||
|
|
||||||
|
for _, i := range someSlice {
|
||||||
|
go func() {
|
||||||
|
if err = i.DoSomething(); err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
if errs != nil && len(errs) != 0 {
|
||||||
|
// err now contains multiple errors presented as a single error.
|
||||||
|
err = multierr.NewErrors(errs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiError also has a shorthand, making the above much less verbose:
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
`r00t2.io/goutils/multierr`
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var multierror *multierr.MultiError = multierr.NewMultiError(nil)
|
||||||
|
|
||||||
|
for _, i := range someSlice {
|
||||||
|
go func() {
|
||||||
|
if err = i.DoSomething(); err != nil {
|
||||||
|
multierror.AddError(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
// multierror now contains any/all errors above.
|
||||||
|
}
|
||||||
|
|
||||||
|
In the above, the multierror assignment can still be used as an error.
|
||||||
|
*/
|
||||||
|
package multierr
|
85
multierr/funcs.go
Normal file
85
multierr/funcs.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package multierr
|
||||||
|
|
||||||
|
import (
|
||||||
|
`fmt`
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
NewErrors returns a new MultiError (as an error) based on/initialized with a slice of error.Error (errs).
|
||||||
|
Any nil errors are trimmed.
|
||||||
|
If there are no actual errors after trimming, err will be nil.
|
||||||
|
*/
|
||||||
|
func NewErrors(errs ...error) (err error) {
|
||||||
|
|
||||||
|
if errs == nil || len(errs) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var realErrs []error = make([]error, 0)
|
||||||
|
|
||||||
|
for _, e := range errs {
|
||||||
|
if e == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
realErrs = append(realErrs, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(realErrs) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = &MultiError{
|
||||||
|
Errors: realErrs,
|
||||||
|
ErrorSep: "\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMultiError will provide a MultiError (true type), optionally initialized with errors.
|
||||||
|
func NewMultiError(errs ...error) (m *MultiError) {
|
||||||
|
|
||||||
|
if errs == nil {
|
||||||
|
errs = make([]error, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
m = &MultiError{
|
||||||
|
Errors: errs,
|
||||||
|
ErrorSep: "\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns a string representation of a MultiError (to conform with the error interface).
|
||||||
|
func (e *MultiError) Error() (errStr string) {
|
||||||
|
|
||||||
|
var numErrs int
|
||||||
|
|
||||||
|
if e == nil || len(e.Errors) == 0 {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
numErrs = len(e.Errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, err := range e.Errors {
|
||||||
|
if (idx + 1) < numErrs {
|
||||||
|
errStr += fmt.Sprintf("%v%v", err.Error(), e.ErrorSep)
|
||||||
|
} else {
|
||||||
|
errStr += err.Error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddError is a shorthand way of adding an error to a MultiError.
|
||||||
|
func (e *MultiError) AddError(err error) {
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Errors = append(e.Errors, err)
|
||||||
|
|
||||||
|
}
|
9
multierr/types.go
Normal file
9
multierr/types.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package multierr
|
||||||
|
|
||||||
|
// MultiError is a type of error.Error that can contain multiple errors.
|
||||||
|
type MultiError struct {
|
||||||
|
// Errors is a slice of errors to combine/concatenate when .Error() is called.
|
||||||
|
Errors []error `json:"errors"`
|
||||||
|
// ErrorSep is a string to use to separate errors for .Error(). The default is "\n".
|
||||||
|
ErrorSep string `json:"separator"`
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user