2015-09-22 10:27:14 +00:00
|
|
|
// 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 {
|
2015-09-22 10:27:14 +00:00
|
|
|
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) {
|
2015-09-22 10:27:14 +00:00
|
|
|
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)
|
2015-09-22 10:27:14 +00:00
|
|
|
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)
|
2015-09-22 10:27:14 +00:00
|
|
|
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
|
2015-09-22 10:27:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|