dovecot: enable global and user queries
This commit is contained in:
parent
62961c6bc9
commit
3ce0647932
|
@ -10,20 +10,25 @@ domains. You can read Dovecot's documentation
|
||||||
```
|
```
|
||||||
# Read metrics about dovecot servers
|
# Read metrics about dovecot servers
|
||||||
[[inputs.dovecot]]
|
[[inputs.dovecot]]
|
||||||
# Dovecot servers
|
## specify dovecot servers via an address:port list
|
||||||
# specify dovecot servers via an address:port list
|
## e.g.
|
||||||
# e.g.
|
## localhost:24242
|
||||||
# localhost:24242
|
##
|
||||||
#
|
## If no servers are specified, then localhost is used as the host.
|
||||||
# If no servers are specified, then localhost is used as the host.
|
|
||||||
servers = ["localhost:24242"]
|
servers = ["localhost:24242"]
|
||||||
# Only collect metrics for these domains, collect all if empty
|
## Type is one of "user", "domain", "ip", or "global"
|
||||||
domains = []
|
type = "global"
|
||||||
|
## Wildcard matches like "*.com". An empty string "" is same as "*"
|
||||||
|
## If type = "ip" filters should be <IP/network>
|
||||||
|
filters = [""]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Tags:
|
### Tags:
|
||||||
server: hostname
|
server: hostname
|
||||||
|
type: query type
|
||||||
|
ip: ip addr
|
||||||
|
user: username
|
||||||
domain: domain name
|
domain: domain name
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Dovecot struct {
|
type Dovecot struct {
|
||||||
|
Type string
|
||||||
|
Filters []string
|
||||||
Servers []string
|
Servers []string
|
||||||
Domains []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dovecot) Description() string {
|
func (d *Dovecot) Description() string {
|
||||||
|
@ -30,12 +31,19 @@ var sampleConfig = `
|
||||||
##
|
##
|
||||||
## If no servers are specified, then localhost is used as the host.
|
## If no servers are specified, then localhost is used as the host.
|
||||||
servers = ["localhost:24242"]
|
servers = ["localhost:24242"]
|
||||||
## Only collect metrics for these domains, collect all if empty
|
## Type is one of "user", "domain", "ip", or "global"
|
||||||
domains = []
|
type = "global"
|
||||||
|
## Wildcard matches like "*.com". An empty string "" is same as "*"
|
||||||
|
## If type = "ip" filters should be <IP/network>
|
||||||
|
filters = [""]
|
||||||
`
|
`
|
||||||
|
|
||||||
var defaultTimeout = time.Second * time.Duration(5)
|
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 }
|
func (d *Dovecot) SampleConfig() string { return sampleConfig }
|
||||||
|
|
||||||
const defaultPort = "24242"
|
const defaultPort = "24242"
|
||||||
|
@ -43,6 +51,11 @@ const defaultPort = "24242"
|
||||||
// Reads stats from all configured servers.
|
// Reads stats from all configured servers.
|
||||||
func (d *Dovecot) Gather(acc telegraf.Accumulator) error {
|
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 {
|
if len(d.Servers) == 0 {
|
||||||
d.Servers = append(d.Servers, "127.0.0.1:24242")
|
d.Servers = append(d.Servers, "127.0.0.1:24242")
|
||||||
}
|
}
|
||||||
|
@ -51,18 +64,14 @@ func (d *Dovecot) Gather(acc telegraf.Accumulator) error {
|
||||||
|
|
||||||
var outerr error
|
var outerr error
|
||||||
|
|
||||||
var domains = make(map[string]bool)
|
|
||||||
|
|
||||||
for _, dom := range d.Domains {
|
|
||||||
domains[dom] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, serv := range d.Servers {
|
for _, serv := range d.Servers {
|
||||||
|
for _, filter := range d.Filters {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(serv string) {
|
go func(serv string, filter string) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
outerr = d.gatherServer(serv, acc, domains)
|
outerr = d.gatherServer(serv, acc, d.Type, filter)
|
||||||
}(serv)
|
}(serv, filter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
@ -70,7 +79,7 @@ func (d *Dovecot) Gather(acc telegraf.Accumulator) error {
|
||||||
return outerr
|
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)
|
_, _, err := net.SplitHostPort(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error: %s on url %s\n", err, addr)
|
return fmt.Errorf("Error: %s on url %s\n", err, addr)
|
||||||
|
@ -85,17 +94,22 @@ func (d *Dovecot) gatherServer(addr string, acc telegraf.Accumulator, doms map[s
|
||||||
// Extend connection
|
// Extend connection
|
||||||
c.SetDeadline(time.Now().Add(defaultTimeout))
|
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
|
var buf bytes.Buffer
|
||||||
io.Copy(&buf, c)
|
io.Copy(&buf, c)
|
||||||
// buf := bufio.NewReader(c)
|
|
||||||
|
|
||||||
host, _, _ := net.SplitHostPort(addr)
|
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")
|
lines := strings.Split(buf.String(), "\n")
|
||||||
head := strings.Split(lines[0], "\t")
|
head := strings.Split(lines[0], "\t")
|
||||||
|
@ -107,15 +121,18 @@ func gatherStats(buf *bytes.Buffer, acc telegraf.Accumulator, doms map[string]bo
|
||||||
}
|
}
|
||||||
val := strings.Split(vals[i], "\t")
|
val := strings.Split(vals[i], "\t")
|
||||||
fields := make(map[string]interface{})
|
fields := make(map[string]interface{})
|
||||||
if len(doms) > 0 && !doms[val[0]] {
|
tags := map[string]string{"server": host, "type": qtype}
|
||||||
|
switch qtype {
|
||||||
|
case "global":
|
||||||
continue
|
continue
|
||||||
|
default:
|
||||||
|
tags[qtype] = val[0]
|
||||||
}
|
}
|
||||||
tags := map[string]string{"server": host, "domain": val[0]}
|
|
||||||
for n := range val {
|
for n := range val {
|
||||||
switch head[n] {
|
switch head[n] {
|
||||||
case "domain":
|
case qtype:
|
||||||
continue
|
continue
|
||||||
// fields[head[n]] = val[n]
|
|
||||||
case "user_cpu", "sys_cpu", "clock_time":
|
case "user_cpu", "sys_cpu", "clock_time":
|
||||||
fields[head[n]] = secParser(val[n])
|
fields[head[n]] = secParser(val[n])
|
||||||
case "reset_timestamp", "last_update":
|
case "reset_timestamp", "last_update":
|
||||||
|
|
|
@ -15,15 +15,12 @@ func TestDovecot(t *testing.T) {
|
||||||
t.Skip("Skipping integration test in short mode")
|
t.Skip("Skipping integration test in short mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test type=global
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
tags := map[string]string{"server": "dovecot.test", "domain": "domain.test"}
|
tags := map[string]string{"server": "dovecot.test", "type": "global"}
|
||||||
buf := bytes.NewBufferString(sampleStats)
|
buf := bytes.NewBufferString(sampleGlobal)
|
||||||
|
|
||||||
var doms = map[string]bool{
|
err := gatherStats(buf, &acc, "dovecot.test", "global")
|
||||||
"domain.test": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := gatherStats(buf, &acc, doms, "dovecot.test")
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
fields := map[string]interface{}{
|
fields := map[string]interface{}{
|
||||||
|
@ -56,6 +53,17 @@ func TestDovecot(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
const sampleGlobal = `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
|
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`
|
||||||
|
|
||||||
|
const sampleDomain = `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.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`
|
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`
|
||||||
|
|
||||||
|
const sampleUser = `user reset_timestamp last_update num_logins num_cmds 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
|
||||||
|
user.1@tiscali.it 1460041745 1460041745.258851 2 0 8.868000 6.344000 2920083490.361458 706804 448916 48979 268148736 950759424 632685 1556937725 219865 907305251 0 0 0 0 0
|
||||||
|
user.2@tiscali.it 1460041657 1460041658.284800 2 0 1.192000 0.660000 2920083316.276633 13873 0 60226 5584 31674368 122347520 78251 207879097 27095 118197529 0 0 0 0 0
|
||||||
|
user.3@tiscali.it 1460041657 1460041717.175634 1 7 0.0 0.0 0.20 319 0 50 9 61440 1228867 73508 28 3174 0 0 0 0 0`
|
||||||
|
|
||||||
|
const sampleIp = `ip 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
|
||||||
|
192.168.0.100 1460041847 1460041847.849766 1 0 0 0.4000 0.0 0.49 449 0 70 3 4096 1228861 45414 24 1606 0 0 0 0 0
|
||||||
|
192.168.0.201 1460041772 1460041772.737830 1 0 0 0.0 0.0 0.0 0 0 0 0 0 0 00 0 0 0 0 0 0 0`
|
||||||
|
|
Loading…
Reference in New Issue