diff --git a/plugins/inputs/dovecot/dovecot.go b/plugins/inputs/dovecot/dovecot.go index bf1b20269..11d4e2f07 100644 --- a/plugins/inputs/dovecot/dovecot.go +++ b/plugins/inputs/dovecot/dovecot.go @@ -15,8 +15,9 @@ import ( ) type Dovecot struct { + Type string + Filters []string Servers []string - Domains []string } func (d *Dovecot) Description() string { @@ -30,12 +31,18 @@ var sampleConfig = ` ## ## If no servers are specified, then localhost is used as the host. servers = ["localhost:24242"] - ## Only collect metrics for these domains, collect all if empty - domains = [] + ## Type is one of "user", "domain", "ip", or "global" + type = "global" + ## Wildcard matches like "*.com". An empty string "" is same as "*" + filters = [""] ` var defaultTimeout = time.Second * time.Duration(5) +var validQuery = map[string]bool{ + "user": true, "domain": true, "global": true, "ip": true, +} + func (d *Dovecot) SampleConfig() string { return sampleConfig } const defaultPort = "24242" @@ -43,6 +50,11 @@ const defaultPort = "24242" // Reads stats from all configured servers. func (d *Dovecot) Gather(acc telegraf.Accumulator) error { + if !validQuery[d.Type] { + return fmt.Errorf("Error: %s is not a valid query type\n", + d.Type) + } + if len(d.Servers) == 0 { d.Servers = append(d.Servers, "127.0.0.1:24242") } @@ -51,18 +63,15 @@ func (d *Dovecot) Gather(acc telegraf.Accumulator) error { var outerr error - var domains = make(map[string]bool) - - for _, dom := range d.Domains { - domains[dom] = true - } - for _, serv := range d.Servers { - wg.Add(1) - go func(serv string) { - defer wg.Done() - outerr = d.gatherServer(serv, acc, domains) - }(serv) + for _, filter := range d.Filters { + wg.Add(1) + go func(serv string, filt string) { + defer wg.Done() + outerr = d.gatherServer(serv, acc, + d.Type, filt) + }(serv, filter) + } } wg.Wait() @@ -70,7 +79,8 @@ func (d *Dovecot) Gather(acc telegraf.Accumulator) error { return outerr } -func (d *Dovecot) gatherServer(addr string, acc telegraf.Accumulator, doms map[string]bool) error { +func (d *Dovecot) gatherServer(addr string, acc telegraf.Accumulator, + qtype string, filter string) error { _, _, err := net.SplitHostPort(addr) if err != nil { return fmt.Errorf("Error: %s on url %s\n", err, addr) @@ -85,17 +95,24 @@ func (d *Dovecot) gatherServer(addr string, acc telegraf.Accumulator, doms map[s // Extend connection c.SetDeadline(time.Now().Add(defaultTimeout)) - c.Write([]byte("EXPORT\tdomain\n")) + msg := fmt.Sprintf("EXPORT\t%s", qtype) + if len(filter) > 0 { + msg += fmt.Sprintf("\t%s=%s", qtype, filter) + } + msg += "\n" + + c.Write([]byte(msg)) var buf bytes.Buffer io.Copy(&buf, c) // buf := bufio.NewReader(c) host, _, _ := net.SplitHostPort(addr) - return gatherStats(&buf, acc, doms, host) + return gatherStats(&buf, acc, host, qtype) } -func gatherStats(buf *bytes.Buffer, acc telegraf.Accumulator, doms map[string]bool, host string) error { +func gatherStats(buf *bytes.Buffer, acc telegraf.Accumulator, + host string, qtype string) error { lines := strings.Split(buf.String(), "\n") head := strings.Split(lines[0], "\t") @@ -107,17 +124,13 @@ func gatherStats(buf *bytes.Buffer, acc telegraf.Accumulator, doms map[string]bo } val := strings.Split(vals[i], "\t") fields := make(map[string]interface{}) - if len(doms) > 0 && !doms[val[0]] { - continue - } - tags := map[string]string{"server": host, "domain": val[0]} + tags := map[string]string{"server": host} for n := range val { switch head[n] { - case "domain": - continue - // fields[head[n]] = val[n] + case qtype: + tags[head[n]] = val[n] case "user_cpu", "sys_cpu", "clock_time": - fields[head[n]] = secParser(val[n]) + fields[head[n]], _ = strconv.ParseFloat(val[n], 64) case "reset_timestamp", "last_update": fields[head[n]] = timeParser(val[n]) default: diff --git a/plugins/inputs/dovecot/dovecot_test.go b/plugins/inputs/dovecot/dovecot_test.go index 76425c0db..85897504c 100644 --- a/plugins/inputs/dovecot/dovecot_test.go +++ b/plugins/inputs/dovecot/dovecot_test.go @@ -4,9 +4,11 @@ import ( "bytes" "testing" "time" + "strconv" "github.com/influxdata/telegraf/testutil" "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" ) func TestDovecot(t *testing.T) { @@ -16,14 +18,11 @@ func TestDovecot(t *testing.T) { } var acc testutil.Accumulator - tags := map[string]string{"server": "dovecot.test", "domain": "domain.test"} + tags := map[string]string{"server": "dovecot.test", + "domain": "domain.bad"} buf := bytes.NewBufferString(sampleStats) - var doms = map[string]bool{ - "domain.test": true, - } - - err := gatherStats(buf, &acc, doms, "dovecot.test") + err := gatherStats(buf, &acc, "dovecot.test", "domain") require.NoError(t, err) fields := map[string]interface{}{ @@ -56,6 +55,12 @@ func TestDovecot(t *testing.T) { } +func TestFloatConversion(t *testing.T) { + f, err := strconv.ParseFloat("4326001931528183.495762", 64) + require.NoError(t, err) + assert.Equal(t, 4326001931528183.495762, f) +} + const sampleStats = `domain reset_timestamp last_update num_logins num_cmds num_connected_sessions user_cpu sys_cpu clock_time min_faults maj_faults vol_cs invol_cs disk_input disk_output read_count read_bytes write_count write_bytes mail_lookup_path mail_lookup_attr mail_read_count mail_read_bytes mail_cache_hits domain.bad 1453970076 1454603947.383029 10749 33828 0 177988.524000 148071.772000 7531838964717.193706 212491179 2125 2190386067 112779200 74487934976 3221808119808 2469948401 5237602841760 1091171292 2951966459802 15363 0 2922 136403379 334372 domain.test 1453969886 1454603963.039864 7503897 52595715 1204 100831175.372000 83849071.112000 4326001931528183.495762 763950011 1112443 4120386897 3685239306 41679480946688 1819070669176832 2368906465 2957928122981169 3545389615 1666822498251286 24396105 302845 20155768 669946617705 1557255080`