tile38/controller/stats.go

171 lines
4.0 KiB
Go
Raw Normal View History

2016-03-05 02:08:16 +03:00
package controller
import (
"encoding/json"
"fmt"
"runtime"
2016-03-29 01:50:18 +03:00
"sort"
2016-03-05 02:08:16 +03:00
"time"
2016-07-10 05:44:28 +03:00
"github.com/tidwall/btree"
2016-03-29 01:50:18 +03:00
"github.com/tidwall/resp"
2016-07-10 23:23:50 +03:00
"github.com/tidwall/tile38/controller/collection"
2016-03-29 01:50:18 +03:00
"github.com/tidwall/tile38/controller/server"
2016-03-05 02:08:16 +03:00
)
2016-03-29 02:11:29 +03:00
func (c *Controller) cmdStats(msg *server.Message) (res string, err error) {
2016-03-05 02:08:16 +03:00
start := time.Now()
2016-03-29 02:11:29 +03:00
vs := msg.Values[1:]
2016-03-05 02:08:16 +03:00
var ms = []map[string]interface{}{}
2016-03-29 02:11:29 +03:00
if len(vs) == 0 {
2016-03-05 02:08:16 +03:00
return "", errInvalidNumberOfArguments
}
2016-03-29 02:11:29 +03:00
var vals []resp.Value
var key string
var ok bool
for {
vs, key, ok = tokenval(vs)
if !ok {
break
}
2016-03-05 02:08:16 +03:00
col := c.getCol(key)
if col != nil {
m := make(map[string]interface{})
points := col.PointCount()
m["num_points"] = points
m["in_memory_size"] = col.TotalWeight()
2016-07-10 23:23:50 +03:00
m["num_objects"] = col.Count(collection.TypeAll)
2016-03-29 02:11:29 +03:00
switch msg.OutputType {
case server.JSON:
ms = append(ms, m)
case server.RESP:
vals = append(vals, resp.ArrayValue(respValuesSimpleMap(m)))
}
2016-03-05 02:08:16 +03:00
} else {
2016-03-29 02:11:29 +03:00
switch msg.OutputType {
case server.JSON:
ms = append(ms, nil)
case server.RESP:
vals = append(vals, resp.NullValue())
}
2016-03-05 02:08:16 +03:00
}
}
2016-03-29 02:11:29 +03:00
switch msg.OutputType {
case server.JSON:
2016-03-29 03:38:21 +03:00
2016-03-29 02:11:29 +03:00
data, err := json.Marshal(ms)
if err != nil {
return "", err
}
res = `{"ok":true,"stats":` + string(data) + `,"elapsed":"` + time.Now().Sub(start).String() + "\"}"
case server.RESP:
data, err := resp.ArrayValue(vals).MarshalRESP()
if err != nil {
return "", err
}
res = string(data)
2016-03-05 02:08:16 +03:00
}
2016-03-29 02:11:29 +03:00
return res, nil
2016-03-05 02:08:16 +03:00
}
2016-03-29 01:50:18 +03:00
func (c *Controller) cmdServer(msg *server.Message) (res string, err error) {
2016-03-05 02:08:16 +03:00
start := time.Now()
2016-03-29 01:50:18 +03:00
if len(msg.Values) != 1 {
2016-03-05 02:08:16 +03:00
return "", errInvalidNumberOfArguments
}
m := make(map[string]interface{})
m["id"] = c.config.ServerID
if c.config.FollowHost != "" {
m["following"] = fmt.Sprintf("%s:%d", c.config.FollowHost, c.config.FollowPort)
m["caught_up"] = c.fcup
}
m["aof_size"] = c.aofsz
m["num_collections"] = c.cols.Len()
2016-03-30 19:32:38 +03:00
m["num_hooks"] = len(c.hooks)
2016-03-05 02:08:16 +03:00
sz := 0
c.cols.Ascend(func(item btree.Item) bool {
col := item.(*collectionT).Collection
sz += col.TotalWeight()
return true
})
m["in_memory_size"] = sz
points := 0
objects := 0
c.cols.Ascend(func(item btree.Item) bool {
col := item.(*collectionT).Collection
points += col.PointCount()
2016-07-10 23:23:50 +03:00
objects += col.Count(collection.TypeAll)
2016-03-05 02:08:16 +03:00
return true
})
m["num_points"] = points
m["num_objects"] = objects
var mem runtime.MemStats
runtime.ReadMemStats(&mem)
avgsz := 0
if points != 0 {
avgsz = int(mem.HeapAlloc) / points
}
m["heap_size"] = mem.HeapAlloc
2016-05-24 05:44:25 +03:00
m["max_heap_size"] = c.config.MaxMemory
2016-03-05 02:08:16 +03:00
m["avg_item_size"] = avgsz
m["pointer_size"] = (32 << uintptr(uint64(^uintptr(0))>>63)) / 8
m["read_only"] = c.config.ReadOnly
2016-03-29 01:50:18 +03:00
switch msg.OutputType {
case server.JSON:
data, err := json.Marshal(m)
if err != nil {
return "", err
}
res = `{"ok":true,"stats":` + string(data) + `,"elapsed":"` + time.Now().Sub(start).String() + "\"}"
case server.RESP:
2016-03-29 02:11:29 +03:00
vals := respValuesSimpleMap(m)
2016-03-29 01:50:18 +03:00
data, err := resp.ArrayValue(vals).MarshalRESP()
if err != nil {
return "", err
}
res = string(data)
2016-03-05 02:08:16 +03:00
}
2016-03-29 01:50:18 +03:00
return res, nil
2016-03-05 02:08:16 +03:00
}
2016-03-29 02:11:29 +03:00
func respValuesSimpleMap(m map[string]interface{}) []resp.Value {
var keys []string
2016-04-03 05:16:36 +03:00
for key := range m {
2016-03-29 02:11:29 +03:00
keys = append(keys, key)
}
sort.Strings(keys)
var vals []resp.Value
for _, key := range keys {
val := m[key]
vals = append(vals, resp.StringValue(key))
vals = append(vals, resp.StringValue(fmt.Sprintf("%v", val)))
}
return vals
}
2016-03-05 02:08:16 +03:00
func (c *Controller) statsCollections(line string) (string, error) {
start := time.Now()
var key string
var ms = []map[string]interface{}{}
for len(line) > 0 {
line, key = token(line)
col := c.getCol(key)
if col != nil {
m := make(map[string]interface{})
points := col.PointCount()
m["num_points"] = points
m["in_memory_size"] = col.TotalWeight()
2016-07-10 23:23:50 +03:00
m["num_objects"] = col.Count(collection.TypeAll)
2016-03-05 02:08:16 +03:00
ms = append(ms, m)
} else {
ms = append(ms, nil)
}
}
data, err := json.Marshal(ms)
if err != nil {
return "", err
}
return `{"ok":true,"stats":` + string(data) + `,"elapsed":"` + time.Now().Sub(start).String() + "\"}", nil
}