logging/backend_syslog_linux.go

142 lines
3 KiB
Go
Raw Permalink 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
//
var _ Backend = &SyslogBackend{}
// 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)
}
if err != nil {
return fmt.Errorf("cannot log to syslog: %w", err)
}
return nil
}
// 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
}