Skip to content

Commit

Permalink
Better memory stats support
Browse files Browse the repository at this point in the history
  • Loading branch information
Soulou committed Oct 28, 2015
1 parent e5f088e commit 1dd7d52
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 15 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# CHANGELOG

## To be released
## v0.2.0

* Can run in a container
* Stats of net interface of containers
* More memory stats

## v0.1.2

Expand Down
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,23 @@ docker run -v /sys/fs/cgroup:/host/cgroup:ro -e CGROUP_DIR=/host/cgroup
API
---

* Memory consumption (in bytes)
* Memory consumption

`GET /containers/:id/mem`

Return 200 OK
Content-Type: text/plain
Content-Type: application/json

```json
{
"mem_usage": 123,
"mem_limit": 5000,
"max_mem_usage": 500,
"max_swap_mem_usage": 200,
"swap_mem_usage": 145,
"swap_mem_limit": 1000
}
```

* CPU usage (percentage)

Expand Down
3 changes: 3 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import (
"net/url"
"strconv"

"github.com/Scalingo/acadock-monitoring/mem"
"gopkg.in/errgo.v1"
)

type MemoryUsage mem.Usage

type Client struct {
Endpoint string
}
Expand Down
65 changes: 58 additions & 7 deletions mem/mem.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,93 @@ import (
"log"
"os"
"strconv"
"sync"

"github.com/Scalingo/acadock-monitoring/config"
"github.com/Scalingo/acadock-monitoring/docker"
)

const (
LXC_MEM_USAGE_FILE = "memory.usage_in_bytes"
LXC_MEM_USAGE_FILE = "memory.usage_in_bytes"
LXC_SWAP_MEM_USAGE_FILE = "memory.memsw.usage_in_bytes"
LXC_MEM_LIMIT_FILE = "memory.limit_in_bytes"
LXC_SWAP_MEM_LIMIT_FILE = "memory.memsw.limit_in_bytes"
LXC_MAX_MEM_FILE = "memory.max_usage_in_bytes"
LXC_MAX_SWAP_MEM_FILE = "memory.memsw.max_usage_in_bytes"
)

func GetUsage(id string) (int64, error) {
type Usage 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"`
}

func GetUsage(id string) (Usage, error) {
usage := Usage{}
id, err := docker.ExpandId(id)
if err != nil {
log.Println("Error when expanding id:", err)
return 0, err
return usage, err
}

errors := make(chan error)
wg := &sync.WaitGroup{}
wg.Add(6)
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_SWAP_MEM_LIMIT_FILE, &usage.SwapMemoryLimit, errors, wg)
go readMemoryCgroupInt64Async(id, LXC_SWAP_MEM_USAGE_FILE, &usage.SwapMemoryUsage, errors, wg)

go func() {
wg.Wait()
close(errors)
}()

for err := range errors {
if err != nil {
return usage, err
}
}

path := config.CgroupPath("memory", id) + "/" + LXC_MEM_USAGE_FILE
return usage, nil
}

func readMemoryCgroupInt64Async(id, file string, ret *int64, errors chan error, wg *sync.WaitGroup) {
defer wg.Done()
val, err := readMemoryCgroupInt64(id, file)
if err != nil {
errors <- err
return
}
*ret = val
}

func readMemoryCgroupInt64(id, file string) (int64, error) {
path := config.CgroupPath("memory", id) + "/" + file
f, err := os.Open(path)
if err != nil {
log.Println("Error while opening:", err)
return 0, err
return -1, err
}
defer f.Close()

buffer := make([]byte, 16)
n, err := f.Read(buffer)
if err != nil {
log.Println("Error while reading ", path, ":", err)
return 0, err
return -1, err
}

buffer = buffer[:n-1]
val, err := strconv.ParseInt(string(buffer), 10, 64)
if err != nil {
log.Println("Error while parsing ", string(buffer), " : ", err)
return 0, err
return -1, err
}

return val, nil
Expand Down
17 changes: 12 additions & 5 deletions server/acadock_monitoring.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"strconv"

Expand All @@ -15,15 +16,21 @@ import (
"github.com/codegangsta/martini"
)

func containerMemUsageHandler(params martini.Params) (int, string) {
func containerMemUsageHandler(params martini.Params, res http.ResponseWriter) {
id := params["id"]

containerMemory, err := mem.GetUsage(id)
containerMemoryUsage, err := mem.GetUsage(id)
if err != nil {
return 500, err.Error()
res.WriteHeader(500)
res.Header().Set("Content-Type", "text/plain")
fmt.Fprintf(res, err.Error())
return
}
containerMemoryStr := strconv.FormatInt(containerMemory, 10)
return 200, containerMemoryStr

res.WriteHeader(200)
res.Header().Set("Content-Type", "application/json")

json.NewEncoder(res).Encode(&containerMemoryUsage)
}

func containerCpuUsageHandler(params martini.Params) (int, string) {
Expand Down

0 comments on commit 1dd7d52

Please sign in to comment.