Merge remote-tracking branch 'kumina/master'

This commit is contained in:
Per Abich 2020-02-24 16:03:53 +01:00
commit 02162353c1
2 changed files with 80 additions and 46 deletions

View File

@ -282,10 +282,10 @@ var (
lmtpPipeSMTPLine = regexp.MustCompile(`, relay=(\S+), .*, delays=([0-9\.]+)/([0-9\.]+)/([0-9\.]+)/([0-9\.]+), `)
qmgrInsertLine = regexp.MustCompile(`:.*, size=(\d+), nrcpt=(\d+) `)
smtpStatusDeferredLine = regexp.MustCompile(`, status=deferred`)
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\)`)
smtpConnectionTimedOut = regexp.MustCompile(`^connect\s+to\s+(.*)\[(.*)\]:(\d+):\s+(Connection timed out)$`)
smtpdFCrDNSErrorsLine = regexp.MustCompile(`^warning: hostname \S+ does not resolve to address `)
smtpdProcessesSASLLine = regexp.MustCompile(`: client=.*, sasl_username=(\S+)`)
smtpdProcessesSASLLine = regexp.MustCompile(`: client=.*, sasl_method=(\S+)`)
smtpdRejectsLine = regexp.MustCompile(`^NOQUEUE: reject: RCPT from \S+: ([0-9]+) `)
smtpdLostConnectionLine = regexp.MustCompile(`^lost connection after (\w+) from `)
smtpdSASLAuthenticationFailuresLine = regexp.MustCompile(`^warning: \S+: SASL \S+ authentication failed: `)
@ -372,8 +372,8 @@ func (e *PostfixExporter) CollectFromLogLine(line string) {
e.smtpdLostConnections.WithLabelValues(smtpdLostConnectionMatches[1]).Inc()
} else if smtpdProcessesSASLMatches := smtpdProcessesSASLLine.FindStringSubmatch(remainder); smtpdProcessesSASLMatches != nil {
e.smtpdProcesses.WithLabelValues(smtpdProcessesSASLMatches[1]).Inc()
} else if strings.Contains(logMatches[2], ": client=") {
e.smtpdProcesses.WithLabelValues("").Inc()
} else if strings.Contains(remainder, ": client=") {
e.smtpdProcesses.WithLabelValues(smtpdProcessesSASLMatches[1]).Inc()
} else if smtpdRejectsMatches := smtpdRejectsLine.FindStringSubmatch(remainder); smtpdRejectsMatches != nil {
e.smtpdRejects.WithLabelValues(smtpdRejectsMatches[1]).Inc()
} else if smtpdSASLAuthenticationFailuresLine.MatchString(remainder) {
@ -449,9 +449,10 @@ func NewPostfixExporter(showqPath string, logfilePath string, journal *Journal,
if logfilePath != "" {
var err error
tailer, err = tail.TailFile(logfilePath, tail.Config{
ReOpen: true, // reopen the file if it's rotated
MustExist: true, // fail immediately if the file is missing or has incorrect permissions
Follow: true, // run in follow mode
ReOpen: true, // reopen the file if it's rotated
MustExist: true, // fail immediately if the file is missing or has incorrect permissions
Follow: true, // run in follow mode
Location: &tail.SeekInfo{Whence: io.SeekEnd}, // seek to end of file
})
if err != nil {
return nil, err
@ -564,7 +565,7 @@ func NewPostfixExporter(showqPath string, logfilePath string, journal *Journal,
Name: "smtpd_messages_processed_total",
Help: "Total number of messages processed.",
},
[]string{"sasl_username"}),
[]string{"sasl_method"}),
smtpdRejects: prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: "postfix",

View File

@ -35,9 +35,11 @@ func TestPostfixExporter_CollectFromLogline(t *testing.T) {
unsupportedLogEntries *prometheus.CounterVec
}
type args struct {
line []string
removedCount int
saslFailedCount int
line []string
removedCount int
saslFailedCount int
outgoingTLS int
smtpdMessagesProcessed int
}
tests := []struct {
name string
@ -54,7 +56,7 @@ func TestPostfixExporter_CollectFromLogline(t *testing.T) {
saslFailedCount: 0,
},
fields: fields{
qmgrRemoves: &testCounter{count: 0},
qmgrRemoves: prometheus.NewCounter(prometheus.CounterOpts{}),
unsupportedLogEntries: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"process"}),
},
},
@ -98,7 +100,7 @@ func TestPostfixExporter_CollectFromLogline(t *testing.T) {
saslFailedCount: 0,
},
fields: fields{
qmgrRemoves: &testCounter{count: 0},
qmgrRemoves: prometheus.NewCounter(prometheus.CounterOpts{}),
unsupportedLogEntries: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"process"}),
},
},
@ -114,10 +116,42 @@ func TestPostfixExporter_CollectFromLogline(t *testing.T) {
removedCount: 0,
},
fields: fields{
smtpdSASLAuthenticationFailures: &testCounter{count: 0},
smtpdSASLAuthenticationFailures: prometheus.NewCounter(prometheus.CounterOpts{}),
unsupportedLogEntries: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"process"}),
},
},
{
name: "SASL login",
args: args{
line: []string{
"Oct 30 13:19:26 mailgw-out1 postfix/smtpd[27530]: EB4B2C19E2: client=xxx[1.2.3.4], sasl_method=PLAIN, sasl_username=user@domain",
},
removedCount: 0,
saslFailedCount: 0,
outgoingTLS: 0,
smtpdMessagesProcessed: 1,
},
fields: fields{
unsupportedLogEntries: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"process"}),
smtpdProcesses: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"sasl_method"}),
},
},
{
name: "Issue #35",
args: args{
line: []string{
"Jul 24 04:38:17 mail postfix/smtp[30582]: Verified TLS connection established to gmail-smtp-in.l.google.com[108.177.14.26]:25: TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256",
"Jul 24 03:28:15 mail postfix/smtp[24052]: Verified TLS connection established to mx2.comcast.net[2001:558:fe21:2a::6]:25: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)",
},
removedCount: 0,
saslFailedCount: 0,
outgoingTLS: 2,
},
fields: fields{
unsupportedLogEntries: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"process"}),
smtpTLSConnects: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"Verified", "TLSv1.2", "ECDHE-RSA-AES256-GCM-SHA384", "256", "256"}),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -145,52 +179,51 @@ func TestPostfixExporter_CollectFromLogline(t *testing.T) {
smtpdSASLAuthenticationFailures: tt.fields.smtpdSASLAuthenticationFailures,
smtpdTLSConnects: tt.fields.smtpdTLSConnects,
unsupportedLogEntries: tt.fields.unsupportedLogEntries,
logUnsupportedLines: true,
}
for _, line := range tt.args.line {
e.CollectFromLogLine(line)
}
assertCounterEquals(t, e.qmgrRemoves, tt.args.removedCount, "Wrong number of lines counted")
assertCounterEquals(t, e.smtpdSASLAuthenticationFailures, tt.args.saslFailedCount, "Wrong number of Sasl counter counted")
assertCounterEquals(t, e.smtpTLSConnects, tt.args.outgoingTLS, "Wrong number of TLS connections counted")
assertCounterEquals(t, e.smtpdProcesses, tt.args.smtpdMessagesProcessed, "Wrong number of smtpd messages processed")
})
}
}
func assertCounterEquals(t *testing.T, counter prometheus.Counter, expected int, message string) {
func assertCounterEquals(t *testing.T, counter prometheus.Collector, expected int, message string) {
if counter != nil && expected > 0 {
switch counter.(type) {
case *testCounter:
counter := counter.(*testCounter)
assert.Equal(t, expected, counter.Count(), message)
case *prometheus.CounterVec:
counter := counter.(*prometheus.CounterVec)
metricsChan := make(chan prometheus.Metric)
go func() {
counter.Collect(metricsChan)
close(metricsChan)
}()
var count int = 0
for metric := range metricsChan {
metricDto := io_prometheus_client.Metric{}
metric.Write(&metricDto)
count += int(*metricDto.Counter.Value)
}
assert.Equal(t, expected, count, message)
case prometheus.Counter:
metricsChan := make(chan prometheus.Metric)
go func() {
counter.Collect(metricsChan)
close(metricsChan)
}()
var count int = 0
for metric := range metricsChan {
metricDto := io_prometheus_client.Metric{}
metric.Write(&metricDto)
count += int(*metricDto.Counter.Value)
}
assert.Equal(t, expected, count, message)
default:
t.Fatal("Type not implemented")
}
}
}
type testCounter struct {
count int
}
func (t *testCounter) setCount(count int) {
t.count = count
}
func (t *testCounter) Count() int {
return t.count
}
func (t *testCounter) Add(_ float64) {
}
func (t *testCounter) Collect(_ chan<- prometheus.Metric) {
}
func (t *testCounter) Describe(_ chan<- *prometheus.Desc) {
}
func (t *testCounter) Desc() *prometheus.Desc {
return nil
}
func (t *testCounter) Inc() {
t.count++
}
func (t *testCounter) Write(_ *io_prometheus_client.Metric) error {
return nil
}