diff --git a/plugins/inputs/all/all.go b/plugins/inputs/all/all.go index 4f7d45f60..39508bed6 100644 --- a/plugins/inputs/all/all.go +++ b/plugins/inputs/all/all.go @@ -55,6 +55,7 @@ import ( _ "github.com/influxdata/telegraf/plugins/inputs/trig" _ "github.com/influxdata/telegraf/plugins/inputs/twemproxy" _ "github.com/influxdata/telegraf/plugins/inputs/udp_listener" + _ "github.com/influxdata/telegraf/plugins/inputs/uwsgi" _ "github.com/influxdata/telegraf/plugins/inputs/win_perf_counters" _ "github.com/influxdata/telegraf/plugins/inputs/zfs" _ "github.com/influxdata/telegraf/plugins/inputs/zookeeper" diff --git a/plugins/inputs/uwsgi/stat_types.go b/plugins/inputs/uwsgi/stat_types.go new file mode 100644 index 000000000..2493ff577 --- /dev/null +++ b/plugins/inputs/uwsgi/stat_types.go @@ -0,0 +1,25 @@ +package uwsgi + +type StatsServer struct { + Url string + Workers []*Worker `json:"workers"` +} + +type Worker struct { + Id int `json:"id"` // Tag + Pid int `json:"pid"` // Tag + Accepting int `json:"accepting"` + Requests int `json:"requests"` + DeltaRequests int `json:"delta_requests"` + HarakiriCount int `json:"harakiri_count"` + Signals int `json:"signals"` + SignalQueue int `json:"signal_queue"` + Status string `json:"status"` + RSS int `json:"rss"` + VSZ int `json:"vsz"` + RunningTime int `json:"running_time"` + LastSpawn int `json:"last_spawn"` + RespawnCount int `json:"respawn_count"` + TX int `json:"tx"` + AvgRT int `json:"avg_rt"` +} diff --git a/plugins/inputs/uwsgi/uwsgi.go b/plugins/inputs/uwsgi/uwsgi.go new file mode 100644 index 000000000..7a5bdc0df --- /dev/null +++ b/plugins/inputs/uwsgi/uwsgi.go @@ -0,0 +1,102 @@ +package uwsgi + +import ( + "encoding/json" + "github.com/influxdata/telegraf" + "github.com/influxdata/telegraf/plugins/inputs" + "net/http" + "strconv" + "time" +) + +var tr = &http.Transport{ + ResponseHeaderTimeout: time.Duration(3 * time.Second), +} + +var client = &http.Client{ + Transport: tr, + Timeout: time.Duration(4 * time.Second), +} + +type Uwsgi struct { + URLs []string `toml:"urls"` +} + +func (u *Uwsgi) Description() string { + return "Read uWSGI metrics." +} + +func (u *Uwsgi) SampleConfig() string { + return ` + ### List with urls of uWSGI Stats servers + urls = [] +` +} + +func (u *Uwsgi) Gather(acc telegraf.Accumulator) error { + for _, url := range u.URLs { + err := u.gatherURL(acc, url) + if err != nil { + return err + } + + } + return nil +} + +func (u *Uwsgi) gatherURL(acc telegraf.Accumulator, url string) error { + resp, err := client.Get(url) + + if err != nil { + return err + } + defer resp.Body.Close() + + var s StatsServer + s.Url = url + + dec := json.NewDecoder(resp.Body) + dec.Decode(&s) + + if err != nil { + return err + } + + u.gatherWorkers(acc, &s) + + return nil +} + +func (u *Uwsgi) gatherWorkers(acc telegraf.Accumulator, s *StatsServer) error { + for _, w := range s.Workers { + fields := map[string]interface{}{ + "requests": w.Requests, + "accepting": w.Accepting, + "delta_request": w.DeltaRequests, + "harakiri_count": w.HarakiriCount, + "signals": w.Signals, + "signal_queue": w.SignalQueue, + "status": w.Status, + "rss": w.RSS, + "vsz": w.VSZ, + "running_time": w.RunningTime, + "last_spawn": w.LastSpawn, + "respawn_count": w.RespawnCount, + "tx": w.TX, + "avg_rt": w.AvgRT, + } + tags := map[string]string{ + "id": strconv.Itoa(w.Id), + "url": s.Url, + "pid": strconv.Itoa(w.Pid), + } + + acc.AddFields("uwsgi_workers", fields, tags) + } + + return nil +} + +func init() { + inputs.Add("uwsgi", func() telegraf.Input { return &Uwsgi{} }) +} diff --git a/plugins/inputs/uwsgi/uwsgi_test.go b/plugins/inputs/uwsgi/uwsgi_test.go new file mode 100644 index 000000000..7ee8013d5 --- /dev/null +++ b/plugins/inputs/uwsgi/uwsgi_test.go @@ -0,0 +1,125 @@ +package uwsgi_test + +import ( + "github.com/influxdata/telegraf/plugins/inputs/uwsgi" + "github.com/influxdata/telegraf/testutil" + "github.com/stretchr/testify/require" + "net/http" + "net/http/httptest" + "testing" +) + +func TestBasic(t *testing.T) { + js := ` +{ + "version":"2.0.12", + "listen_queue":0, + "listen_queue_errors":0, + "signal_queue":0, + "load":0, + "pid":28372, + "uid":1000, + "gid":1000, + "cwd":"/opt/uwsgi", + "locks":[ + { + "user 0":0 + }, + { + "signal":0 + }, + { + "filemon":0 + }, + { + "timer":0 + }, + { + "rbtimer":0 + }, + { + "cron":0 + }, + { + "rpc":0 + }, + { + "snmp":0 + } + ], + "sockets":[ + { + "name":"127.0.0.1:47430", + "proto":"uwsgi", + "queue":0, + "max_queue":100, + "shared":0, + "can_offload":0 + } + ], + "workers":[ + { + "id":1, + "pid":28375, + "accepting":1, + "requests":0, + "delta_requests":0, + "exceptions":0, + "harakiri_count":0, + "signals":0, + "signal_queue":0, + "status":"idle", + "rss":0, + "vsz":0, + "running_time":0, + "last_spawn":1459942782, + "respawn_count":1, + "tx":0, + "avg_rt":0, + "apps":[ + { + "id":0, + "modifier1":0, + "mountpoint":"", + "startup_time":0, + "requests":0, + "exceptions":0, + "chdir":"" + } + ], + "cores":[ + { + "id":0, + "requests":0, + "static_requests":0, + "routed_requests":0, + "offloaded_requests":0, + "write_errors":0, + "read_errors":0, + "in_request":0, + "vars":[ + + ] + } + ] + } + ] +} +` + + 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{ + URLs: []string{fakeServer.URL + "/"}, + } + var acc testutil.Accumulator + require.NoError(t, plugin.Gather(&acc)) +}