mirror of
https://github.com/42wim/matterbridge
synced 2024-11-05 12:00:27 +00:00
127 lines
3.2 KiB
Go
127 lines
3.2 KiB
Go
|
// Copyright (C) 2010, Kyle Lemons <kyle@kylelemons.net>. All rights reserved.
|
||
|
|
||
|
package log4go
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
FORMAT_DEFAULT = "[%D %T] [%L] (%S) %M"
|
||
|
FORMAT_SHORT = "[%t %d] [%L] %M"
|
||
|
FORMAT_ABBREV = "[%L] %M"
|
||
|
)
|
||
|
|
||
|
type formatCacheType struct {
|
||
|
LastUpdateSeconds int64
|
||
|
shortTime, shortDate string
|
||
|
longTime, longDate string
|
||
|
}
|
||
|
|
||
|
var formatCache = &formatCacheType{}
|
||
|
|
||
|
// Known format codes:
|
||
|
// %T - Time (15:04:05 MST)
|
||
|
// %t - Time (15:04)
|
||
|
// %D - Date (2006/01/02)
|
||
|
// %d - Date (01/02/06)
|
||
|
// %L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT)
|
||
|
// %S - Source
|
||
|
// %M - Message
|
||
|
// Ignores unknown formats
|
||
|
// Recommended: "[%D %T] [%L] (%S) %M"
|
||
|
func FormatLogRecord(format string, rec *LogRecord) string {
|
||
|
if rec == nil {
|
||
|
return "<nil>"
|
||
|
}
|
||
|
if len(format) == 0 {
|
||
|
return ""
|
||
|
}
|
||
|
|
||
|
out := bytes.NewBuffer(make([]byte, 0, 64))
|
||
|
secs := rec.Created.UnixNano() / 1e9
|
||
|
|
||
|
cache := *formatCache
|
||
|
if cache.LastUpdateSeconds != secs {
|
||
|
month, day, year := rec.Created.Month(), rec.Created.Day(), rec.Created.Year()
|
||
|
hour, minute, second := rec.Created.Hour(), rec.Created.Minute(), rec.Created.Second()
|
||
|
zone, _ := rec.Created.Zone()
|
||
|
updated := &formatCacheType{
|
||
|
LastUpdateSeconds: secs,
|
||
|
shortTime: fmt.Sprintf("%02d:%02d", hour, minute),
|
||
|
shortDate: fmt.Sprintf("%02d/%02d/%02d", day, month, year%100),
|
||
|
longTime: fmt.Sprintf("%02d:%02d:%02d %s", hour, minute, second, zone),
|
||
|
longDate: fmt.Sprintf("%04d/%02d/%02d", year, month, day),
|
||
|
}
|
||
|
cache = *updated
|
||
|
formatCache = updated
|
||
|
}
|
||
|
|
||
|
// Split the string into pieces by % signs
|
||
|
pieces := bytes.Split([]byte(format), []byte{'%'})
|
||
|
|
||
|
// Iterate over the pieces, replacing known formats
|
||
|
for i, piece := range pieces {
|
||
|
if i > 0 && len(piece) > 0 {
|
||
|
switch piece[0] {
|
||
|
case 'T':
|
||
|
out.WriteString(cache.longTime)
|
||
|
case 't':
|
||
|
out.WriteString(cache.shortTime)
|
||
|
case 'D':
|
||
|
out.WriteString(cache.longDate)
|
||
|
case 'd':
|
||
|
out.WriteString(cache.shortDate)
|
||
|
case 'L':
|
||
|
out.WriteString(levelStrings[rec.Level])
|
||
|
case 'S':
|
||
|
out.WriteString(rec.Source)
|
||
|
case 's':
|
||
|
slice := strings.Split(rec.Source, "/")
|
||
|
out.WriteString(slice[len(slice)-1])
|
||
|
case 'M':
|
||
|
out.WriteString(rec.Message)
|
||
|
}
|
||
|
if len(piece) > 1 {
|
||
|
out.Write(piece[1:])
|
||
|
}
|
||
|
} else if len(piece) > 0 {
|
||
|
out.Write(piece)
|
||
|
}
|
||
|
}
|
||
|
out.WriteByte('\n')
|
||
|
|
||
|
return out.String()
|
||
|
}
|
||
|
|
||
|
// This is the standard writer that prints to standard output.
|
||
|
type FormatLogWriter chan *LogRecord
|
||
|
|
||
|
// This creates a new FormatLogWriter
|
||
|
func NewFormatLogWriter(out io.Writer, format string) FormatLogWriter {
|
||
|
records := make(FormatLogWriter, LogBufferLength)
|
||
|
go records.run(out, format)
|
||
|
return records
|
||
|
}
|
||
|
|
||
|
func (w FormatLogWriter) run(out io.Writer, format string) {
|
||
|
for rec := range w {
|
||
|
fmt.Fprint(out, FormatLogRecord(format, rec))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// This is the FormatLogWriter's output method. This will block if the output
|
||
|
// buffer is full.
|
||
|
func (w FormatLogWriter) LogWrite(rec *LogRecord) {
|
||
|
w <- rec
|
||
|
}
|
||
|
|
||
|
// Close stops the logger from sending messages to standard output. Attempts to
|
||
|
// send log messages to this logger after a Close have undefined behavior.
|
||
|
func (w FormatLogWriter) Close() {
|
||
|
close(w)
|
||
|
}
|