Merge branch 'master' into tail
This commit is contained in:
commit
a4e09a2c37
9
.gitignore
vendored
9
.gitignore
vendored
@ -1,2 +1,9 @@
|
|||||||
|
# Editor files
|
||||||
|
*~
|
||||||
|
-.idea/
|
||||||
|
|
||||||
|
# Test binary, build with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Binaries
|
||||||
postfix_exporter
|
postfix_exporter
|
||||||
.idea/
|
|
||||||
|
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
FROM golang:1.8
|
||||||
|
ADD . /go/src/github.com/kumina/postfix_exporter
|
||||||
|
WORKDIR /go/src/github.com/kumina/postfix_exporter
|
||||||
|
RUN apt-get update -qq && apt-get install -qqy \
|
||||||
|
build-essential \
|
||||||
|
libsystemd-dev
|
||||||
|
RUN go get -v ./...
|
||||||
|
RUN go build
|
||||||
|
|
||||||
|
FROM debian:latest
|
||||||
|
EXPOSE 9154
|
||||||
|
WORKDIR /
|
||||||
|
COPY --from=0 /go/src/github.com/kumina/postfix_exporter/postfix_exporter .
|
||||||
|
ENTRYPOINT ["/postfix_exporter"]
|
@ -3,14 +3,19 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "io"
|
import(
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/alecthomas/kingpin"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
type Journal struct {
|
type Journal struct {
|
||||||
io.Closer
|
io.Closer
|
||||||
Path string
|
Path string
|
||||||
}
|
}
|
||||||
|
|
||||||
func systemdFlags(enable *bool, unit, slice, path *string) {}
|
func systemdFlags(enable *bool, unit, slice, path *string, app *kingpin.Application) {}
|
||||||
|
|
||||||
func NewJournal(unit, slice, path string) (*Journal, error) {
|
func NewJournal(unit, slice, path string) (*Journal, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -17,8 +17,8 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/alecthomas/kingpin"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
@ -78,7 +78,10 @@ type PostfixExporter struct {
|
|||||||
// for null bytes in the first 128 bytes of output.
|
// for null bytes in the first 128 bytes of output.
|
||||||
func CollectShowqFromReader(file io.Reader, ch chan<- prometheus.Metric) error {
|
func CollectShowqFromReader(file io.Reader, ch chan<- prometheus.Metric) error {
|
||||||
reader := bufio.NewReader(file)
|
reader := bufio.NewReader(file)
|
||||||
buf, _ := reader.Peek(128)
|
buf, err := reader.Peek(128)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
log.Printf("Could not read postfix output, %v", err)
|
||||||
|
}
|
||||||
if bytes.IndexByte(buf, 0) >= 0 {
|
if bytes.IndexByte(buf, 0) >= 0 {
|
||||||
return CollectBinaryShowqFromReader(reader, ch)
|
return CollectBinaryShowqFromReader(reader, ch)
|
||||||
}
|
}
|
||||||
@ -92,7 +95,7 @@ func CollectTextualShowqFromReader(file io.Reader, ch chan<- prometheus.Metric)
|
|||||||
|
|
||||||
// Regular expression for matching postqueue's output. Example:
|
// Regular expression for matching postqueue's output. Example:
|
||||||
// "A07A81514 5156 Tue Feb 14 13:13:54 MAILER-DAEMON"
|
// "A07A81514 5156 Tue Feb 14 13:13:54 MAILER-DAEMON"
|
||||||
messageLine := regexp.MustCompile("^[0-9A-F]+([\\*!]?) +(\\d+) (\\w{3} \\w{3} +\\d+ +\\d+:\\d{2}:\\d{2}) +")
|
messageLine := regexp.MustCompile(`^[0-9A-F]+([\*!]?) +(\d+) (\w{3} \w{3} +\d+ +\d+:\d{2}:\d{2}) +`)
|
||||||
|
|
||||||
// Histograms tracking the messages by size and age.
|
// Histograms tracking the messages by size and age.
|
||||||
sizeHistogram := prometheus.NewHistogramVec(
|
sizeHistogram := prometheus.NewHistogramVec(
|
||||||
@ -119,7 +122,11 @@ func CollectTextualShowqFromReader(file io.Reader, ch chan<- prometheus.Metric)
|
|||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
location, _ := time.LoadLocation("Local")
|
location, err := time.LoadLocation("Local")
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
matches := messageLine.FindStringSubmatch(scanner.Text())
|
matches := messageLine.FindStringSubmatch(scanner.Text())
|
||||||
if matches != nil {
|
if matches != nil {
|
||||||
@ -232,11 +239,11 @@ func CollectBinaryShowqFromReader(file io.Reader, ch chan<- prometheus.Metric) e
|
|||||||
sizeHistogram.WithLabelValues(queue).Observe(size)
|
sizeHistogram.WithLabelValues(queue).Observe(size)
|
||||||
} else if key == "time" {
|
} else if key == "time" {
|
||||||
// Message time as a UNIX timestamp.
|
// Message time as a UNIX timestamp.
|
||||||
time, err := strconv.ParseFloat(value, 64)
|
utime, err := strconv.ParseFloat(value, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ageHistogram.WithLabelValues(queue).Observe(now - time)
|
ageHistogram.WithLabelValues(queue).Observe(now - utime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,14 +253,14 @@ func CollectBinaryShowqFromReader(file io.Reader, ch chan<- prometheus.Metric) e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CollectShowqFromFile collects Postfix queue statistics from a file.
|
// CollectShowqFromFile collects Postfix queue statistics from a file.
|
||||||
func CollectShowqFromFile(path string, ch chan<- prometheus.Metric) error {
|
//func CollectShowqFromFile(path string, ch chan<- prometheus.Metric) error {
|
||||||
fd, err := os.Open(path)
|
// fd, err := os.Open(path)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
defer fd.Close()
|
// defer fd.Close()
|
||||||
return CollectShowqFromReader(fd, ch)
|
// return CollectShowqFromReader(fd, ch)
|
||||||
}
|
//}
|
||||||
|
|
||||||
// CollectShowqFromSocket collects Postfix queue statistics from a socket.
|
// CollectShowqFromSocket collects Postfix queue statistics from a socket.
|
||||||
func CollectShowqFromSocket(path string, ch chan<- prometheus.Metric) error {
|
func CollectShowqFromSocket(path string, ch chan<- prometheus.Metric) error {
|
||||||
@ -267,16 +274,16 @@ func CollectShowqFromSocket(path string, ch chan<- prometheus.Metric) error {
|
|||||||
|
|
||||||
// Patterns for parsing log messages.
|
// Patterns for parsing log messages.
|
||||||
var (
|
var (
|
||||||
logLine = regexp.MustCompile(" ?postfix/(\\w+)\\[\\d+\\]: (.*)")
|
logLine = regexp.MustCompile(` ?postfix/(\w+)\[\d+\]: (.*)`)
|
||||||
lmtpPipeSMTPLine = regexp.MustCompile(", relay=(\\S+), .*, delays=([0-9\\.]+)/([0-9\\.]+)/([0-9\\.]+)/([0-9\\.]+), ")
|
lmtpPipeSMTPLine = regexp.MustCompile(`, relay=(\S+), .*, delays=([0-9\.]+)/([0-9\.]+)/([0-9\.]+)/([0-9\.]+), `)
|
||||||
qmgrInsertLine = regexp.MustCompile(":.*, size=(\\d+), nrcpt=(\\d+) ")
|
qmgrInsertLine = regexp.MustCompile(`:.*, size=(\d+), nrcpt=(\d+) `)
|
||||||
smtpTLSLine = regexp.MustCompile("^(\\S+) TLS connection established to \\S+: (\\S+) with cipher (\\S+) \\((\\d+)/(\\d+) bits\\)$")
|
smtpTLSLine = regexp.MustCompile(`^(\S+) TLS connection established to \S+: (\S+) with cipher (\S+) \((\d+)/(\d+) bits\)$`)
|
||||||
smtpdFCrDNSErrorsLine = regexp.MustCompile("^warning: hostname \\S+ does not resolve to address ")
|
smtpdFCrDNSErrorsLine = regexp.MustCompile(`^warning: hostname \S+ does not resolve to address `)
|
||||||
smtpdProcessesSASLLine = regexp.MustCompile(": client=.*, sasl_username=(\\S+)")
|
smtpdProcessesSASLLine = regexp.MustCompile(`: client=.*, sasl_username=(\S+)`)
|
||||||
smtpdRejectsLine = regexp.MustCompile("^NOQUEUE: reject: RCPT from \\S+: ([0-9]+) ")
|
smtpdRejectsLine = regexp.MustCompile(`^NOQUEUE: reject: RCPT from \S+: ([0-9]+) `)
|
||||||
smtpdLostConnectionLine = regexp.MustCompile("^lost connection after (\\w+) from ")
|
smtpdLostConnectionLine = regexp.MustCompile(`^lost connection after (\w+) from `)
|
||||||
smtpdSASLAuthenticationFailuresLine = regexp.MustCompile("^warning: \\S+: SASL \\S+ authentication failed: ")
|
smtpdSASLAuthenticationFailuresLine = regexp.MustCompile(`^warning: \S+: SASL \S+ authentication failed: `)
|
||||||
smtpdTLSLine = regexp.MustCompile("^(\\S+) TLS connection established from \\S+: (\\S+) with cipher (\\S+) \\((\\d+)/(\\d+) bits\\)$")
|
smtpdTLSLine = regexp.MustCompile(`^(\S+) TLS connection established from \S+: (\S+) with cipher (\S+) \((\d+)/(\d+) bits\)$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// CollectFromLogline collects metrict from a Postfix log line.
|
// CollectFromLogline collects metrict from a Postfix log line.
|
||||||
@ -294,35 +301,65 @@ func (e *PostfixExporter) CollectFromLogline(line string) {
|
|||||||
}
|
}
|
||||||
} else if logMatches[1] == "lmtp" {
|
} else if logMatches[1] == "lmtp" {
|
||||||
if lmtpMatches := lmtpPipeSMTPLine.FindStringSubmatch(logMatches[2]); lmtpMatches != nil {
|
if lmtpMatches := lmtpPipeSMTPLine.FindStringSubmatch(logMatches[2]); lmtpMatches != nil {
|
||||||
pdelay, _ := strconv.ParseFloat(lmtpMatches[2], 64)
|
pdelay, err := strconv.ParseFloat(lmtpMatches[2], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert LMTP pdelay: %v", err)
|
||||||
|
}
|
||||||
e.lmtpDelays.WithLabelValues("before_queue_manager").Observe(pdelay)
|
e.lmtpDelays.WithLabelValues("before_queue_manager").Observe(pdelay)
|
||||||
adelay, _ := strconv.ParseFloat(lmtpMatches[3], 64)
|
adelay, err := strconv.ParseFloat(lmtpMatches[3], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert LMTP adelay: %v", err)
|
||||||
|
}
|
||||||
e.lmtpDelays.WithLabelValues("queue_manager").Observe(adelay)
|
e.lmtpDelays.WithLabelValues("queue_manager").Observe(adelay)
|
||||||
sdelay, _ := strconv.ParseFloat(lmtpMatches[4], 64)
|
sdelay, err := strconv.ParseFloat(lmtpMatches[4], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert LMTP adelay: %v", err)
|
||||||
|
}
|
||||||
e.lmtpDelays.WithLabelValues("connection_setup").Observe(sdelay)
|
e.lmtpDelays.WithLabelValues("connection_setup").Observe(sdelay)
|
||||||
xdelay, _ := strconv.ParseFloat(lmtpMatches[5], 64)
|
xdelay, err := strconv.ParseFloat(lmtpMatches[5], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert LMTP xdelay: %v", err)
|
||||||
|
}
|
||||||
e.lmtpDelays.WithLabelValues("transmission").Observe(xdelay)
|
e.lmtpDelays.WithLabelValues("transmission").Observe(xdelay)
|
||||||
} else {
|
} else {
|
||||||
e.unsupportedLogEntries.WithLabelValues(logMatches[1]).Inc()
|
e.unsupportedLogEntries.WithLabelValues(logMatches[1]).Inc()
|
||||||
}
|
}
|
||||||
} else if logMatches[1] == "pipe" {
|
} else if logMatches[1] == "pipe" {
|
||||||
if pipeMatches := lmtpPipeSMTPLine.FindStringSubmatch(logMatches[2]); pipeMatches != nil {
|
if pipeMatches := lmtpPipeSMTPLine.FindStringSubmatch(logMatches[2]); pipeMatches != nil {
|
||||||
pdelay, _ := strconv.ParseFloat(pipeMatches[2], 64)
|
pdelay, err := strconv.ParseFloat(pipeMatches[2], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert PIPE pdelay: %v", err)
|
||||||
|
}
|
||||||
e.pipeDelays.WithLabelValues(pipeMatches[1], "before_queue_manager").Observe(pdelay)
|
e.pipeDelays.WithLabelValues(pipeMatches[1], "before_queue_manager").Observe(pdelay)
|
||||||
adelay, _ := strconv.ParseFloat(pipeMatches[3], 64)
|
adelay, err := strconv.ParseFloat(pipeMatches[3], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert PIPE adelay: %v", err)
|
||||||
|
}
|
||||||
e.pipeDelays.WithLabelValues(pipeMatches[1], "queue_manager").Observe(adelay)
|
e.pipeDelays.WithLabelValues(pipeMatches[1], "queue_manager").Observe(adelay)
|
||||||
sdelay, _ := strconv.ParseFloat(pipeMatches[4], 64)
|
sdelay, err := strconv.ParseFloat(pipeMatches[4], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert PIPE sdelay: %v", err)
|
||||||
|
}
|
||||||
e.pipeDelays.WithLabelValues(pipeMatches[1], "connection_setup").Observe(sdelay)
|
e.pipeDelays.WithLabelValues(pipeMatches[1], "connection_setup").Observe(sdelay)
|
||||||
xdelay, _ := strconv.ParseFloat(pipeMatches[5], 64)
|
xdelay, err := strconv.ParseFloat(pipeMatches[5], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert PIPE xdelay: %v", err)
|
||||||
|
}
|
||||||
e.pipeDelays.WithLabelValues(pipeMatches[1], "transmission").Observe(xdelay)
|
e.pipeDelays.WithLabelValues(pipeMatches[1], "transmission").Observe(xdelay)
|
||||||
} else {
|
} else {
|
||||||
e.unsupportedLogEntries.WithLabelValues(logMatches[1]).Inc()
|
e.unsupportedLogEntries.WithLabelValues(logMatches[1]).Inc()
|
||||||
}
|
}
|
||||||
} else if logMatches[1] == "qmgr" {
|
} else if logMatches[1] == "qmgr" {
|
||||||
if qmgrInsertMatches := qmgrInsertLine.FindStringSubmatch(logMatches[2]); qmgrInsertMatches != nil {
|
if qmgrInsertMatches := qmgrInsertLine.FindStringSubmatch(logMatches[2]); qmgrInsertMatches != nil {
|
||||||
size, _ := strconv.ParseFloat(qmgrInsertMatches[1], 64)
|
size, err := strconv.ParseFloat(qmgrInsertMatches[1], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert QMGR size: %v", err)
|
||||||
|
}
|
||||||
e.qmgrInsertsSize.Observe(size)
|
e.qmgrInsertsSize.Observe(size)
|
||||||
nrcpt, _ := strconv.ParseFloat(qmgrInsertMatches[2], 64)
|
nrcpt, err := strconv.ParseFloat(qmgrInsertMatches[2], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert QMGR nrcpt: %v", err)
|
||||||
|
}
|
||||||
e.qmgrInsertsNrcpt.Observe(nrcpt)
|
e.qmgrInsertsNrcpt.Observe(nrcpt)
|
||||||
} else if strings.HasSuffix(logMatches[2], ": removed") {
|
} else if strings.HasSuffix(logMatches[2], ": removed") {
|
||||||
e.qmgrRemoves.Inc()
|
e.qmgrRemoves.Inc()
|
||||||
@ -331,13 +368,25 @@ func (e *PostfixExporter) CollectFromLogline(line string) {
|
|||||||
}
|
}
|
||||||
} else if logMatches[1] == "smtp" {
|
} else if logMatches[1] == "smtp" {
|
||||||
if smtpMatches := lmtpPipeSMTPLine.FindStringSubmatch(logMatches[2]); smtpMatches != nil {
|
if smtpMatches := lmtpPipeSMTPLine.FindStringSubmatch(logMatches[2]); smtpMatches != nil {
|
||||||
pdelay, _ := strconv.ParseFloat(smtpMatches[2], 64)
|
pdelay, err := strconv.ParseFloat(smtpMatches[2], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert SMTP pdelay: %v", err)
|
||||||
|
}
|
||||||
e.smtpDelays.WithLabelValues("before_queue_manager").Observe(pdelay)
|
e.smtpDelays.WithLabelValues("before_queue_manager").Observe(pdelay)
|
||||||
adelay, _ := strconv.ParseFloat(smtpMatches[3], 64)
|
adelay, err := strconv.ParseFloat(smtpMatches[3], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert SMTP adelay: %v", err)
|
||||||
|
}
|
||||||
e.smtpDelays.WithLabelValues("queue_manager").Observe(adelay)
|
e.smtpDelays.WithLabelValues("queue_manager").Observe(adelay)
|
||||||
sdelay, _ := strconv.ParseFloat(smtpMatches[4], 64)
|
sdelay, err := strconv.ParseFloat(smtpMatches[4], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert SMTP sdelay: %v", err)
|
||||||
|
}
|
||||||
e.smtpDelays.WithLabelValues("connection_setup").Observe(sdelay)
|
e.smtpDelays.WithLabelValues("connection_setup").Observe(sdelay)
|
||||||
xdelay, _ := strconv.ParseFloat(smtpMatches[5], 64)
|
xdelay, err := strconv.ParseFloat(smtpMatches[5], 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Couldn't convert SMTP xdelay: %v", err)
|
||||||
|
}
|
||||||
e.smtpDelays.WithLabelValues("transmission").Observe(xdelay)
|
e.smtpDelays.WithLabelValues("transmission").Observe(xdelay)
|
||||||
} else if smtpTLSMatches := smtpTLSLine.FindStringSubmatch(logMatches[2]); smtpTLSMatches != nil {
|
} else if smtpTLSMatches := smtpTLSLine.FindStringSubmatch(logMatches[2]); smtpTLSMatches != nil {
|
||||||
e.smtpTLSConnects.WithLabelValues(smtpTLSMatches[1:]...).Inc()
|
e.smtpTLSConnects.WithLabelValues(smtpTLSMatches[1:]...).Inc()
|
||||||
@ -610,16 +659,17 @@ func (e *PostfixExporter) Collect(ch chan<- prometheus.Metric) {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var (
|
var (
|
||||||
listenAddress = flag.String("web.listen-address", ":9154", "Address to listen on for web interface and telemetry.")
|
app = kingpin.New("postfix_exporter", "Prometheus metrics exporter for postfix")
|
||||||
metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.")
|
listenAddress = app.Flag("web.listen-address", "Address to listen on for web interface and telemetry.").Default(":9154").String()
|
||||||
postfixShowqPath = flag.String("postfix.showq_path", "/var/spool/postfix/public/showq", "Path at which Postfix places its showq socket.")
|
metricsPath = app.Flag("web.telemetry-path", "Path under which to expose metrics.").Default("/metrics").String()
|
||||||
postfixLogfilePath = flag.String("postfix.logfile_path", "/var/log/postfix_exporter_input.log", "Path where Postfix writes log entries.")
|
postfixShowqPath = app.Flag("postfix.showq_path", "Path at which Postfix places its showq socket.").Default("/var/spool/postfix/public/showq").String()
|
||||||
|
postfixLogfilePath = app.Flag("postfix.logfile_path", "Path where Postfix writes log entries. This file will be truncated by this exporter.").Default("/var/log/postfix_exporter_input.log").String()
|
||||||
systemdEnable bool
|
systemdEnable bool
|
||||||
systemdUnit, systemdSlice, systemdJournalPath string
|
systemdUnit, systemdSlice, systemdJournalPath string
|
||||||
)
|
)
|
||||||
systemdFlags(&systemdEnable, &systemdUnit, &systemdSlice, &systemdJournalPath)
|
systemdFlags(&systemdEnable, &systemdUnit, &systemdSlice, &systemdJournalPath, app)
|
||||||
flag.Parse()
|
|
||||||
|
kingpin.MustParse(app.Parse(os.Args[1:]))
|
||||||
|
|
||||||
var journal *Journal
|
var journal *Journal
|
||||||
if systemdEnable {
|
if systemdEnable {
|
||||||
@ -643,7 +693,7 @@ func main() {
|
|||||||
|
|
||||||
http.Handle(*metricsPath, prometheus.Handler())
|
http.Handle(*metricsPath, prometheus.Handler())
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte(`
|
_, err = w.Write([]byte(`
|
||||||
<html>
|
<html>
|
||||||
<head><title>Postfix Exporter</title></head>
|
<head><title>Postfix Exporter</title></head>
|
||||||
<body>
|
<body>
|
||||||
@ -651,6 +701,9 @@ func main() {
|
|||||||
<p><a href='` + *metricsPath + `'>Metrics</a></p>
|
<p><a href='` + *metricsPath + `'>Metrics</a></p>
|
||||||
</body>
|
</body>
|
||||||
</html>`))
|
</html>`))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
log.Print("Listening on ", *listenAddress)
|
log.Print("Listening on ", *listenAddress)
|
||||||
|
18
systemd.go
18
systemd.go
@ -3,12 +3,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/alecthomas/kingpin"
|
||||||
"github.com/coreos/go-systemd/sdjournal"
|
"github.com/coreos/go-systemd/sdjournal"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -46,8 +46,10 @@ func NewJournal(unit, slice, path string) (j *Journal, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start at end of journal
|
// Start at end of journal
|
||||||
j.SeekRealtimeUsec(uint64(time.Now().UnixNano() / 1000))
|
err = j.SeekRealtimeUsec(uint64(time.Now().UnixNano() / 1000))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("%v", err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,11 +88,11 @@ func (j *Journal) NextMessage() (s string, c uint64, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// systemdFlags sets the flags for use with systemd
|
// systemdFlags sets the flags for use with systemd
|
||||||
func systemdFlags(enable *bool, unit, slice, path *string) {
|
func systemdFlags(enable *bool, unit, slice, path *string, app *kingpin.Application) {
|
||||||
flag.BoolVar(enable, "systemd.enable", false, "Read from the systemd journal instead of log")
|
app.Flag("systemd.enable", "Read from the systemd journal instead of log").Default("false").BoolVar(enable)
|
||||||
flag.StringVar(unit, "systemd.unit", "postfix.service", "Name of the Postfix systemd unit.")
|
app.Flag("systemd.unit", "Name of the Postfix systemd unit.").Default("postfix.service").StringVar(unit)
|
||||||
flag.StringVar(slice, "systemd.slice", "", "Name of the Postfix systemd slice. Overrides the systemd unit.")
|
app.Flag("systemd.slice", "Name of the Postfix systemd slice. Overrides the systemd unit.").Default("").StringVar(slice)
|
||||||
flag.StringVar(path, "systemd.journal_path", "", "Path to the systemd journal")
|
app.Flag("systemd.journal_path", "Path to the systemd journal").Default("").StringVar(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CollectLogfileFromJournal Collects entries from the systemd journal.
|
// CollectLogfileFromJournal Collects entries from the systemd journal.
|
||||||
|
Loading…
Reference in New Issue
Block a user