172 lines
3.4 KiB
Go
172 lines
3.4 KiB
Go
package logging
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"log/syslog"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
type Backend interface {
|
|
Write(*Record) error
|
|
SetFormatter(*Formatter)
|
|
SetLevel(Level)
|
|
Level() Level
|
|
}
|
|
|
|
//
|
|
// Backend to write in file-like objects
|
|
//
|
|
|
|
type FileBackend struct {
|
|
l io.Writer
|
|
formatter *Formatter
|
|
level Level
|
|
}
|
|
|
|
// Creates a new backend to write the logs on the standard output
|
|
func NewStdoutBackend() (b *FileBackend) {
|
|
b = &FileBackend{
|
|
l: os.Stdout,
|
|
formatter: &defaultFormatter,
|
|
}
|
|
return
|
|
}
|
|
|
|
// Creates a new backend to write the logs on the error output
|
|
func NewStderrBackend() (b *FileBackend) {
|
|
b = &FileBackend{
|
|
l: os.Stderr,
|
|
formatter: &defaultFormatter,
|
|
}
|
|
return
|
|
}
|
|
|
|
// Creates a new backend to write the logs in a given file
|
|
func NewFileBackend(filename string) (b *FileBackend, e error) {
|
|
filename_fd, err := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
|
if err != nil {
|
|
e = errors.New(fmt.Sprintf("Cannot open log file %s (%s)", filename, err.Error()))
|
|
}
|
|
b = &FileBackend{
|
|
l: filename_fd,
|
|
formatter: &defaultFormatter,
|
|
}
|
|
return
|
|
}
|
|
|
|
// Creates a new backend to write the logs in a given io.Writer
|
|
func NewIoBackend(buf io.Writer) (b *FileBackend) {
|
|
return &FileBackend{
|
|
l: buf,
|
|
formatter: &defaultFormatter,
|
|
}
|
|
}
|
|
|
|
func (b FileBackend) Write(r *Record) error {
|
|
text := (*b.formatter)(r)
|
|
_, err := io.WriteString(b.l, text)
|
|
return err
|
|
}
|
|
|
|
func (b *FileBackend) SetLevel(l Level) {
|
|
b.level = l
|
|
}
|
|
|
|
func (b *FileBackend) Level() Level {
|
|
return b.level
|
|
}
|
|
|
|
func (b *FileBackend) SetFormatter(f *Formatter) {
|
|
b.formatter = f
|
|
}
|
|
|
|
//
|
|
// Syslog Backend
|
|
//
|
|
|
|
type SyslogBackend struct {
|
|
w *syslog.Writer
|
|
formatter *Formatter
|
|
level Level
|
|
}
|
|
|
|
func NewSyslogBackend(facilityName string, tag string) (Backend, error) {
|
|
f, err := facility(facilityName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
w, err := syslog.New(f, tag)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sb := &SyslogBackend{
|
|
w: w,
|
|
formatter: &basicFormatter,
|
|
}
|
|
return sb, nil
|
|
}
|
|
|
|
func (sb *SyslogBackend) Write(r *Record) (err error) {
|
|
text := (*sb.formatter)(r)
|
|
switch r.Level {
|
|
case DEBUG:
|
|
err = sb.w.Debug(text)
|
|
case INFO:
|
|
err = sb.w.Info(text)
|
|
case WARNING:
|
|
err = sb.w.Warning(text)
|
|
case ERROR:
|
|
err = sb.w.Err(text)
|
|
case CRITICAL:
|
|
err = sb.w.Crit(text)
|
|
case FATAL:
|
|
err = sb.w.Emerg(text)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (sb *SyslogBackend) SetFormatter(f *Formatter) {
|
|
sb.formatter = f
|
|
}
|
|
|
|
func (sb *SyslogBackend) SetLevel(level Level) {
|
|
sb.level = level
|
|
}
|
|
|
|
func (sb *SyslogBackend) Level() Level {
|
|
return sb.level
|
|
}
|
|
|
|
var facilities = map[string]syslog.Priority{
|
|
"kern": syslog.LOG_KERN,
|
|
"user": syslog.LOG_USER,
|
|
"mail": syslog.LOG_MAIL,
|
|
"daemon": syslog.LOG_DAEMON,
|
|
"auth": syslog.LOG_AUTH,
|
|
"syslog": syslog.LOG_SYSLOG,
|
|
"lpr": syslog.LOG_LPR,
|
|
"news": syslog.LOG_NEWS,
|
|
"uucp": syslog.LOG_UUCP,
|
|
"cron": syslog.LOG_CRON,
|
|
"authpriv": syslog.LOG_AUTHPRIV,
|
|
"ftp": syslog.LOG_FTP,
|
|
"local0": syslog.LOG_LOCAL0,
|
|
"local1": syslog.LOG_LOCAL1,
|
|
"local2": syslog.LOG_LOCAL2,
|
|
"local3": syslog.LOG_LOCAL3,
|
|
"local4": syslog.LOG_LOCAL4,
|
|
"local5": syslog.LOG_LOCAL5,
|
|
"local6": syslog.LOG_LOCAL6,
|
|
"local7": syslog.LOG_LOCAL7,
|
|
}
|
|
|
|
func facility(name string) (syslog.Priority, error) {
|
|
if p, ok := facilities[strings.ToLower(name)]; !ok {
|
|
return 0, fmt.Errorf("Facility '%s' does not exist", name)
|
|
} else {
|
|
return p, nil
|
|
}
|
|
}
|