Better domain handling in logging.
This commit is contained in:
parent
4b3f1037b3
commit
ea689c7e97
|
@ -3,7 +3,7 @@ package logging_test
|
||||||
import "github.com/kisom/goutils/logging"
|
import "github.com/kisom/goutils/logging"
|
||||||
|
|
||||||
var log = logging.Init()
|
var log = logging.Init()
|
||||||
var olog = logging.New("subsystem #42", logging.LevelNotice)
|
var olog, _ = logging.New("subsystem #42", logging.LevelNotice)
|
||||||
|
|
||||||
func Example() {
|
func Example() {
|
||||||
log.Notice("Hello, world.")
|
log.Notice("Hello, world.")
|
||||||
|
|
|
@ -64,7 +64,7 @@ var levelPrefix = [...]string{
|
||||||
var DateFormat = "2006-01-02T15:03:04-0700"
|
var DateFormat = "2006-01-02T15:03:04-0700"
|
||||||
|
|
||||||
func (l *Logger) outputf(level Level, format string, v []interface{}) {
|
func (l *Logger) outputf(level Level, format string, v []interface{}) {
|
||||||
if !logConfig.registered[l.domain] {
|
if !l.Enabled() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ func (l *Logger) outputf(level Level, format string, v []interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logger) output(level Level, v []interface{}) {
|
func (l *Logger) output(level Level, v []interface{}) {
|
||||||
if !logConfig.registered[l.domain] {
|
if !l.Enabled() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
117
logging/log.go
117
logging/log.go
|
@ -9,16 +9,17 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/kisom/goutils/mwc"
|
"github.com/kisom/goutils/mwc"
|
||||||
)
|
)
|
||||||
|
|
||||||
var logConfig = struct {
|
var logConfig = struct {
|
||||||
registered map[string]bool
|
registered map[string]*Logger
|
||||||
lock *sync.Mutex
|
lock *sync.Mutex
|
||||||
}{
|
}{
|
||||||
registered: map[string]bool{},
|
registered: map[string]*Logger{},
|
||||||
lock: new(sync.Mutex),
|
lock: new(sync.Mutex),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,12 +29,15 @@ const DefaultLevel = LevelNotice
|
||||||
// Init returns a new default logger. The domain is set to the
|
// Init returns a new default logger. The domain is set to the
|
||||||
// program's name, and the default logging level is used.
|
// program's name, and the default logging level is used.
|
||||||
func Init() *Logger {
|
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
|
// A Logger writes logs on behalf of a particular domain at a certain
|
||||||
// level.
|
// level.
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
|
enabled bool
|
||||||
|
lock *sync.Mutex
|
||||||
domain string
|
domain string
|
||||||
level Level
|
level Level
|
||||||
out io.WriteCloser
|
out io.WriteCloser
|
||||||
|
@ -55,15 +59,30 @@ func (l *Logger) Close() error {
|
||||||
func Suppress(domain string) {
|
func Suppress(domain string) {
|
||||||
logConfig.lock.Lock()
|
logConfig.lock.Lock()
|
||||||
defer logConfig.lock.Unlock()
|
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.
|
// SuppressAll suppresses all logging output.
|
||||||
func SuppressAll() {
|
func SuppressAll() {
|
||||||
logConfig.lock.Lock()
|
logConfig.lock.Lock()
|
||||||
defer logConfig.lock.Unlock()
|
defer logConfig.lock.Unlock()
|
||||||
for domain := range logConfig.registered {
|
for _, l := range logConfig.registered {
|
||||||
logConfig.registered[domain] = false
|
l.Suppress()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,48 +90,90 @@ func SuppressAll() {
|
||||||
func Enable(domain string) {
|
func Enable(domain string) {
|
||||||
logConfig.lock.Lock()
|
logConfig.lock.Lock()
|
||||||
defer logConfig.lock.Unlock()
|
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.
|
// EnableAll enables all domains.
|
||||||
func EnableAll() {
|
func EnableAll() {
|
||||||
logConfig.lock.Lock()
|
logConfig.lock.Lock()
|
||||||
defer logConfig.lock.Unlock()
|
defer logConfig.lock.Unlock()
|
||||||
for domain := range logConfig.registered {
|
for _, l := range logConfig.registered {
|
||||||
logConfig.registered[domain] = true
|
l.Enable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new logger that writes to standard output for Notice
|
// New returns a new logger that writes to standard output for Notice
|
||||||
// and below and standard error for levels above Notice.
|
// and below and standard error for levels above Notice. If a logger
|
||||||
func New(domain string, level Level) *Logger {
|
// with the same domain exists, the logger will set its level to level
|
||||||
l := &Logger{
|
// 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,
|
domain: domain,
|
||||||
level: level,
|
level: level,
|
||||||
out: os.Stdout,
|
out: os.Stdout,
|
||||||
err: os.Stderr,
|
err: os.Stderr,
|
||||||
|
lock: new(sync.Mutex),
|
||||||
}
|
}
|
||||||
|
|
||||||
Enable(domain)
|
l.Enable()
|
||||||
return l
|
logConfig.registered[domain] = l
|
||||||
|
return l, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWriters returns a new logger that writes to the w io.WriteCloser for
|
// NewWriters returns a new logger that writes to the w io.WriteCloser
|
||||||
// Notice and below and to the e io.WriteCloser for levels above Notice. If e is nil, w will be used.
|
// for Notice and below and to the e io.WriteCloser for levels above
|
||||||
func NewFromWriters(domain string, level Level, w, e io.WriteCloser) *Logger {
|
// 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 {
|
if e == nil {
|
||||||
e = w
|
e = w
|
||||||
}
|
}
|
||||||
|
|
||||||
l := &Logger{
|
l = &Logger{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
level: level,
|
level: level,
|
||||||
out: w,
|
out: w,
|
||||||
err: e,
|
err: e,
|
||||||
|
lock: new(sync.Mutex),
|
||||||
}
|
}
|
||||||
|
|
||||||
Enable(domain)
|
l.Enable()
|
||||||
return l
|
logConfig.registered[domain] = l
|
||||||
|
return l, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFile returns a new logger that opens the files for writing. If
|
// 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{
|
l := &Logger{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
level: level,
|
level: level,
|
||||||
|
lock: new(sync.Mutex),
|
||||||
}
|
}
|
||||||
|
|
||||||
outf, err := os.OpenFile(outFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
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.
|
// Enable allows output from the logger.
|
||||||
func (l *Logger) Enable() {
|
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.
|
// Suppress ignores output from the logger.
|
||||||
func (l *Logger) Suppress() {
|
func (l *Logger) Suppress() {
|
||||||
Suppress(l.domain)
|
l.lock.Lock()
|
||||||
|
defer l.lock.Unlock()
|
||||||
|
l.enabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Domain returns the domain of the logger.
|
// Domain returns the domain of the logger.
|
||||||
|
@ -163,5 +234,7 @@ func (l *Logger) Domain() string {
|
||||||
|
|
||||||
// SetLevel changes the level of the logger.
|
// SetLevel changes the level of the logger.
|
||||||
func (l *Logger) SetLevel(level Level) {
|
func (l *Logger) SetLevel(level Level) {
|
||||||
|
l.lock.Lock()
|
||||||
|
defer l.lock.Unlock()
|
||||||
l.level = level
|
l.level = level
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue