postfix_exporter/systemd.go

120 lines
2.4 KiB
Go
Raw Normal View History

// +build !nosystemd
package main
import (
"flag"
"fmt"
"log"
"sync"
"time"
"github.com/coreos/go-systemd/sdjournal"
)
// Journal represents a lockable systemd journal.
type Journal struct {
*sdjournal.Journal
sync.Mutex
Path string
}
// NewJournal returns a Journal for reading journal entries.
func NewJournal(unit, slice, path string) (j *Journal, err error) {
j = new(Journal)
if path != "" {
j.Journal, err = sdjournal.NewJournalFromDir(path)
j.Path = path
} else {
j.Journal, err = sdjournal.NewJournal()
j.Path = "journald"
}
if err != nil {
return
}
if slice != "" {
err = j.AddMatch("_SYSTEMD_SLICE=" + slice)
if err != nil {
return
}
} else if unit != "" {
err = j.AddMatch("_SYSTEMD_UNIT=" + unit)
if err != nil {
return
}
}
// Start at end of journal
err = j.SeekRealtimeUsec(uint64(time.Now().UnixNano() / 1000))
if err != nil {
log.Printf("%v", err)
}
return
}
// NextMessage reads the next message from the journal.
func (j *Journal) NextMessage() (s string, c uint64, err error) {
var e *sdjournal.JournalEntry
// Read to next
c, err = j.Next()
if err != nil {
return
}
// Return when on the end of journal
if c == 0 {
return
}
// Get entry
e, err = j.GetEntry()
if err != nil {
return
}
ts := time.Unix(0, int64(e.RealtimeTimestamp)*int64(time.Microsecond))
// Format entry
s = fmt.Sprintf(
"%s %s %s[%s]: %s",
ts.Format(time.Stamp),
e.Fields["_HOSTNAME"],
e.Fields["SYSLOG_IDENTIFIER"],
e.Fields["_PID"],
e.Fields["MESSAGE"],
)
return
}
// systemdFlags sets the flags for use with systemd
func systemdFlags(enable *bool, unit, slice, path *string) {
flag.BoolVar(enable, "systemd.enable", false, "Read from the systemd journal instead of log")
flag.StringVar(unit, "systemd.unit", "postfix.service", "Name of the Postfix systemd unit.")
flag.StringVar(slice, "systemd.slice", "", "Name of the Postfix systemd slice. Overrides the systemd unit.")
flag.StringVar(path, "systemd.journal_path", "", "Path to the systemd journal")
}
// CollectLogfileFromJournal Collects entries from the systemd journal.
func (e *PostfixExporter) CollectLogfileFromJournal() error {
e.journal.Lock()
defer e.journal.Unlock()
r := e.journal.Wait(time.Duration(1) * time.Second)
if r < 0 {
log.Print("error while waiting for journal!")
}
for {
m, c, err := e.journal.NextMessage()
if err != nil {
return err
}
if c == 0 {
break
}
e.CollectFromLogline(m)
}
return nil
}