logging/backend_syslog_linux.go

143 lines
3 KiB
Go
Raw Normal View History

//go:build !windows && !nacl && !plan9
2016-10-28 18:34:07 +02:00
// +build !windows,!nacl,!plan9
2019-11-05 15:24:26 +01:00
2016-10-28 18:34:07 +02:00
package logging
import (
"errors"
2016-10-28 18:34:07 +02:00
"fmt"
"log/syslog"
"strings"
)
var errUnknownFacility = errors.New("unknown facility")
2016-10-28 18:34:07 +02:00
//
// Syslog Backend
//
var _ Backend = &SyslogBackend{}
// SyslogBackend writes the logs to a syslog system.
2016-10-28 18:34:07 +02:00
type SyslogBackend struct {
w *syslog.Writer
formatter Formatter
2016-10-28 18:34:07 +02:00
level Level
}
2020-02-01 17:30:09 +01:00
// NewSyslogBackend initializes a new connection to a syslog server with the
// given facility.
// tag can contain an identifier for the log stream. It defaults to os.Arg[0].
func NewSyslogBackend(facilityName, tag string) (*SyslogBackend, error) {
2016-10-28 18:34:07 +02:00
f, err := facility(facilityName)
if err != nil {
return nil, err
}
2016-10-28 18:34:07 +02:00
w, err := syslog.New(f, tag)
if err != nil {
return nil, fmt.Errorf("cannot initialize syslog: %w", err)
2016-10-28 18:34:07 +02:00
}
2016-10-28 18:34:07 +02:00
sb := &SyslogBackend{
w: w,
formatter: basicFormatter,
2016-10-28 18:34:07 +02:00
}
2016-10-28 18:34:07 +02:00
return sb, nil
}
// Write sends an entry to the syslog server.
func (sb *SyslogBackend) Write(r *Record) error {
var err error
text := sb.formatter(r)
2016-10-28 18:34:07 +02:00
switch r.Level {
2022-05-31 16:04:07 +02:00
case Trace, Debug:
2016-10-28 18:34:07 +02:00
err = sb.w.Debug(text)
2020-02-01 17:30:09 +01:00
case Info:
2016-10-28 18:34:07 +02:00
err = sb.w.Info(text)
2022-05-31 16:04:07 +02:00
case Notice:
err = sb.w.Notice(text)
2020-02-01 17:30:09 +01:00
case Warning:
2016-10-28 18:34:07 +02:00
err = sb.w.Warning(text)
2020-02-01 17:30:09 +01:00
case Error:
2016-10-28 18:34:07 +02:00
err = sb.w.Err(text)
2020-02-01 17:30:09 +01:00
case Critical:
2016-10-28 18:34:07 +02:00
err = sb.w.Crit(text)
2022-05-31 16:04:07 +02:00
case Alert:
err = sb.w.Alert(text)
2020-02-01 17:30:09 +01:00
case Fatal:
2016-10-28 18:34:07 +02:00
err = sb.w.Emerg(text)
}
if err != nil {
return fmt.Errorf("cannot log to syslog: %w", err)
}
return nil
2016-10-28 18:34:07 +02:00
}
// SetFormatter defines the formatter for this backend.
func (sb *SyslogBackend) SetFormatter(f Formatter) {
2016-10-28 18:34:07 +02:00
sb.formatter = f
}
// SetLevel changes the log level of the backend.
2016-10-28 18:34:07 +02:00
func (sb *SyslogBackend) SetLevel(level Level) {
sb.level = level
}
// Level returns the log level set for this backend.
2016-10-28 18:34:07 +02:00
func (sb *SyslogBackend) Level() Level {
return sb.level
}
// Reopen is a no-op.
func (*SyslogBackend) Reopen() error {
2016-10-28 18:34:07 +02:00
return nil
}
// Close closes the connection to the syslog daemon.
2020-05-17 14:33:16 +02:00
func (sb *SyslogBackend) Close() error {
if err := sb.w.Close(); err != nil {
return fmt.Errorf("cannot close syslog: %w", err)
}
return nil
2020-05-17 14:33:16 +02:00
}
//nolint:gochecknoglobals // global var is used by design
2016-10-28 18:34:07 +02:00
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) {
2020-02-01 17:30:09 +01:00
p, ok := facilities[strings.ToLower(name)]
if !ok {
return 0, fmt.Errorf("facility '%s' does not exist: %w", name, errUnknownFacility)
2016-10-28 18:34:07 +02:00
}
2020-02-01 17:30:09 +01:00
return p, nil
2016-10-28 18:34:07 +02:00
}