[IMP] Error Handling and Tests

Signed-off-by: David Arnold <dar@devco.co>
This commit is contained in:
David Arnold 2016-07-31 01:59:27 -05:00
parent 8e2b6ea996
commit 8ee442042e
2 changed files with 107 additions and 7 deletions

View File

@ -1,3 +1,5 @@
// Package uwsgi implements a telegraf plugin for
// collecting uwsgi stats from the uwsgi stats server.
package uwsgi package uwsgi
import ( import (
@ -15,14 +17,53 @@ import (
var timeout = 5 * time.Second var timeout = 5 * time.Second
// uWSGI Server struct
type Uwsgi struct { type Uwsgi struct {
Servers []string `toml:"server"` Servers []string `toml:"server"`
} }
// Errors is a list of errors accumulated during an interval.
type Errors []error
func (errs Errors) Error() string {
s := ""
for _, err := range errs {
if s == "" {
s = err.Error()
} else {
s = s + ". " + err.Error()
}
}
return s
}
// NestedError wraps an error returned from deeper in the code.
type NestedError struct {
// Err is the error from where the NestedError was constructed.
Err error
// NestedError is the error that was passed back from the called function.
NestedErr error
}
// Error returns a concatenated string of all the nested errors.
func (ne NestedError) Error() string {
return ne.Err.Error() + ": " + ne.NestedErr.Error()
}
// Errorf is a convenience function for constructing a NestedError.
func Errorf(err error, msg string, format ...interface{}) error {
return NestedError{
NestedErr: err,
Err: fmt.Errorf(msg, format...),
}
}
// Description returns the plugin description
func (u *Uwsgi) Description() string { func (u *Uwsgi) Description() string {
return "Read uWSGI metrics." return "Read uWSGI metrics."
} }
// SampleConfig returns the sample configuration
func (u *Uwsgi) SampleConfig() string { func (u *Uwsgi) SampleConfig() string {
return ` return `
## List with urls of uWSGI Stats servers. Url must match pattern: ## List with urls of uWSGI Stats servers. Url must match pattern:
@ -34,17 +75,20 @@ func (u *Uwsgi) SampleConfig() string {
` `
} }
// Gather collect data from uWSGI Server
func (u *Uwsgi) Gather(acc telegraf.Accumulator) error { func (u *Uwsgi) Gather(acc telegraf.Accumulator) error {
var errs Errors
for _, s := range u.Servers { for _, s := range u.Servers {
n, err := url.Parse(s) n, err := url.Parse(s)
if err != nil { if err != nil {
return fmt.Errorf("Could not parse uWSGI Stats Server url '%s': %s", s, err) return fmt.Errorf("Could not parse uWSGI Stats Server url '%s': %s", s, err)
} }
if err := u.gatherServer(acc, n); err != nil {
u.gatherServer(acc, n) errs = append(errs, Errorf(err, "server %s", s))
}
} }
return nil return errs
} }
func (u *Uwsgi) gatherServer(acc telegraf.Accumulator, url *url.URL) error { func (u *Uwsgi) gatherServer(acc telegraf.Accumulator, url *url.URL) error {
@ -59,7 +103,7 @@ func (u *Uwsgi) gatherServer(acc telegraf.Accumulator, url *url.URL) error {
case "http": case "http":
resp, err := http.Get(url.String()) resp, err := http.Get(url.String())
if err != nil { if err != nil {
return fmt.Errorf("Could not connect to uWSGI Stats Server '%s': %s", url.String(), err) return Errorf(err, "Could not connect to uWSGI Stats Server '%s'", url.String())
} }
r = resp.Body r = resp.Body
default: default:
@ -67,7 +111,7 @@ func (u *Uwsgi) gatherServer(acc telegraf.Accumulator, url *url.URL) error {
} }
if err != nil { if err != nil {
return fmt.Errorf("Could not connect to uWSGI Stats Server '%s': %s", url.String(), err) return Errorf(err, "Could not connect to uWSGI Stats Server '%s'", url.String())
} }
defer r.Close() defer r.Close()
@ -75,11 +119,13 @@ func (u *Uwsgi) gatherServer(acc telegraf.Accumulator, url *url.URL) error {
s.Url = url.String() s.Url = url.String()
dec := json.NewDecoder(r) dec := json.NewDecoder(r)
dec.Decode(&s) if err := dec.Decode(&s); err != nil {
return Errorf(err, "Could not decode json payload from server '%s'", url.String())
}
u.gatherStatServer(acc, &s) u.gatherStatServer(acc, &s)
return nil return err
} }
func (u *Uwsgi) gatherStatServer(acc telegraf.Accumulator, s *StatsServer) { func (u *Uwsgi) gatherStatServer(acc telegraf.Accumulator, s *StatsServer) {

View File

@ -123,3 +123,57 @@ func TestBasic(t *testing.T) {
var acc testutil.Accumulator var acc testutil.Accumulator
require.NoError(t, plugin.Gather(&acc)) require.NoError(t, plugin.Gather(&acc))
} }
func TestInvalidJason(t *testing.T) {
js := `
{
"version":"2.0.12",
"listen_queue":0,
"listen_queue_errors":0,
"signal_queue":0,
"load":0,
"pid:28372
"uid":10
}
`
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
_, _ = w.Write([]byte(js))
} else {
w.WriteHeader(http.StatusNotFound)
}
}))
defer fakeServer.Close()
plugin := &uwsgi.Uwsgi{
Servers: []string{fakeServer.URL + "/"},
}
var acc testutil.Accumulator
require.Error(t, plugin.Gather(&acc))
}
func TestHttpError(t *testing.T) {
plugin := &uwsgi.Uwsgi{
Servers: []string{"http://novalidurladress/"},
}
var acc testutil.Accumulator
require.Error(t, plugin.Gather(&acc))
}
func TestTcpError(t *testing.T) {
plugin := &uwsgi.Uwsgi{
Servers: []string{"tcp://novalidtcpadress/"},
}
var acc testutil.Accumulator
require.Error(t, plugin.Gather(&acc))
}
func TestUnixSocketError(t *testing.T) {
plugin := &uwsgi.Uwsgi{
Servers: []string{"unix:///novalidunixsocket"},
}
var acc testutil.Accumulator
require.Error(t, plugin.Gather(&acc))
}