goutils/logging/log.go

168 lines
3.7 KiB
Go
Raw Normal View History

// Package logging is an adaptation of the CFSSL logging library. It
// operates on domains, which are components for which logging can be
// selectively enabled or disabled. It also differentiates between
// normal messages (which are sent to standard output) and errors,
// which are sent to standard error.
package logging
import (
"io"
"os"
"path/filepath"
"sync"
"github.com/kisom/goutils/mwc"
)
var logConfig = struct {
registered map[string]bool
lock *sync.Mutex
}{
registered: map[string]bool{},
lock: new(sync.Mutex),
}
// DefaultLevel defaults to the notice level of logging.
const DefaultLevel = LevelNotice
// Init returns a new default logger. The domain is set to the
// program's name, and the default logging level is used.
func Init() *Logger {
return New(filepath.Base(os.Args[0]), DefaultLevel)
}
// A Logger writes logs on behalf of a particular domain at a certain
// level.
type Logger struct {
domain string
level Level
out io.WriteCloser
err io.WriteCloser
}
// Close closes the log's writers and suppresses the logger.
func (l *Logger) Close() error {
Suppress(l.domain)
err := l.out.Close()
if err != nil {
return nil
}
return l.err.Close()
}
// Suppress ignores logs from a specific domain.
func Suppress(domain string) {
logConfig.lock.Lock()
defer logConfig.lock.Unlock()
logConfig.registered[domain] = false
}
// SuppressAll suppresses all logging output.
func SuppressAll() {
logConfig.lock.Lock()
defer logConfig.lock.Unlock()
for domain := range logConfig.registered {
logConfig.registered[domain] = false
}
}
// Enable enables logs from a specific domain.
func Enable(domain string) {
logConfig.lock.Lock()
defer logConfig.lock.Unlock()
logConfig.registered[domain] = true
}
// EnableAll enables all domains.
func EnableAll() {
logConfig.lock.Lock()
defer logConfig.lock.Unlock()
for domain := range logConfig.registered {
logConfig.registered[domain] = true
}
}
// New returns a new logger that writes to standard output for Notice
// and below and standard error for levels above Notice.
func New(domain string, level Level) *Logger {
l := &Logger{
domain: domain,
level: level,
out: os.Stdout,
err: os.Stderr,
}
Enable(domain)
return l
}
// NewWriters returns a new logger that writes to the w io.WriteCloser for
// Notice and below and to the e io.WriteCloser for levels above Notice. If e is nil, w will be used.
2015-09-22 10:43:33 +00:00
func NewFromWriters(domain string, level Level, w, e io.WriteCloser) *Logger {
if e == nil {
e = w
}
l := &Logger{
domain: domain,
level: level,
out: w,
err: e,
}
Enable(domain)
return l
}
// NewFile returns a new logger that opens the files for writing. If
// multiplex is true, output will be multiplexed to standard output
// and standard error as well.
2015-09-22 10:43:33 +00:00
func NewFromFile(domain string, level Level, outFile, errFile string, multiplex bool) (*Logger, error) {
l := &Logger{
domain: domain,
level: level,
}
2015-09-22 17:45:51 +00:00
outf, err := os.OpenFile(outFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return nil, err
}
2015-09-22 17:45:51 +00:00
errf, err := os.OpenFile(errFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return nil, err
}
if multiplex {
2015-09-22 17:45:51 +00:00
l.out = mwc.MultiWriteCloser(outf, os.Stdout)
l.err = mwc.MultiWriteCloser(errf, os.Stderr)
} else {
l.out = outf
l.err = errf
}
Enable(domain)
return l, nil
}
// Enable allows output from the logger.
func (l *Logger) Enable() {
Enable(l.domain)
}
// Suppress ignores output from the logger.
func (l *Logger) Suppress() {
Suppress(l.domain)
}
// Domain returns the domain of the logger.
func (l *Logger) Domain() string {
return l.domain
}
// SetLevel changes the level of the logger.
func (l *Logger) SetLevel(level Level) {
l.level = level
}