Adding some test for the showq part. Found a minor bug.

This commit is contained in:
Per Abich 2020-02-24 15:42:20 +01:00
parent 0436fed067
commit bc2175fb01
5 changed files with 230 additions and 17 deletions

46
mock/HistogramVecMock.go Normal file
View File

@ -0,0 +1,46 @@
package mock
import "github.com/prometheus/client_golang/prometheus"
type HistorgramVecMock struct {
mock HistogramMock
}
func (m *HistorgramVecMock) Describe(chan<- *prometheus.Desc) {
panic("implement me")
}
func (m *HistorgramVecMock) GetMetricWith(prometheus.Labels) (prometheus.Observer, error) {
panic("implement me")
}
func (m *HistorgramVecMock) GetMetricWithLabelValues(lvs ...string) (prometheus.Observer, error) {
panic("implement me")
}
func (m *HistorgramVecMock) With(prometheus.Labels) prometheus.Observer {
panic("implement me")
}
func (m *HistorgramVecMock) WithLabelValues(...string) prometheus.Observer {
return m.mock
}
func (m *HistorgramVecMock) CurryWith(prometheus.Labels) (prometheus.ObserverVec, error) {
panic("implement me")
}
func (m *HistorgramVecMock) MustCurryWith(prometheus.Labels) prometheus.ObserverVec {
panic("implement me")
}
func (m *HistorgramVecMock) Collect(chan<- prometheus.Metric) {
panic("implement me")
}
func (m *HistorgramVecMock) GetSum() float64 {
return *m.mock.sum
}
func NewHistogramVecMock() *HistorgramVecMock {
return &HistorgramVecMock{mock: *NewHistogramMock()}
}

34
mock/HistorgramMock.go Normal file
View File

@ -0,0 +1,34 @@
package mock
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_model/go"
)
type HistogramMock struct {
sum *float64
}
func NewHistogramMock() *HistogramMock {
return &HistogramMock{sum: new(float64)}
}
func (HistogramMock) Desc() *prometheus.Desc {
panic("implement me")
}
func (HistogramMock) Write(*io_prometheus_client.Metric) error {
panic("implement me")
}
func (HistogramMock) Describe(chan<- *prometheus.Desc) {
panic("implement me")
}
func (HistogramMock) Collect(chan<- prometheus.Metric) {
panic("implement me")
}
func (h HistogramMock) Observe(value float64) {
*h.sum += value
}

View File

