Better domain handling in logging.

This commit is contained in:
Kyle Isom 2015-09-22 13:26:06 -07:00
parent 4b3f1037b3
commit ea689c7e97
3 changed files with 102 additions and 29 deletions

View File

@ -3,7 +3,7 @@ package logging_test
import "github.com/kisom/goutils/logging"
var log = logging.Init()
var olog = logging.New("subsystem #42", logging.LevelNotice)
var olog, _ = logging.New("subsystem #42", logging.LevelNotice)
func Example() {
log.Notice("Hello, world.")

View File

@ -64,7 +64,7 @@ var levelPrefix = [...]string{
var DateFormat = "2006-01-02T15:03:04-0700"
func (l *Logger) outputf(level Level, format string, v []interface{}) {
if !logConfig.registered[l.domain] {
if !l.Enabled() {
return
}
@ -81,7 +81,7 @@ func (l *Logger) outputf(level Level, format string, v []interface{}) {
}
func (l *Logger) output(level Level, v []interface{}) {
if !logConfig.registered[l.domain] {
if !l.Enabled() {
return
}

View File

@ -9,16 +9,17 @@ import (
"io"
"os"
"path/filepath"
"strings"
"sync"
"github.com/kisom/goutils/mwc"
)
var logConfig = struct {
registered map[string]bool
registered map[string]*Logger
lock *sync.Mutex
}{
registered: map[string]bool{},
registered: map[string]*Logger{},
lock: new(sync.Mutex),
}
@ -28,16 +29,19 @@ 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)
l, _ := New(filepath.Base(os.Args[0]), DefaultLevel)
return l
}
// 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
enabled bool
lock *sync.Mutex
domain string
level Level
out io.WriteCloser
err io.WriteCloser
}
// Close closes the log's writers and suppresses the logger.
@ -55,15 +59,30 @@ func (l *Logger) Close() error {
func Suppress(domain string) {
logConfig.lock.Lock()
defer logConfig.lock.Unlock()
logConfig.registered[domain] = false
l, ok := logConfig.registered[domain]
if ok {
l.Suppress()
}
}
// SuppressPrefix suppress logs whose domain is prefixed with the
// prefix.
func SuppressPrefix(prefix string) {
logConfig.lock.Lock()
defer logConfig.lock.Unlock()
for domain, l := range logConfig.registered {
if strings.HasPrefix(domain, prefix) {
l.Suppress()
}
}
}
// SuppressAll suppresses all logging output.
func SuppressAll() {
logConfig.lock.Lock()
defer logConfig.lock.Unlock()
for domain := range logConfig.registered {
logConfig.registered[domain] = false
for _, l := range logConfig.registered {
l.Suppress()
}
}
@ -71,48 +90,90 @@ func SuppressAll() {
func Enable(domain string) {
logConfig.lock.Lock()
defer logConfig.lock.Unlock()
logConfig.registered[domain] = true
l, ok := logConfig.registered[domain]
if ok {
l.Enable()
}
}
// EnablePrefix enables logs whose domain is prefixed with prefix.
func EnablePrefix(prefix string) {
logConfig.lock.Lock()
defer logConfig.lock.Unlock()
for domain, l := range logConfig.registered {
if strings.HasPrefix(domain, prefix) {
l.Enable()
}
}
}
// EnableAll enables all domains.
func EnableAll() {
logConfig.lock.Lock()
defer logConfig.lock.Unlock()
for domain := range logConfig.registered {
logConfig.registered[domain] = true
for _, l := range logConfig.registered {
l.Enable()
}
}
// 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{
// and below and standard error for levels above Notice. If a logger
// with the same domain exists, the logger will set its level to level
// and return the logger; in this case, the registered return value
// will be true.
func New(domain string, level Level) (l *Logger, registered bool) {
logConfig.lock.Lock()
defer logConfig.lock.Unlock()
l = logConfig.registered[domain]
if l != nil {
l.SetLevel(level)
return l, true
}
l = &Logger{
domain: domain,
level: level,
out: os.Stdout,
err: os.Stderr,
lock: new(sync.Mutex),
}
Enable(domain)
return l
l.Enable()
logConfig.registered[domain] = l
return l, false
}
// 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.
func NewFromWriters(domain string, level Level, w, e io.WriteCloser) *Logger {
// 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. If a logger with the same
// domain exists, the logger will set its level to level and return
// the logger; in this case, the registered return value will be true.
func NewFromWriters(domain string, level Level, w, e io.WriteCloser) (l *Logger, registered bool) {
logConfig.lock.Lock()
defer logConfig.lock.Unlock()
l = logConfig.registered[domain]
if l != nil {
l.SetLevel(level)
return l, true
}
if e == nil {
e = w
}
l := &Logger{
l = &Logger{
domain: domain,
level: level,
out: w,
err: e,
lock: new(sync.Mutex),
}
Enable(domain)
return l
l.Enable()
logConfig.registered[domain] = l
return l, false
}
// NewFile returns a new logger that opens the files for writing. If
@ -122,6 +183,7 @@ func NewFromFile(domain string, level Level, outFile, errFile string, multiplex
l := &Logger{
domain: domain,
level: level,
lock: new(sync.Mutex),
}
outf, err := os.OpenFile(outFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
@ -148,12 +210,21 @@ func NewFromFile(domain string, level Level, outFile, errFile string, multiplex
// Enable allows output from the logger.
func (l *Logger) Enable() {
Enable(l.domain)
l.lock.Lock()
defer l.lock.Unlock()
l.enabled = true
}
// Enabled returns true if the logger is enabled.
func (l *Logger) Enabled() bool {
return l.enabled
}
// Suppress ignores output from the logger.
func (l *Logger) Suppress() {
Suppress(l.domain)
l.lock.Lock()
defer l.lock.Unlock()
l.enabled = false
}
// Domain returns the domain of the logger.
@ -163,5 +234,7 @@ func (l *Logger) Domain() string {
// SetLevel changes the level of the logger.
func (l *Logger) SetLevel(level Level) {
l.lock.Lock()
defer l.lock.Unlock()
l.level = level
}