golanggohlsrtmpwebrtcmedia-serverobs-studiortcprtmp-proxyrtmp-serverrtprtsprtsp-proxyrtsp-relayrtsp-serversrtstreamingwebrtc-proxy
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
3.0 KiB
157 lines
3.0 KiB
// Package logger contains a logger implementation. |
|
package logger |
|
|
|
import ( |
|
"bytes" |
|
"fmt" |
|
"sync" |
|
"time" |
|
|
|
"github.com/gookit/color" |
|
) |
|
|
|
// Logger is a log handler. |
|
type Logger struct { |
|
level Level |
|
|
|
destinations []destination |
|
mutex sync.Mutex |
|
} |
|
|
|
// New allocates a log handler. |
|
func New(level Level, destinations []Destination, filePath string) (*Logger, error) { |
|
lh := &Logger{ |
|
level: level, |
|
} |
|
|
|
for _, destType := range destinations { |
|
switch destType { |
|
case DestinationStdout: |
|
lh.destinations = append(lh.destinations, newDestionationStdout()) |
|
|
|
case DestinationFile: |
|
dest, err := newDestinationFile(filePath) |
|
if err != nil { |
|
lh.Close() |
|
return nil, err |
|
} |
|
lh.destinations = append(lh.destinations, dest) |
|
|
|
case DestinationSyslog: |
|
dest, err := newDestinationSyslog() |
|
if err != nil { |
|
lh.Close() |
|
return nil, err |
|
} |
|
lh.destinations = append(lh.destinations, dest) |
|
} |
|
} |
|
|
|
return lh, nil |
|
} |
|
|
|
// Close closes a log handler. |
|
func (lh *Logger) Close() { |
|
for _, dest := range lh.destinations { |
|
dest.close() |
|
} |
|
} |
|
|
|
// https://golang.org/src/log/log.go#L78 |
|
func itoa(i int, wid int) []byte { |
|
// Assemble decimal in reverse order. |
|
var b [20]byte |
|
bp := len(b) - 1 |
|
for i >= 10 || wid > 1 { |
|
wid-- |
|
q := i / 10 |
|
b[bp] = byte('0' + i - q*10) |
|
bp-- |
|
i = q |
|
} |
|
// i < 10 |
|
b[bp] = byte('0' + i) |
|
return b[bp:] |
|
} |
|
|
|
func writeTime(buf *bytes.Buffer, t time.Time, useColor bool) { |
|
var intbuf bytes.Buffer |
|
|
|
// date |
|
year, month, day := t.Date() |
|
intbuf.Write(itoa(year, 4)) |
|
intbuf.WriteByte('/') |
|
intbuf.Write(itoa(int(month), 2)) |
|
intbuf.WriteByte('/') |
|
intbuf.Write(itoa(day, 2)) |
|
intbuf.WriteByte(' ') |
|
|
|
// time |
|
hour, min, sec := t.Clock() |
|
intbuf.Write(itoa(hour, 2)) |
|
intbuf.WriteByte(':') |
|
intbuf.Write(itoa(min, 2)) |
|
intbuf.WriteByte(':') |
|
intbuf.Write(itoa(sec, 2)) |
|
intbuf.WriteByte(' ') |
|
|
|
if useColor { |
|
buf.WriteString(color.RenderString(color.Gray.Code(), intbuf.String())) |
|
} else { |
|
buf.WriteString(intbuf.String()) |
|
} |
|
} |
|
|
|
func writeLevel(buf *bytes.Buffer, level Level, useColor bool) { |
|
switch level { |
|
case Debug: |
|
if useColor { |
|
buf.WriteString(color.RenderString(color.Debug.Code(), "DEB")) |
|
} else { |
|
buf.WriteString("DEB") |
|
} |
|
|
|
case Info: |
|
if useColor { |
|
buf.WriteString(color.RenderString(color.Green.Code(), "INF")) |
|
} else { |
|
buf.WriteString("INF") |
|
} |
|
|
|
case Warn: |
|
if useColor { |
|
buf.WriteString(color.RenderString(color.Warn.Code(), "WAR")) |
|
} else { |
|
buf.WriteString("WAR") |
|
} |
|
|
|
case Error: |
|
if useColor { |
|
buf.WriteString(color.RenderString(color.Error.Code(), "ERR")) |
|
} else { |
|
buf.WriteString("ERR") |
|
} |
|
} |
|
buf.WriteByte(' ') |
|
} |
|
|
|
func writeContent(buf *bytes.Buffer, format string, args []interface{}) { |
|
buf.Write([]byte(fmt.Sprintf(format, args...))) |
|
buf.WriteByte('\n') |
|
} |
|
|
|
// Log writes a log entry. |
|
func (lh *Logger) Log(level Level, format string, args ...interface{}) { |
|
if level < lh.level { |
|
return |
|
} |
|
|
|
lh.mutex.Lock() |
|
defer lh.mutex.Unlock() |
|
|
|
t := time.Now() |
|
|
|
for _, dest := range lh.destinations { |
|
dest.log(t, level, format, args...) |
|
} |
|
}
|
|
|