diff options
Diffstat (limited to 'libgo/go/log/log.go')
-rw-r--r-- | libgo/go/log/log.go | 101 |
1 files changed, 69 insertions, 32 deletions
diff --git a/libgo/go/log/log.go b/libgo/go/log/log.go index 658e3bd..33140ee 100644 --- a/libgo/go/log/log.go +++ b/libgo/go/log/log.go @@ -28,11 +28,12 @@ const ( // order they appear (the order listed here) or the format they present (as // described in the comments). A colon appears after these items: // 2009/0123 01:23:23.123123 /a/b/c/d.go:23: message - Ldate = 1 << iota // the date: 2009/0123 - Ltime // the time: 01:23:23 - Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. - Llongfile // full file name and line number: /a/b/c/d.go:23 - Lshortfile // final file name element and line number: d.go:23. overrides Llongfile + Ldate = 1 << iota // the date: 2009/0123 + Ltime // the time: 01:23:23 + Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. + Llongfile // full file name and line number: /a/b/c/d.go:23 + Lshortfile // final file name element and line number: d.go:23. overrides Llongfile + LstdFlags = Ldate | Ltime // initial values for the standard logger ) // A Logger represents an active logging object that generates lines of @@ -40,10 +41,11 @@ const ( // the Writer's Write method. A Logger can be used simultaneously from // multiple goroutines; it guarantees to serialize access to the Writer. type Logger struct { - mu sync.Mutex // ensures atomic writes - out io.Writer // destination for output - prefix string // prefix to write at beginning of each line - flag int // properties + prefix string // prefix to write at beginning of each line + flag int // properties + mu sync.Mutex // ensures atomic writes; protects the following fields + out io.Writer // destination for output + buf bytes.Buffer // for accumulating text to write } // New creates a new Logger. The out variable sets the @@ -54,7 +56,7 @@ func New(out io.Writer, prefix string, flag int) *Logger { return &Logger{out: out, prefix: prefix, flag: flag} } -var std = New(os.Stderr, "", Ldate|Ltime) +var std = New(os.Stderr, "", LstdFlags) // Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding. // Knows the buffer has capacity. @@ -81,7 +83,7 @@ func itoa(buf *bytes.Buffer, i int, wid int) { } } -func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) { +func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, file string, line int) { buf.WriteString(l.prefix) if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 { t := time.SecondsToLocalTime(ns / 1e9) @@ -107,21 +109,15 @@ func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) { } } if l.flag&(Lshortfile|Llongfile) != 0 { - _, file, line, ok := runtime.Caller(calldepth) - if ok { - if l.flag&Lshortfile != 0 { - short := file - for i := len(file) - 1; i > 0; i-- { - if file[i] == '/' { - short = file[i+1:] - break - } + if l.flag&Lshortfile != 0 { + short := file + for i := len(file) - 1; i > 0; i-- { + if file[i] == '/' { + short = file[i+1:] + break } - file = short } - } else { - file = "???" - line = 0 + file = short } buf.WriteString(file) buf.WriteByte(':') @@ -138,15 +134,26 @@ func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) { // paths it will be 2. func (l *Logger) Output(calldepth int, s string) os.Error { now := time.Nanoseconds() // get this early. - buf := new(bytes.Buffer) - l.formatHeader(buf, now, calldepth+1) - buf.WriteString(s) - if len(s) > 0 && s[len(s)-1] != '\n' { - buf.WriteByte('\n') + // get caller info (if required) before locking - it's expensive. + var file string + var line int + if l.flag&(Lshortfile|Llongfile) != 0 { + var ok bool + _, file, line, ok = runtime.Caller(calldepth) + if !ok { + file = "???" + line = 0 + } } l.mu.Lock() defer l.mu.Unlock() - _, err := l.out.Write(buf.Bytes()) + l.buf.Reset() + l.formatHeader(&l.buf, now, file, line) + l.buf.WriteString(s) + if len(s) > 0 && s[len(s)-1] != '\n' { + l.buf.WriteByte('\n') + } + _, err := l.out.Write(l.buf.Bytes()) return err } @@ -203,19 +210,49 @@ func (l *Logger) Panicln(v ...interface{}) { panic(s) } +// Flags returns the output flags for the logger. +func (l *Logger) Flags() int { + return l.flag +} + +// SetFlags sets the output flags for the logger. +func (l *Logger) SetFlags(flag int) { + l.flag = flag +} + +// Prefix returns the output prefix for the logger. +func (l *Logger) Prefix() string { + return l.prefix +} + +// SetPrefix sets the output prefix for the logger. +func (l *Logger) SetPrefix(prefix string) { + l.prefix = prefix +} + // SetOutput sets the output destination for the standard logger. func SetOutput(w io.Writer) { std.out = w } +// Flags returns the output flags for the standard logger. +func Flags() int { + return std.Flags() +} + // SetFlags sets the output flags for the standard logger. func SetFlags(flag int) { - std.flag = flag + std.SetFlags(flag) +} + +// Prefix returns the output prefix for the standard logger. +func Prefix() string { + return std.Prefix() } // SetPrefix sets the output prefix for the standard logger. func SetPrefix(prefix string) { - std.prefix = prefix + std.SetPrefix(prefix) } // These functions write to the standard logger. |