Merge pull request #44 from UnikumAB/Issue#38

Fixes #38 List of postfix_smtpd_messages_processed_total growing over time
This commit is contained in:
Ivaylo Korakov 2020-02-24 11:18:16 +01:00 committed by GitHub
commit 52ac4648f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 53 deletions

View File

@ -277,7 +277,7 @@ var (
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)$`) smtpConnectionTimedOut = regexp.MustCompile(`^connect\s+to\s+(.*)\[(.*)\]:(\d+):\s+(Connection timed out)$`)
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_method=(\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: `)
@ -364,8 +364,8 @@ func (e *PostfixExporter) CollectFromLogLine(line string) {
e.smtpdLostConnections.WithLabelValues(smtpdLostConnectionMatches[1]).Inc() e.smtpdLostConnections.WithLabelValues(smtpdLostConnectionMatches[1]).Inc()
} else if smtpdProcessesSASLMatches := smtpdProcessesSASLLine.FindStringSubmatch(remainder); smtpdProcessesSASLMatches != nil { } else if smtpdProcessesSASLMatches := smtpdProcessesSASLLine.FindStringSubmatch(remainder); smtpdProcessesSASLMatches != nil {
e.smtpdProcesses.WithLabelValues(smtpdProcessesSASLMatches[1]).Inc() e.smtpdProcesses.WithLabelValues(smtpdProcessesSASLMatches[1]).Inc()
} else if strings.Contains(logMatches[2], ": client=") { } else if strings.Contains(remainder, ": client=") {
e.smtpdProcesses.WithLabelValues("").Inc() e.smtpdProcesses.WithLabelValues(smtpdProcessesSASLMatches[1]).Inc()
} else if smtpdRejectsMatches := smtpdRejectsLine.FindStringSubmatch(remainder); smtpdRejectsMatches != nil { } else if smtpdRejectsMatches := smtpdRejectsLine.FindStringSubmatch(remainder); smtpdRejectsMatches != nil {
e.smtpdRejects.WithLabelValues(smtpdRejectsMatches[1]).Inc() e.smtpdRejects.WithLabelValues(smtpdRejectsMatches[1]).Inc()
} else if smtpdSASLAuthenticationFailuresLine.MatchString(remainder) { } else if smtpdSASLAuthenticationFailuresLine.MatchString(remainder) {
@ -557,7 +557,7 @@ func NewPostfixExporter(showqPath string, logfilePath string, journal *Journal,
Name: "smtpd_messages_processed_total", Name: "smtpd_messages_processed_total",
Help: "Total number of messages processed.", Help: "Total number of messages processed.",
}, },
[]string{"sasl_username"}), []string{"sasl_method"}),
smtpdRejects: prometheus.NewCounterVec( smtpdRejects: prometheus.NewCounterVec(
prometheus.CounterOpts{ prometheus.CounterOpts{
Namespace: "postfix", Namespace: "postfix",

View File

@ -35,10 +35,11 @@ func TestPostfixExporter_CollectFromLogline(t *testing.T) {
unsupportedLogEntries *prometheus.CounterVec unsupportedLogEntries *prometheus.CounterVec
} }
type args struct { type args struct {
line []string line []string
removedCount int removedCount int
saslFailedCount int saslFailedCount int
outgoingTLS int outgoingTLS int
smtpdMessagesProcessed int
} }
tests := []struct { tests := []struct {
name string name string
@ -55,7 +56,7 @@ func TestPostfixExporter_CollectFromLogline(t *testing.T) {
saslFailedCount: 0, saslFailedCount: 0,
}, },
fields: fields{ fields: fields{
qmgrRemoves: &testCounter{count: 0}, qmgrRemoves: prometheus.NewCounter(prometheus.CounterOpts{}),
unsupportedLogEntries: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"process"}), unsupportedLogEntries: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"process"}),
}, },
}, },
@ -99,7 +100,7 @@ func TestPostfixExporter_CollectFromLogline(t *testing.T) {
saslFailedCount: 0, saslFailedCount: 0,
}, },
fields: fields{ fields: fields{
qmgrRemoves: &testCounter{count: 0}, qmgrRemoves: prometheus.NewCounter(prometheus.CounterOpts{}),
unsupportedLogEntries: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"process"}), unsupportedLogEntries: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"process"}),
}, },
}, },
@ -115,10 +116,26 @@ func TestPostfixExporter_CollectFromLogline(t *testing.T) {
removedCount: 0, removedCount: 0,
}, },
fields: fields{ fields: fields{
smtpdSASLAuthenticationFailures: &testCounter{count: 0}, smtpdSASLAuthenticationFailures: prometheus.NewCounter(prometheus.CounterOpts{}),
unsupportedLogEntries: prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"process"}), 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", name: "Issue #35",
args: args{ args: args{
@ -169,11 +186,12 @@ func TestPostfixExporter_CollectFromLogline(t *testing.T) {
} }
assertCounterEquals(t, e.qmgrRemoves, tt.args.removedCount, "Wrong number of lines counted") 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.smtpdSASLAuthenticationFailures, tt.args.saslFailedCount, "Wrong number of Sasl counter counted")
assertCounterVecEquals(t, e.smtpTLSConnects, tt.args.outgoingTLS, "Wrong number of TLS connections 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 assertCounterVecEquals(t *testing.T, counter prometheus.Collector, expected int, message string) { func assertCounterEquals(t *testing.T, counter prometheus.Collector, expected int, message string) {
if counter != nil && expected > 0 { if counter != nil && expected > 0 {
switch counter.(type) { switch counter.(type) {
@ -191,48 +209,21 @@ func assertCounterVecEquals(t *testing.T, counter prometheus.Collector, expected
count += int(*metricDto.Counter.Value) count += int(*metricDto.Counter.Value)
} }
assert.Equal(t, expected, count, message) 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: default:
t.Fatal("Type not implemented") t.Fatal("Type not implemented")
} }
} }
} }
func assertCounterEquals(t *testing.T, counter prometheus.Counter, expected int, message string) {
if counter != nil && expected > 0 {
switch counter.(type) {
case *testCounter:
counter := counter.(*testCounter)
assert.Equal(t, expected, counter.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
}