@ -94,12 +94,6 @@ func CollectShowqFromReader(file io.Reader, ch chan<- prometheus.Metric) error {
// CollectTextualShowqFromReader parses Postfix's textual showq output.
func CollectTextualShowqFromReader(file io.Reader, ch chan<- prometheus.Metric) error {
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
// Regular expression for matching postqueue's output. Example:
// "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}) +`)
// Histograms tracking the messages by size and age.
sizeHistogram := prometheus.NewHistogramVec(
@ -119,34 +113,51 @@ func CollectTextualShowqFromReader(file io.Reader, ch chan<- prometheus.Metric)
},
[]string{"queue"})
err := CollectTextualShowqFromScanner(sizeHistogram, ageHistogram, file)
sizeHistogram.Collect(ch)
ageHistogram.Collect(ch)
return err
}
func CollectTextualShowqFromScanner(sizeHistogram prometheus.ObserverVec, ageHistogram prometheus.ObserverVec, file io.Reader) error {
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
// Initialize all queue buckets to zero.
for _, q := range []string{"active", "hold", "other"} {
sizeHistogram.WithLabelValues(q)
ageHistogram.WithLabelValues(q)
}
now := time.Now()
location, err := time.LoadLocation("Local")
if err != nil {
log.Println(err)
}
// Regular expression for matching postqueue's output. Example:
// "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}) +`)
for scanner.Scan() {
matches := messageLine.FindStringSubmatch(scanner.Text())
if matches != nil {
text := scanner.Text()
matches := messageLine.FindStringSubmatch(text)
if matches == nil {
continue
}
queueMatch := matches[1]
sizeMatch := matches[2]
dateMatch := matches[3]
// Derive the name of the message queue.
queue := "other"
if matches[1] == "*" {
if queueMatch == "*" {
queue = "active"
} else if matches[1] == "!" {
} else if queueMatch == "!" {
queue = "hold"
}
// Parse the message size.
size, err := strconv.ParseFloat(matches[2], 64)
size, err := strconv.ParseFloat(sizeMatch, 64)
if err != nil {
return err
}
@ -155,11 +166,11 @@ func CollectTextualShowqFromReader(file io.Reader, ch chan<- prometheus.Metric)
// output contains no year number. Assume it
// applies to the last year for which the
// message date doesn't exceed time.Now().
date, err := time.ParseInLocation("Mon Jan 2 15:04:05",
matches[3], location)
date, err := time.ParseInLocation("Mon Jan 2 15:04:05", dateMatch, location)
if err != nil {
return err
}
now := time.Now()
date = date.AddDate(now.Year(), 0, 0)
if date.After(now) {
date = date.AddDate(-1, 0, 0)
@ -168,9 +179,6 @@ func CollectTextualShowqFromReader(file io.Reader, ch chan<- prometheus.Metric)
sizeHistogram.WithLabelValues(queue).Observe(size)
ageHistogram.WithLabelValues(queue).Observe(now.Sub(date).Seconds())
}
sizeHistogram.Collect(ch)
ageHistogram.Collect(ch)
return scanner.Err()
}

45
showq_test.go Normal file
View File

@ -0,0 +1,45 @@
package main
import (
"github.com/kumina/postfix_exporter/mock"
"github.com/stretchr/testify/assert"
"os"
"testing"
)
func TestCollectShowqFromReader(t *testing.T) {
type args struct {
file string
}
tests := []struct {
name string
args args
wantErr bool
expectedTotalCount float64
}{
{
name: "basic test",
args: args{
file: "testdata/showq.txt",
},
wantErr: false,
expectedTotalCount: 118702,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
file, err := os.Open(tt.args.file)
if err != nil {
t.Error(err)
}
sizeHistogram := mock.NewHistogramVecMock()
ageHistogram := mock.NewHistogramVecMock()
if err := CollectTextualShowqFromScanner(sizeHistogram, ageHistogram, file); (err != nil) != tt.wantErr {
t.Errorf("CollectShowqFromReader() error = %v, wantErr %v", err, tt.wantErr)
}
assert.Equal(t, tt.expectedTotalCount, sizeHistogram.GetSum(), "Expected a lot more data.")
assert.Less(t, 0.0, ageHistogram.GetSum(), "Age not greater than 0")
})
}
}

80
testdata/showq.txt vendored Normal file
View File

@ -0,0 +1,80 @@
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
C420820802* 4387 Mon Feb 24 13:35:18 sender@example.com
recipient@lerum.se
8D5D4205B9* 4033 Mon Feb 24 13:22:16 sender@example.com
recipient@lerum.se
7465520414* 4043 Mon Feb 24 13:22:16 sender@example.com
recipient@lerum.se
3E2F72070A* 5301 Mon Feb 24 13:35:39 sender@example.com
recipient@hotmail.se
542032060A* 5828 Mon Feb 24 13:34:46 sender@example.com
recipient@skatteverket.se
4B96A2037C* 9868 Mon Feb 24 13:32:03 sender@example.com
recipient@lerum.se
E88EA20796* 5956 Mon Feb 24 13:34:55 sender@example.com
recipient@edu.halmstad.se
8C9912052C* 4047 Mon Feb 24 13:22:16 sender@example.com
recipient@lerum.se
70BDA2079B* 4404 Mon Feb 24 13:35:18 sender@example.com
recipient@lerum.se
76E6A20536* 3875 Mon Feb 24 13:21:20 sender@example.com
recipient@lerum.se
92C662062A* 3864 Mon Feb 24 13:21:20 sender@example.com
recipient@lerum.se
BA9BC2071E* 4387 Mon Feb 24 13:35:18 sender@example.com
recipient@lerum.se
9A67020670* 4393 Mon Feb 24 13:34:06 sender@example.com
recipient@lerum.se
651AC20138* 3872 Mon Feb 24 13:23:17 sender@example.com
recipient@lerum.se
4F16D20516* 4052 Mon Feb 24 13:24:38 sender@example.com
recipient@lerum.se
C9C4A20501* 5099 Mon Feb 24 13:14:10 sender@example.com
recipient@haninge.se
0572820D64 4098 Sat Feb 22 00:44:54 sender@example.com
(host mail.wekudata.com[37.208.0.7] said: 452 4.2.2 Quota exceeded (rehanna@stahlstierna.se) (in reply to RCPT TO command))
recipient@stahlstierna.se
0B2C320952 4173 Sat Feb 22 00:42:07 sender@example.com
(host alt1.gmail-smtp-in.l.google.com[108.177.97.26] said: 452-4.2.2 The email account that you tried to reach is over quota. Please direct 452-4.2.2 the recipient to 452 4.2.2 https://support.google.com/mail/?p=OverQuotaTemp q24si6538316pgt.498 - gsmtp (in reply to RCPT TO command))
recipient@gmail.com
0CC2B22124 10926 Fri Feb 21 13:31:58 sender@example.com
(host alt1.gmail-smtp-in.l.google.com[108.177.97.26] said: 452-4.2.2 The email account that you tried to reach is over quota. Please direct 452-4.2.2 the recipient to 452 4.2.2 https://support.google.com/mail/?p=OverQuotaTemp f10si11999094pgj.597 - gsmtp (in reply to RCPT TO command))
recipient@gmail.com
0C84020606 4898 Mon Feb 24 08:30:34 sender@example.com
(host alt1.gmail-smtp-in.l.google.com[108.177.97.26] said: 452-4.2.2 The email account that you tried to reach is over quota. Please direct 452-4.2.2 the recipient to 452 4.2.2 https://support.google.com/mail/?p=OverQuotaTemp 2si12536346pld.231 - gsmtp (in reply to RCPT TO command))
recipient@gmail.com
04EAA203C0 4133 Mon Feb 24 12:21:58 sender@example.com
(host alt1.gmail-smtp-in.l.google.com[108.177.97.26] said: 452-4.2.2 The email account that you tried to reach is over quota. Please direct 452-4.2.2 the recipient to 452 4.2.2 https://support.google.com/mail/?p=OverQuotaTemp i16si12220651pfq.60 - gsmtp (in reply to RCPT TO command))
recipient@gmail.com
00C33202B6 4823 Mon Feb 24 11:32:37 sender@example.com
(connect to gafe.se[151.252.30.111]:25: Connection refused)
recipient@gafe.se
046E0218CA 4154 Mon Feb 24 00:13:12 sender@example.com
(host alt1.gmail-smtp-in.l.google.com[108.177.97.26] said: 452-4.2.2 The email account that you tried to reach is over quota. Please direct 452-4.2.2 the recipient to 452 4.2.2 https://support.google.com/mail/?p=OverQuotaTemp y1si11835269pgi.474 - gsmtp (in reply to RCPT TO command))
recipient@gmail.com
06373212DC 4088 Sat Feb 22 00:34:11 sender@example.com
(connect to smtp.falun.se[192.121.234.25]:25: Connection timed out)
recipient@utb.falun.se