1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
// Copyright (c) 2012-2016 Eli Janssen
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package mlog
import (
"fmt"
"io"
"os"
"sync"
"sync/atomic"
)
// Emitter is the interface implemented by mlog logging format writers.
type Emitter interface {
Emit(logger *Logger, level int, message string, extra Map)
EmitAttrs(logger *Logger, level int, message string, extra ...*Attr)
}
// A Logger represents a logging object, that embeds log.Logger, and
// provides support for a toggle-able debug flag.
type Logger struct {
out io.Writer
e Emitter
mu sync.Mutex // ensures atomic writes are synchronized
flags uint64
}
// SetOutput sets the Logger output io.Writer
func (l *Logger) SetOutput(writer io.Writer) {
// lock writing to serialize log output (no scrambled log lines)
l.mu.Lock()
defer l.mu.Unlock()
l.out = writer
}
func (l *Logger) Write(b []byte) (int, error) {
// lock writing to serialize log output (no scrambled log lines)
l.mu.Lock()
defer l.mu.Unlock()
return l.out.Write(b)
}
// Emit invokes the FormatWriter and logs the event.
func (l *Logger) Emit(level int, message string, extra Map) {
l.e.Emit(l, level, message, extra)
}
// Emit invokes the FormatWriter and logs the event.
func (l *Logger) EmitAttrs(level int, message string, extra ...*Attr) {
l.e.EmitAttrs(l, level, message, extra...)
}
// SetEmitter sets the Emitter
func (l *Logger) SetEmitter(e Emitter) {
l.mu.Lock()
defer l.mu.Unlock()
l.e = e
}
// Flags returns the current FlagSet
func (l *Logger) Flags() FlagSet {
return FlagSet(atomic.LoadUint64(&l.flags))
}
// SetFlags sets the current FlagSet
func (l *Logger) SetFlags(flags FlagSet) {
atomic.StoreUint64(&l.flags, uint64(flags))
}
// HasDebug returns true if the debug logging FlagSet is enabled, false
// otherwise.
func (l *Logger) HasDebug() bool {
flags := FlagSet(atomic.LoadUint64(&l.flags))
return flags&Ldebug != 0
}
// Debugx conditionally logs message and any Attr elements at level="debug".
// If the Logger does not have the Ldebug flag, nothing is logged.
func (l *Logger) Debugx(message string, attrs ...*Attr) {
if l.HasDebug() {
l.EmitAttrs(-1, message, attrs...)
}
}
// Infox logs message and any Map elements at level="info".
func (l *Logger) Infox(message string, attrs ...*Attr) {
l.EmitAttrs(0, message, attrs...)
}
// Printx logs message and any Map elements at level="info".
func (l *Logger) Printx(message string, attrs ...*Attr) {
l.EmitAttrs(0, message, attrs...)
}
// Fatalx logs message and any Map elements at level="fatal", then calls
// os.Exit(1)
func (l *Logger) Fatalx(message string, attrs ...*Attr) {
l.EmitAttrs(1, message, attrs...)
os.Exit(1)
}
// Panicx logs message and any Map elements at level="fatal", then calls
// panic().
func (l *Logger) Panicx(message string, attrs ...*Attr) {
l.EmitAttrs(1, message, attrs...)
panic(message)
}
// Debugm conditionally logs message and any Map elements at level="debug".
// If the Logger does not have the Ldebug flag, nothing is logged.
func (l *Logger) Debugm(message string, v Map) {
if l.HasDebug() {
l.Emit(-1, message, v)
}
}
// Infom logs message and any Map elements at level="info".
func (l *Logger) Infom(message string, v Map) {
l.Emit(0, message, v)
}
// Printm logs message and any Map elements at level="info".
func (l *Logger) Printm(message string, v Map) {
l.Emit(0, message, v)
}
// Fatalm logs message and any Map elements at level="fatal", then calls
// os.Exit(1)
func (l *Logger) Fatalm(message string, v Map) {
l.Emit(1, message, v)
os.Exit(1)
}
// Panicm logs message and any Map elements at level="fatal", then calls
// panic().
func (l *Logger) Panicm(message string, v Map) {
l.Emit(1, message, v)
panic(message)
}
// Debugf formats and conditionally logs message at level="debug".
// If the Logger does not have the Ldebug flag, nothing is logged.
func (l *Logger) Debugf(format string, v ...interface{}) {
if l.HasDebug() {
l.Emit(-1, fmt.Sprintf(format, v...), nil)
}
}
// Infof formats and logs message at level="info".
func (l *Logger) Infof(format string, v ...interface{}) {
l.Emit(0, fmt.Sprintf(format, v...), nil)
}
// Printf formats and logs message at level="info".
func (l *Logger) Printf(format string, v ...interface{}) {
l.Emit(0, fmt.Sprintf(format, v...), nil)
}
// Fatalf formats and logs message at level="fatal", then calls
// os.Exit(1)
func (l *Logger) Fatalf(format string, v ...interface{}) {
l.Emit(1, fmt.Sprintf(format, v...), nil)
os.Exit(1)
}
// Panicf formats and logs message at level="fatal", then calls
// panic().
func (l *Logger) Panicf(format string, v ...interface{}) {
s := fmt.Sprintf(format, v...)
l.Emit(1, s, nil)
panic(s)
}
// Debug conditionally logs message at level="debug".
// If the Logger does not have the Ldebug flag, nothing is logged.
func (l *Logger) Debug(v ...interface{}) {
if l.HasDebug() {
l.Emit(-1, fmt.Sprint(v...), nil)
}
}
// Info logs message at level="info".
func (l *Logger) Info(v ...interface{}) {
l.Emit(0, fmt.Sprint(v...), nil)
}
// Print logs message at level="info".
func (l *Logger) Print(v ...interface{}) {
l.Emit(0, fmt.Sprint(v...), nil)
}
// Fatal logs message at level="fatal", then calls
// os.Exit(1)
func (l *Logger) Fatal(v ...interface{}) {
l.Emit(1, fmt.Sprint(v...), nil)
os.Exit(1)
}
// Panic logs message at level="fatal", then calls
// panic().
func (l *Logger) Panic(v ...interface{}) {
s := fmt.Sprint(v...)
l.Emit(1, s, nil)
panic(s)
}
// New creates a new Logger.
func New(out io.Writer, flags FlagSet) *Logger {
return NewFormatLogger(out, flags, &FormatWriterStructured{})
}
// NewFormatLogger creates a new Logger, using the specified Emitter.
func NewFormatLogger(out io.Writer, flags FlagSet, e Emitter) *Logger {
return &Logger{
out: out,
flags: uint64(flags),
e: e,
}
}
|