From 85207e0a7729554ea7ef4a5a8affdc716c862dfc Mon Sep 17 00:00:00 2001 From: Julien Riou Date: Sun, 24 Jun 2018 16:10:26 +0200 Subject: [PATCH] Add syslog notifier --- base/config.go | 2 ++ cmd/pgterminate/main.go | 11 ++++++ config.yaml.example | 2 ++ notifier/notifier.go | 3 ++ notifier/syslog.go | 79 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+) create mode 100644 notifier/syslog.go diff --git a/base/config.go b/base/config.go index 82fd21c..cfb528e 100644 --- a/base/config.go +++ b/base/config.go @@ -28,6 +28,8 @@ type Config struct { ActiveTimeout float64 `yaml:"active-timeout"` LogFile string `yaml:"log-file"` PidFile string `yaml:"pid-file"` + SyslogIdent string `yaml:"syslog-ident"` + SyslogFacility string `yaml:"syslog-facility"` } func init() { diff --git a/cmd/pgterminate/main.go b/cmd/pgterminate/main.go index 6ebeaef..e47c1cf 100644 --- a/cmd/pgterminate/main.go +++ b/cmd/pgterminate/main.go @@ -10,6 +10,7 @@ import ( "log" "os" "os/signal" + "regexp" "strconv" "sync" "syscall" @@ -36,6 +37,8 @@ func main() { flag.Float64Var(&config.ActiveTimeout, "active-timeout", 0, "Time for active connections to be terminated in seconds") flag.StringVar(&config.LogFile, "log-file", "", "Write logs to a file") flag.StringVar(&config.PidFile, "pid-file", "", "Write process id into a file") + flag.StringVar(&config.SyslogIdent, "syslog-ident", "pgterminate", "Define syslog tag") + flag.StringVar(&config.SyslogFacility, "syslog-facility", "", "Define syslog facility from LOCAL0 to LOCAL7") flag.Parse() if *version { @@ -63,6 +66,14 @@ func main() { log.Fatalln("Parameter -active-timeout or -idle-timeout required") } + if config.SyslogFacility != "" { + matched, err := regexp.MatchString("^LOCAL[0-7]$", config.SyslogFacility) + base.Panic(err) + if !matched { + log.Fatalln("Syslog facility must range from LOCAL0 to LOCAL7") + } + } + if config.PidFile != "" { writePid(config.PidFile) defer removePid(config.PidFile) diff --git a/config.yaml.example b/config.yaml.example index 86108b4..f10adb7 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -9,3 +9,5 @@ idle-timeout: 300 active-timeout: 10 log-file: /var/log/pgterminate/pgterminate.log pid-file: /var/run/pgterminate/pgterminate.pid +#syslog-ident: pgterminate +#syslog-facility: LOCAL0 diff --git a/notifier/notifier.go b/notifier/notifier.go index 9a8ea21..2c6921e 100644 --- a/notifier/notifier.go +++ b/notifier/notifier.go @@ -16,5 +16,8 @@ func NewNotifier(ctx *base.Context) Notifier { if ctx.Config.LogFile != "" { return NewFile(ctx.Config.LogFile, ctx.Sessions) } + if ctx.Config.SyslogFacility != "" { + return NewSyslog(ctx.Config.SyslogFacility, ctx.Config.SyslogIdent, ctx.Sessions) + } return NewConsole(ctx.Sessions) } diff --git a/notifier/syslog.go b/notifier/syslog.go new file mode 100644 index 0000000..8ca7ec0 --- /dev/null +++ b/notifier/syslog.go @@ -0,0 +1,79 @@ +package notifier + +import ( + "fmt" + "github.com/jouir/pgterminate/base" + "log/syslog" +) + +// Syslog notifier +type Syslog struct { + sessions chan base.Session + ident string + priority syslog.Priority + writer *syslog.Writer +} + +// NewSyslog creates a syslog notifier +func NewSyslog(facility string, ident string, sessions chan base.Session) Notifier { + var priority syslog.Priority + switch facility { + case "LOCAL0": + priority = syslog.LOG_INFO | syslog.LOG_LOCAL0 + case "LOCAL1": + priority = syslog.LOG_INFO | syslog.LOG_LOCAL1 + case "LOCAL2": + priority = syslog.LOG_INFO | syslog.LOG_LOCAL2 + case "LOCAL3": + priority = syslog.LOG_INFO | syslog.LOG_LOCAL3 + case "LOCAL4": + priority = syslog.LOG_INFO | syslog.LOG_LOCAL4 + case "LOCAL5": + priority = syslog.LOG_INFO | syslog.LOG_LOCAL5 + case "LOCAL6": + priority = syslog.LOG_INFO | syslog.LOG_LOCAL6 + default: // LOCAL7 + priority = syslog.LOG_INFO | syslog.LOG_LOCAL7 + } + return &Syslog{ + sessions: sessions, + ident: ident, + priority: priority, + } +} + +// Run starts syslog notifier +func (s *Syslog) Run() { + var err error + if s.writer, err = syslog.New(s.priority, s.ident); err != nil { + base.Panic(err) + } + for session := range s.sessions { + s.writer.Info(fmt.Sprintf("%s", session)) + } +} + +// Reload disconnect from syslog daemon and re-connect +// Executed when receiving SIGHUP signal +func (s *Syslog) Reload() { + if s.writer != nil { + s.disconnect() + s.connect() + } +} + +// connect to syslog daemon +func (s *Syslog) connect() { + var err error + if s.writer, err = syslog.New(s.priority, s.ident); err != nil { + base.Panic(err) + } +} + +// disconnect from syslog daemon +func (s *Syslog) disconnect() { + var err error + if err = s.writer.Close(); err != nil { + base.Panic(err) + } +}