logging/backend_syslog_linux.go

136 lines
2.9 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//go:build !windows && !nacl && !plan9
// +build !windows,!nacl,!plan9
package logging
import (
"errors"
"fmt"
"log/syslog"
"strings"
)
var errUnknownFacility = errors.New("unknown facility")
//
// Syslog Backend
//
// SyslogBackend writes the logs to a syslog system.
type SyslogBackend struct {
w *syslog.Writer
formatter Formatter
level Level
}
// 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) {
f, err := facility(facilityName)
if err != nil {
return nil, err
}
w, err := syslog.New(f, tag)
if err != nil {
return nil, fmt.Errorf("cannot initialize syslog: %w", err)
}
sb := &SyslogBackend{
w: w,
formatter: basicFormatter,
}
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)
switch r.Level {
case Trace, Debug:
err = sb.w.Debug(text)
case Info:
err = sb.w.Info(text)
case Notice:
err = sb.w.Notice(text)
case Warning:
err = sb.w.Warning(text)
case Error:
err = sb.w.Err(text)
case Critical:
err = sb.w.Crit(text)
case Alert:
err = sb.w.Alert(text)
case Fatal:
err = sb.w.Emerg(text)
}
return fmt.Errorf("cannot log to syslog: %w", err)
}
// SetFormatter defines the formatter for this backend.
func (sb *SyslogBackend) SetFormatter(f Formatter) {
sb.formatter = f
}
// SetLevel changes the log level of the backend.
func (sb *SyslogBackend) SetLevel(level Level) {
sb.level = level
}
// Level returns the log level set for this backend.
func (sb *SyslogBackend) Level() Level {
return sb.level
}
// Reopen is a no-op.
func (*SyslogBackend) Reopen() error {
return nil
}
// Close closes the connection to the syslog daemon.
func (sb *SyslogBackend) Close() error {
if err := sb.w.Close(); err != nil {
return fmt.Errorf("cannot close syslog: %w", err)
}
return nil
}
//nolint:gochecknoglobals // global var is used by design
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) {
p, ok := facilities[strings.ToLower(name)]
if !ok {
return 0, fmt.Errorf("facility '%s' does not exist: %w", name, errUnknownFacility)
}
return p, nil
}