From 33f2d0c18a382d7be0774e622700da36f247726a Mon Sep 17 00:00:00 2001 From: Diptanu Choudhury Date: Sat, 21 May 2016 20:05:51 -0700 Subject: [PATCH] Added a stats api for retreiving node stats --- api/allocations.go | 6 ++--- api/nodes.go | 57 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/api/allocations.go b/api/allocations.go index 765a349fc..2f5415576 100644 --- a/api/allocations.go +++ b/api/allocations.go @@ -46,7 +46,7 @@ func (a *Allocations) Info(allocID string, q *QueryOptions) (*Allocation, *Query } func (a *Allocations) Stats(alloc *Allocation, q *QueryOptions) (map[string]*TaskResourceUsage, error) { - node, _, err := a.client.Nodes().Info(alloc.NodeID, &QueryOptions{}) + node, _, err := a.client.Nodes().Info(alloc.NodeID, q) if err != nil { return nil, err } @@ -71,7 +71,7 @@ func (a *Allocations) Stats(alloc *Allocation, q *QueryOptions) (map[string]*Tas return nil, err } if resp.StatusCode != 200 { - return nil, a.getErrorMsg(resp) + return nil, getErrorMsg(resp) } decoder := json.NewDecoder(resp.Body) var stats map[string]*TaskResourceUsage @@ -81,7 +81,7 @@ func (a *Allocations) Stats(alloc *Allocation, q *QueryOptions) (map[string]*Tas return stats, nil } -func (a *Allocations) getErrorMsg(resp *http.Response) error { +func getErrorMsg(resp *http.Response) error { if errMsg, err := ioutil.ReadAll(resp.Body); err == nil { return fmt.Errorf(string(errMsg)) } else { diff --git a/api/nodes.go b/api/nodes.go index 7d4e6dba0..e8be07564 100644 --- a/api/nodes.go +++ b/api/nodes.go @@ -1,6 +1,10 @@ package api import ( + "encoding/json" + "fmt" + "net/http" + "net/url" "sort" "strconv" ) @@ -71,6 +75,39 @@ func (n *Nodes) ForceEvaluate(nodeID string, q *WriteOptions) (string, *WriteMet return resp.EvalID, wm, nil } +func (n *Nodes) Stats(nodeID string, q *QueryOptions) (*HostStats, error) { + node, _, err := n.client.Nodes().Info(nodeID, q) + if err != nil { + return nil, err + } + if node.HTTPAddr == "" { + return nil, fmt.Errorf("http addr of the node %q is running is not advertised", nodeID) + } + u := &url.URL{ + Scheme: "http", + Host: node.HTTPAddr, + Path: "/v1/client/stats/", + } + req := &http.Request{ + Method: "GET", + URL: u, + } + c := http.Client{} + resp, err := c.Do(req) + if err != nil { + return nil, err + } + if resp.StatusCode != 200 { + return nil, getErrorMsg(resp) + } + decoder := json.NewDecoder(resp.Body) + var stats *HostStats + if err := decoder.Decode(&stats); err != nil { + return nil, err + } + return stats, nil +} + // Node is used to deserialize a node entry. type Node struct { ID string @@ -90,6 +127,26 @@ type Node struct { ModifyIndex uint64 } +// HostStats represents resource usage stats of the host running a Nomad client +type HostStats struct { + Memory *HostMemoryStats + CPU []*HostCPUStats +} + +type HostMemoryStats struct { + Total uint64 + Available uint64 + Used uint64 + Free uint64 +} + +type HostCPUStats struct { + CPU string + User float64 + System float64 + Idle float64 +} + // NodeListStub is a subset of information returned during // node list operations. type NodeListStub struct {