2022-05-31 12:23:48 +02:00
|
|
|
|
//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 (
|
2022-05-31 12:23:48 +02:00
|
|
|
|
"errors"
|
2016-10-28 18:34:07 +02:00
|
|
|
|
"fmt"
|
|
|
|
|
"log/syslog"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
2022-05-31 12:23:48 +02:00
|
|
|
|
var errUnknownFacility = errors.New("unknown facility")
|
|
|
|
|
|
2016-10-28 18:34:07 +02:00
|
|
|
|
//
|
|
|
|
|
// Syslog Backend
|
|
|
|
|
//
|
|
|
|
|
|
2022-06-03 10:20:07 +02:00
|
|
|
|
var _ Backend = &SyslogBackend{}
|
|
|
|
|
|
2022-05-31 12:23:48 +02:00
|
|
|
|
// SyslogBackend writes the logs to a syslog system.
|
2016-10-28 18:34:07 +02:00
|
|
|
|
type SyslogBackend struct {
|
|
|
|
|
w *syslog.Writer
|
2022-05-31 12:23:48 +02:00
|
|
|
|
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].
|
2022-05-31 12:23:48 +02:00
|
|
|
|
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
|
|
|
|
|
}
|
2022-05-31 12:23:48 +02:00
|
|
|
|
|
2016-10-28 18:34:07 +02:00
|
|
|
|
w, err := syslog.New(f, tag)
|
|
|
|
|
if err != nil {
|
2022-05-31 12:23:48 +02:00
|
|
|
|
return nil, fmt.Errorf("cannot initialize syslog: %w", err)
|
2016-10-28 18:34:07 +02:00
|
|
|
|
}
|
2022-05-31 12:23:48 +02:00
|
|
|
|
|
2016-10-28 18:34:07 +02:00
|
|
|
|
sb := &SyslogBackend{
|
|
|
|
|
w: w,
|
2022-05-31 12:23:48 +02:00
|
|
|
|
formatter: basicFormatter,
|
2016-10-28 18:34:07 +02:00
|
|
|
|
}
|
2022-05-31 12:23:48 +02:00
|
|
|
|
|
2016-10-28 18:34:07 +02:00
|
|
|
|
return sb, nil
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-31 12:23:48 +02:00
|
|
|
|
// 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)
|
|
|
|
|
}
|
2022-05-31 12:23:48 +02:00
|
|
|
|
|
|
|
|
|
return fmt.Errorf("cannot log to syslog: %w", err)
|
2016-10-28 18:34:07 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-31 12:23:48 +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
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-31 12:23:48 +02:00
|
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-31 12:23:48 +02:00
|
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-31 12:23:48 +02:00
|
|
|
|
// Reopen is a no-op.
|
|
|
|
|
func (*SyslogBackend) Reopen() error {
|
2016-10-28 18:34:07 +02:00
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-31 12:23:48 +02:00
|
|
|
|
// Close closes the connection to the syslog daemon.
|
2020-05-17 14:33:16 +02:00
|
|
|
|
func (sb *SyslogBackend) Close() error {
|
2022-05-31 12:23:48 +02:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
2022-05-31 12:23:48 +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 {
|
2022-05-31 12:23:48 +02:00
|
|
|
|
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
|
|
|
|
}
|