diff options
Diffstat (limited to 'weed/stats')
| -rw-r--r-- | weed/stats/disk.go | 14 | ||||
| -rw-r--r-- | weed/stats/disk_notsupported.go | 7 | ||||
| -rw-r--r-- | weed/stats/disk_supported.go | 19 | ||||
| -rw-r--r-- | weed/stats/duration_counter.go | 94 | ||||
| -rw-r--r-- | weed/stats/duration_counter_test.go | 19 | ||||
| -rw-r--r-- | weed/stats/memory.go | 28 | ||||
| -rw-r--r-- | weed/stats/memory_notsupported.go | 7 | ||||
| -rw-r--r-- | weed/stats/memory_supported.go | 18 | ||||
| -rw-r--r-- | weed/stats/stats.go | 113 |
9 files changed, 319 insertions, 0 deletions
diff --git a/weed/stats/disk.go b/weed/stats/disk.go new file mode 100644 index 000000000..46d8c465e --- /dev/null +++ b/weed/stats/disk.go @@ -0,0 +1,14 @@ +package stats + +type DiskStatus struct { + Dir string + All uint64 + Used uint64 + Free uint64 +} + +func NewDiskStatus(path string) (disk *DiskStatus) { + disk = &DiskStatus{Dir: path} + disk.fillInStatus() + return +} diff --git a/weed/stats/disk_notsupported.go b/weed/stats/disk_notsupported.go new file mode 100644 index 000000000..e380d27ea --- /dev/null +++ b/weed/stats/disk_notsupported.go @@ -0,0 +1,7 @@ +// +build windows openbsd netbsd plan9 solaris + +package stats + +func (disk *DiskStatus) fillInStatus() { + return +} diff --git a/weed/stats/disk_supported.go b/weed/stats/disk_supported.go new file mode 100644 index 000000000..d68f0a32e --- /dev/null +++ b/weed/stats/disk_supported.go @@ -0,0 +1,19 @@ +// +build !windows,!openbsd,!netbsd,!plan9,!solaris + +package stats + +import ( + "syscall" +) + +func (disk *DiskStatus) fillInStatus() { + fs := syscall.Statfs_t{} + err := syscall.Statfs(disk.Dir, &fs) + if err != nil { + return + } + disk.All = fs.Blocks * uint64(fs.Bsize) + disk.Free = fs.Bfree * uint64(fs.Bsize) + disk.Used = disk.All - disk.Free + return +} diff --git a/weed/stats/duration_counter.go b/weed/stats/duration_counter.go new file mode 100644 index 000000000..69c8be61d --- /dev/null +++ b/weed/stats/duration_counter.go @@ -0,0 +1,94 @@ +package stats + +import ( + "time" +) + +type TimedValue struct { + t time.Time + val int64 +} + +func NewTimedValue(t time.Time, val int64) *TimedValue { + return &TimedValue{t: t, val: val} +} + +type RoundRobinCounter struct { + LastIndex int + Values []int64 + Counts []int64 +} + +func NewRoundRobinCounter(slots int) *RoundRobinCounter { + return &RoundRobinCounter{LastIndex: -1, Values: make([]int64, slots), Counts: make([]int64, slots)} +} +func (rrc *RoundRobinCounter) Add(index int, val int64) { + if index >= len(rrc.Values) { + return + } + for rrc.LastIndex != index { + rrc.LastIndex = (rrc.LastIndex + 1) % len(rrc.Values) + rrc.Values[rrc.LastIndex] = 0 + rrc.Counts[rrc.LastIndex] = 0 + } + rrc.Values[index] += val + rrc.Counts[index]++ +} +func (rrc *RoundRobinCounter) Max() (max int64) { + for _, val := range rrc.Values { + if max < val { + max = val + } + } + return +} +func (rrc *RoundRobinCounter) Count() (cnt int64) { + for _, c := range rrc.Counts { + cnt += c + } + return +} +func (rrc *RoundRobinCounter) Sum() (sum int64) { + for _, val := range rrc.Values { + sum += val + } + return +} + +func (rrc *RoundRobinCounter) ToList() (ret []int64) { + index := rrc.LastIndex + step := len(rrc.Values) + for step > 0 { + step-- + index++ + if index >= len(rrc.Values) { + index = 0 + } + ret = append(ret, rrc.Values[index]) + } + return +} + +type DurationCounter struct { + MinuteCounter *RoundRobinCounter + HourCounter *RoundRobinCounter + DayCounter *RoundRobinCounter + WeekCounter *RoundRobinCounter +} + +func NewDurationCounter() *DurationCounter { + return &DurationCounter{ + MinuteCounter: NewRoundRobinCounter(60), + HourCounter: NewRoundRobinCounter(60), + DayCounter: NewRoundRobinCounter(24), + WeekCounter: NewRoundRobinCounter(7), + } +} + +// Add is for cumulative counts +func (sc *DurationCounter) Add(tv *TimedValue) { + sc.MinuteCounter.Add(tv.t.Second(), tv.val) + sc.HourCounter.Add(tv.t.Minute(), tv.val) + sc.DayCounter.Add(tv.t.Hour(), tv.val) + sc.WeekCounter.Add(int(tv.t.Weekday()), tv.val) +} diff --git a/weed/stats/duration_counter_test.go b/weed/stats/duration_counter_test.go new file mode 100644 index 000000000..aa9d61c87 --- /dev/null +++ b/weed/stats/duration_counter_test.go @@ -0,0 +1,19 @@ +package stats + +import "testing" + +func TestRobinCounter(t *testing.T) { + rrc := NewRoundRobinCounter(60) + rrc.Add(0, 1) + rrc.Add(50, 2) + if rrc.Count() != 2 { + t.Fatal() + } + if rrc.Sum() != 3 { + t.Fatal() + } + /* + index out of range + */ + rrc.Add(61, 1) +} diff --git a/weed/stats/memory.go b/weed/stats/memory.go new file mode 100644 index 000000000..0700d92de --- /dev/null +++ b/weed/stats/memory.go @@ -0,0 +1,28 @@ +package stats + +import ( + "runtime" +) + +type MemStatus struct { + Goroutines int + All uint64 + Used uint64 + Free uint64 + Self uint64 + Heap uint64 + Stack uint64 +} + +func MemStat() MemStatus { + mem := MemStatus{} + mem.Goroutines = runtime.NumGoroutine() + memStat := new(runtime.MemStats) + runtime.ReadMemStats(memStat) + mem.Self = memStat.Alloc + mem.Heap = memStat.HeapAlloc + mem.Stack = memStat.StackInuse + + mem.fillInStatus() + return mem +} diff --git a/weed/stats/memory_notsupported.go b/weed/stats/memory_notsupported.go new file mode 100644 index 000000000..ba8229364 --- /dev/null +++ b/weed/stats/memory_notsupported.go @@ -0,0 +1,7 @@ +// +build !linux + +package stats + +func (mem *MemStatus) fillInStatus() { + return +} diff --git a/weed/stats/memory_supported.go b/weed/stats/memory_supported.go new file mode 100644 index 000000000..fd0c36d72 --- /dev/null +++ b/weed/stats/memory_supported.go @@ -0,0 +1,18 @@ +// +build linux + +package stats + +import ( + "syscall" +) + +func (mem *MemStatus) fillInStatus() { + //system memory usage + sysInfo := new(syscall.Sysinfo_t) + err := syscall.Sysinfo(sysInfo) + if err == nil { + mem.All = uint64(sysInfo.Totalram) //* uint64(syscall.Getpagesize()) + mem.Free = uint64(sysInfo.Freeram) //* uint64(syscall.Getpagesize()) + mem.Used = mem.All - mem.Free + } +} diff --git a/weed/stats/stats.go b/weed/stats/stats.go new file mode 100644 index 000000000..09826152f --- /dev/null +++ b/weed/stats/stats.go @@ -0,0 +1,113 @@ +package stats + +import ( + "time" +) + +type ServerStats struct { + Requests *DurationCounter + Connections *DurationCounter + AssignRequests *DurationCounter + ReadRequests *DurationCounter + WriteRequests *DurationCounter + DeleteRequests *DurationCounter + BytesIn *DurationCounter + BytesOut *DurationCounter +} + +type Channels struct { + Connections chan *TimedValue + Requests chan *TimedValue + AssignRequests chan *TimedValue + ReadRequests chan *TimedValue + WriteRequests chan *TimedValue + DeleteRequests chan *TimedValue + BytesIn chan *TimedValue + BytesOut chan *TimedValue +} + +var ( + Chan *Channels +) + +func init() { + Chan = &Channels{ + Connections: make(chan *TimedValue, 100), + Requests: make(chan *TimedValue, 100), + AssignRequests: make(chan *TimedValue, 100), + ReadRequests: make(chan *TimedValue, 100), + WriteRequests: make(chan *TimedValue, 100), + DeleteRequests: make(chan *TimedValue, 100), + BytesIn: make(chan *TimedValue, 100), + BytesOut: make(chan *TimedValue, 100), + } +} + +func NewServerStats() *ServerStats { + return &ServerStats{ + Requests: NewDurationCounter(), + Connections: NewDurationCounter(), + AssignRequests: NewDurationCounter(), + ReadRequests: NewDurationCounter(), + WriteRequests: NewDurationCounter(), + DeleteRequests: NewDurationCounter(), + BytesIn: NewDurationCounter(), + BytesOut: NewDurationCounter(), + } +} + +func ConnectionOpen() { + Chan.Connections <- NewTimedValue(time.Now(), 1) +} +func ConnectionClose() { + Chan.Connections <- NewTimedValue(time.Now(), -1) +} +func RequestOpen() { + Chan.Requests <- NewTimedValue(time.Now(), 1) +} +func RequestClose() { + Chan.Requests <- NewTimedValue(time.Now(), -1) +} +func AssignRequest() { + Chan.AssignRequests <- NewTimedValue(time.Now(), 1) +} +func ReadRequest() { + Chan.ReadRequests <- NewTimedValue(time.Now(), 1) +} +func WriteRequest() { + Chan.WriteRequests <- NewTimedValue(time.Now(), 1) +} +func DeleteRequest() { + Chan.DeleteRequests <- NewTimedValue(time.Now(), 1) +} +func BytesIn(val int64) { + Chan.BytesIn <- NewTimedValue(time.Now(), val) +} +func BytesOut(val int64) { + Chan.BytesOut <- NewTimedValue(time.Now(), val) +} + +func (ss *ServerStats) Start() { + for { + select { + case tv := <-Chan.Connections: + ss.Connections.Add(tv) + case tv := <-Chan.Requests: + ss.Requests.Add(tv) + case tv := <-Chan.AssignRequests: + ss.AssignRequests.Add(tv) + case tv := <-Chan.ReadRequests: + ss.ReadRequests.Add(tv) + case tv := <-Chan.WriteRequests: + ss.WriteRequests.Add(tv) + case tv := <-Chan.ReadRequests: + ss.ReadRequests.Add(tv) + case tv := <-Chan.DeleteRequests: + ss.DeleteRequests.Add(tv) + case tv := <-Chan.BytesIn: + ss.BytesIn.Add(tv) + case tv := <-Chan.BytesOut: + ss.BytesOut.Add(tv) + } + } +} |
