diff --git a/client/client.go b/client/client.go index a34cce6c..8656dc40 100644 --- a/client/client.go +++ b/client/client.go @@ -2,21 +2,23 @@ package client import ( "encoding/json" - "io/ioutil" "net/http" "net/url" - "strconv" "gopkg.in/errgo.v1" ) type MemoryUsage struct { - MemoryUsage int64 `json:"memory_usage"` - SwapMemoryUsage int64 `json:"swap_memory_usage"` - MemoryLimit int64 `json:"memory_limit"` - SwapMemoryLimit int64 `json:"swap_memory_limit"` - MaxMemoryUsage int64 `json:"max_memory_usage"` - MaxSwapMemoryUsage int64 `json:"max_swap_memory_usage"` + MemoryUsage int64 `json:"memory_usage"` + SwapUsage int64 `json:"swap_usage"` + MemoryLimit int64 `json:"memory_limit"` + SwapLimit int64 `json:"swap_limit"` + MaxMemoryUsage int64 `json:"max_memory_usage"` + MaxSwapUsage int64 `json:"max_swap_usage"` +} + +type CpuUsage struct { + UsageInPercents int `json:"usage_in_percents"` } type Client struct { @@ -55,42 +57,30 @@ func (c *Client) Memory(dockerId string) (*MemoryUsage, error) { return mem, nil } -func (c *Client) CpuUsage(dockerId string) (int64, error) { +func (c *Client) CpuUsage(dockerId string) (*CpuUsage, error) { req, err := http.NewRequest("GET", c.Endpoint+"/containers/"+dockerId+"/cpu", nil) if err != nil { - return -1, errgo.Mask(err) - } - - cpu, err := c.getInt(req) - if err != nil { - return -1, errgo.Mask(err) + return nil, errgo.Mask(err) } - return cpu, nil -} - -func (c *Client) do(req *http.Request) (*http.Response, error) { - req.Header.Add("Content-Type", "text/plain") - req.Header.Add("User-Agent", "Acadocker Client v1") - return http.DefaultClient.Do(req) -} - -func (c *Client) getInt(req *http.Request) (int64, error) { res, err := c.do(req) if err != nil { - return -1, errgo.Mask(err) + return nil, errgo.Mask(err) } + defer res.Body.Close() - body, err := ioutil.ReadAll(res.Body) + var cpu *CpuUsage + err = json.NewDecoder(res.Body).Decode(&cpu) if err != nil { - return -1, errgo.Mask(err) + return nil, errgo.Mask(err) } - i, err := strconv.ParseInt(string(body), 10, 64) - if err != nil { - return -1, errgo.Mask(err) - } + return cpu, nil +} - return i, nil +func (c *Client) do(req *http.Request) (*http.Response, error) { + req.Header.Add("Content-Type", "application/json") + req.Header.Add("User-Agent", "Acadocker Client v1") + return http.DefaultClient.Do(req) } diff --git a/cpu/cpu.go b/cpu/cpu.go index ade15880..b4711675 100644 --- a/cpu/cpu.go +++ b/cpu/cpu.go @@ -12,6 +12,7 @@ import ( "sync" "time" + "github.com/Scalingo/acadock-monitoring/client" "github.com/Scalingo/acadock-monitoring/config" "github.com/Scalingo/acadock-monitoring/docker" ) @@ -20,6 +21,8 @@ const ( LXC_CPUACCT_USAGE_FILE = "cpuacct.usage" ) +type Usage client.CpuUsage + var ( currentSystemUsage = make(map[string]int64) previousSystemUsage = make(map[string]int64) @@ -89,19 +92,22 @@ func monitorContainer(id string) { } } -func GetUsage(id string) (int64, error) { +func GetUsage(id string) (*Usage, error) { id, err := docker.ExpandId(id) if err != nil { log.Println("Error when expanding id:", err) - return -1, err + return nil, err } if _, ok := previousCpuUsages[id]; !ok { - return -1, nil + return nil, nil } deltaCpuUsage := float64(cpuUsages[id] - previousCpuUsages[id]) deltaSystemCpuUsage := float64(currentSystemUsage[id] - previousSystemUsage[id]) - return int64(deltaCpuUsage / deltaSystemCpuUsage * 100 * float64(runtime.NumCPU())), nil + percents := int(deltaCpuUsage / deltaSystemCpuUsage * 100 * float64(runtime.NumCPU())) + return &Usage{ + UsageInPercents: percents, + }, nil } func systemUsage() (int64, error) { diff --git a/mem/mem.go b/mem/mem.go index 661ea97a..38558132 100644 --- a/mem/mem.go +++ b/mem/mem.go @@ -20,7 +20,12 @@ const ( LXC_MAX_SWAP_MEM_FILE = "memory.memsw.max_usage_in_bytes" ) -type Usage client.MemoryUsage +type Usage struct { + client.MemoryUsage + SwapMemoryUsage int64 `json:"-"` + SwapMemoryLimit int64 `json:"-"` + MaxSwapMemoryUsage int64 `json:"-"` +} func GetUsage(id string) (Usage, error) { usage := Usage{} @@ -36,7 +41,7 @@ func GetUsage(id string) (Usage, error) { go readMemoryCgroupInt64Async(id, LXC_MAX_MEM_FILE, &usage.MaxMemoryUsage, errors, wg) go readMemoryCgroupInt64Async(id, LXC_MAX_SWAP_MEM_FILE, &usage.MaxSwapMemoryUsage, errors, wg) go readMemoryCgroupInt64Async(id, LXC_MEM_LIMIT_FILE, &usage.MemoryLimit, errors, wg) - go readMemoryCgroupInt64Async(id, LXC_MEM_USAGE_FILE, &usage.MemoryUsage, errors, wg) + go readMemoryCgroupInt64Async(id, LXC_MEM_USAGE_FILE, &usage.MemoryUsage.MemoryUsage, errors, wg) go readMemoryCgroupInt64Async(id, LXC_SWAP_MEM_LIMIT_FILE, &usage.SwapMemoryLimit, errors, wg) go readMemoryCgroupInt64Async(id, LXC_SWAP_MEM_USAGE_FILE, &usage.SwapMemoryUsage, errors, wg) @@ -51,6 +56,9 @@ func GetUsage(id string) (Usage, error) { } } + usage.SwapUsage = usage.SwapMemoryUsage - usage.MemoryUsage.MemoryUsage + usage.SwapLimit = usage.SwapMemoryLimit - usage.MemoryLimit + usage.MaxSwapUsage = usage.MaxSwapMemoryUsage - usage.MaxMemoryUsage return usage, nil } diff --git a/server/acadock_monitoring.go b/server/acadock_monitoring.go index 11ca89f2..e3f5d757 100644 --- a/server/acadock_monitoring.go +++ b/server/acadock_monitoring.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" "log" - "strconv" "net/http" "net/http/pprof" @@ -33,15 +32,18 @@ func containerMemUsageHandler(params martini.Params, res http.ResponseWriter) { json.NewEncoder(res).Encode(&containerMemoryUsage) } -func containerCpuUsageHandler(params martini.Params) (int, string) { +func containerCpuUsageHandler(res http.ResponseWriter, req *http.Request, params martini.Params) { id := params["id"] - containerCpu, err := cpu.GetUsage(id) + containerCpuUsage, err := cpu.GetUsage(id) if err != nil { - return 200, err.Error() + res.WriteHeader(500) + res.Header().Set("Content-Type", "text/plain") + fmt.Fprintf(res, err.Error()) + return } - containerCpuStr := strconv.FormatInt(containerCpu, 10) - return 200, containerCpuStr + res.WriteHeader(200) + json.NewEncoder(res).Encode(&containerCpuUsage) } func containerNetUsageHandler(params martini.Params, res http.ResponseWriter) { @@ -49,6 +51,8 @@ func containerNetUsageHandler(params martini.Params, res http.ResponseWriter) { containerNet, err := net.GetUsage(id) if err != nil { + res.WriteHeader(500) + res.Header().Set("Content-Type", "text/plain") res.Write([]byte(err.Error())) return }