Sudo support for ceph/varnish plugin
In many default installations ceph and varnish binaries require root permissions or specific user permissions to actually gather metrics. Although it's possible to instrumented system configuration to either run telegraf with root privileges or share the same user/permissions as measured software it's not a default setup. In my opinion ability to run binary with `sudo` makes entire setup simpler without additional interaction. My changes allow to use configuration like: ``` binary = "/usr/bin/sudo /usr/bin/varnishstat" ceph_binary = "/usr/bin/sudo /usr/bin/ceph" ``` With a proper sudo configuration it will simplify amount of changes needed to collect metrics. I've also changed type of varnish metrics. It was `int` but in varnish source code we can find all metrics are actually uint64 (https://github.com/varnishcache/varnish-cache/blob/master/include/tbl/vsc_f_main.h) I hit that issue with some metrics: ``` ~# varnishstat -1 | grep -i MAIN.n_objectcore MAIN.n_objectcore 18446744073709550877 . objectcore structs made ```
This commit is contained in:
parent
3e4a19539a
commit
e3e6fa4f1d
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/gonuts/go-shellquote"
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
"github.com/influxdata/telegraf/plugins/inputs"
|
"github.com/influxdata/telegraf/plugins/inputs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -109,7 +110,13 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var perfDump = func(binary string, socket *socket) (string, error) {
|
var perfDump = func(binary string, socket *socket) (string, error) {
|
||||||
|
split_cmd, err := shellquote.Split(binary)
|
||||||
|
if err != nil || len(split_cmd) == 0 {
|
||||||
|
return "", fmt.Errorf("exec: unable to parse command, %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
cmdArgs := []string{"--admin-daemon", socket.socket}
|
cmdArgs := []string{"--admin-daemon", socket.socket}
|
||||||
|
|
||||||
if socket.sockType == typeOsd {
|
if socket.sockType == typeOsd {
|
||||||
cmdArgs = append(cmdArgs, "perf", "dump")
|
cmdArgs = append(cmdArgs, "perf", "dump")
|
||||||
} else if socket.sockType == typeMon {
|
} else if socket.sockType == typeMon {
|
||||||
|
@ -118,10 +125,12 @@ var perfDump = func(binary string, socket *socket) (string, error) {
|
||||||
return "", fmt.Errorf("ignoring unknown socket type: %s", socket.sockType)
|
return "", fmt.Errorf("ignoring unknown socket type: %s", socket.sockType)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(binary, cmdArgs...)
|
split_cmd = append(split_cmd, cmdArgs...)
|
||||||
|
|
||||||
|
cmd := exec.Command(split_cmd[0], split_cmd[1:]...)
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
err := cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("error running ceph dump: %s", err)
|
return "", fmt.Errorf("error running ceph dump: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gonuts/go-shellquote"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
"github.com/influxdata/telegraf/internal"
|
"github.com/influxdata/telegraf/internal"
|
||||||
"github.com/influxdata/telegraf/plugins/inputs"
|
"github.com/influxdata/telegraf/plugins/inputs"
|
||||||
|
@ -84,12 +86,17 @@ func (s *Varnish) statsFilter() func(string) bool {
|
||||||
|
|
||||||
// Shell out to varnish_stat and return the output
|
// Shell out to varnish_stat and return the output
|
||||||
var varnishStat = func(cmdName string) (*bytes.Buffer, error) {
|
var varnishStat = func(cmdName string) (*bytes.Buffer, error) {
|
||||||
|
split_cmd, err := shellquote.Split(cmdName)
|
||||||
|
if err != nil || len(split_cmd) == 0 {
|
||||||
|
return nil, fmt.Errorf("exec: unable to parse command, %s", err)
|
||||||
|
}
|
||||||
cmdArgs := []string{"-1"}
|
cmdArgs := []string{"-1"}
|
||||||
|
split_cmd = append(split_cmd, cmdArgs...)
|
||||||
|
|
||||||
cmd := exec.Command(cmdName, cmdArgs...)
|
cmd := exec.Command(split_cmd[0], split_cmd[1:]...)
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
err := internal.RunTimeout(cmd, time.Millisecond*200)
|
err = internal.RunTimeout(cmd, time.Millisecond*200)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &out, fmt.Errorf("error running varnishstat: %s", err)
|
return &out, fmt.Errorf("error running varnishstat: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -138,7 +145,7 @@ func (s *Varnish) Gather(acc telegraf.Accumulator) error {
|
||||||
sectionMap[section] = make(map[string]interface{})
|
sectionMap[section] = make(map[string]interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
sectionMap[section][field], err = strconv.Atoi(value)
|
sectionMap[section][field], err = strconv.ParseUint(value, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Expected a numeric value for %s = %v\n",
|
fmt.Fprintf(os.Stderr, "Expected a numeric value for %s = %v\n",
|
||||||
stat, value)
|
stat, value)
|
||||||
|
|
Loading…
Reference in New Issue