1
0
mirror of https://github.com/nikoksr/notify.git synced 2025-01-10 00:28:36 +02:00
notify/service/syslog/syslog.go
2022-02-13 18:18:03 +01:00

74 lines
2.4 KiB
Go

package syslog
import (
"context"
"io"
"log/syslog"
"strings"
"github.com/pkg/errors"
)
// mockSyslogWriter abstracts log/syslog for writing unit tests.
type syslogWriter interface {
io.WriteCloser
}
// Service encapsulates a syslog daemon writer.
type Service struct {
writer syslogWriter
}
// dial is a wrapper function around syslog.Dial. It normalizes the prefix tag in case that it's empty and returns
// a new Service with the writer field set to writer from the call to syslog.Dial.
func dial(network, raddr string, priority syslog.Priority, tag string) (*Service, error) {
if strings.TrimSpace(tag) == "" {
tag = "notify"
}
// Usually we could call syslog.New and syslog.Dial respectively for specific use-cases. But since syslog.New is
// only a wrapper around a call to syslog.Dial without information about the network we're doing the same here to
// keep the API a little more clean.
writer, err := syslog.Dial(network, raddr, priority, tag)
if err != nil {
return nil, err
}
return &Service{writer: writer}, nil
}
// New returns a new instance of a Service notification service. Parameter 'tag' is used as a log prefix and may be left
// empty, it has a fallback value.
func New(priority syslog.Priority, tag string) (*Service, error) {
return dial("", "", priority, tag)
}
// NewFromDial returns a new instance of a Service notification service. The underlying syslog writer establishes a
// connection to a log daemon by connecting to address raddr on the specified network. Parameter 'tag' is used as a log
// prefix and may be left empty, it has a fallback value.
// Calling NewFromDial with network and raddr being empty strings is equal in function to calling New directly.
func NewFromDial(network, raddr string, priority syslog.Priority, tag string) (*Service, error) {
return dial(network, raddr, priority, tag)
}
// Close the underlying syslog writer.
func (s *Service) Close() error {
return s.writer.Close()
}
// Send takes a message subject and a message body and sends them to all previously set channels.
// user used for sending the message has to be a member of the channel.
func (s *Service) Send(ctx context.Context, subject, message string) error {
select {
case <-ctx.Done():
return ctx.Err()
default:
_, err := s.writer.Write([]byte(subject + ": " + message))
if err != nil {
return errors.Wrap(err, "failed to write message to syslog")
}
}
return nil
}