From 71ed3bcca52edfed31d19b78bb87f3ffa9d0d4e4 Mon Sep 17 00:00:00 2001 From: Hamcha Date: Wed, 10 Feb 2016 14:31:53 +0000 Subject: [PATCH] Started stat module --- Makefile | 3 + stats/main.go | 31 ++++++++--- stats/stats.go | 145 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 stats/stats.go diff --git a/Makefile b/Makefile index 03071a5..78e1eab 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,8 @@ all: clessy-broker clessy-mods clessy-stats +deps: + go get github.com/boltdb/bolt/... + install-tg: go install github.com/hamcha/clessy/tg diff --git a/stats/main.go b/stats/main.go index 0e70f11..a6c2610 100644 --- a/stats/main.go +++ b/stats/main.go @@ -3,18 +3,33 @@ package main import ( "flag" + "github.com/boltdb/bolt" "github.com/hamcha/clessy/tg" ) -func process(broker *tg.Broker, update tg.APIMessage) { -} - -func main() { - brokerAddr := flag.String("broker", "localhost:7314", "Broker address:port") - flag.Parse() - - err := tg.CreateBrokerClient(*brokerAddr, process) +func assert(err error) { if err != nil { panic(err) } } + +var db *bolt.DB + +func process(broker *tg.Broker, update tg.APIMessage) { + +} + +func main() { + brokerAddr := flag.String("broker", "localhost:7314", "Broker address:port") + boltdbFile := flag.String("boltdb", "stats.db", "BoltDB database file") + flag.Parse() + + db, err := bolt.Open(*boltdbFile, 0600, nil) + assert(err) + defer db.Close() + + loadStats() + + err = tg.CreateBrokerClient(*brokerAddr, process) + assert(err) +} diff --git a/stats/stats.go b/stats/stats.go new file mode 100644 index 0000000..b03f0a6 --- /dev/null +++ b/stats/stats.go @@ -0,0 +1,145 @@ +package main + +import ( + "encoding/binary" + "log" + "strconv" + "time" + + "github.com/boltdb/bolt" +) + +const ( + MessageTypeText int = 0 + MessageTypeAudio int = 1 + MessageTypePhoto int = 2 + MessageTypeSticker int = 3 + MessageTypeVideo int = 4 + MessageTypeVoice int = 5 + MessageTypeContact int = 6 + MessageTypeLocation int = 7 + MessageTypeMax int = 8 +) + +type Stats struct { + ByUserCount map[string]uint64 + ByUserAvgLen map[string]uint64 + ByWeekday [7]uint64 + ByHour [24]uint64 + ByType [MessageTypeMax]uint64 + TodayDate time.Time + Today uint64 + TotalCount uint64 + TotalAvgLength uint64 + Replies uint64 + Forward uint64 +} + +var stats Stats + +func MakeUint(bval []byte, bucketName string, key string) uint64 { + if bval != nil { + intval, bts := binary.Uvarint(bval) + if bts > 0 { + return intval + } else { + log.Printf("[%s] Value of key \"%s\" is NaN: %v\r\n", bucketName, key, bval) + return 0 + } + } else { + log.Printf("[%s] Key \"%s\" does not exist, set to 0\n", bucketName, key) + return 0 + } +} + +func loadStats() { + // Load today + stats.TodayDate = time.Now() + + err := db.View(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("global")) + if err != nil { + return err + } + + // Load total messages counter + bval := bucket.Get([]byte("count")) + stats.TotalCount = MakeUint(bval, "global", "count") + + // Load total messages counter + bval := bucket.Get([]byte("avg")) + stats.TotalAvgLength = MakeUint(bval, "global", "avg") + + // Load total replies counter + bval = bucket.Get([]byte("replies")) + stats.Replies = MakeUint(bval, "global", "replies") + + // Load total replies counter + bval = bucket.Get([]byte("forward")) + stats.Forward = MakeUint(bval, "global", "forward") + + // Load hour counters + b, err = tx.CreateBucketIfNotExists([]byte("hour")) + if err != nil { + return err + } + + for i := 0; i < 24; i++ { + bval = bucket.Get([]byte(i)) + stats.ByHour[i] = MakeUint(bval, "hour", strconv.Itoa(i)) + } + + // Load weekday counters + b, err = tx.CreateBucketIfNotExists([]byte("weekday")) + if err != nil { + return err + } + + for i := 0; i < 7; i++ { + bval = bucket.Get([]byte(i)) + stats.ByWeekday[i] = MakeUint(bval, "weekday", strconv.Itoa(i)) + } + + // Load today's message counter, if possible + b, err = tx.CreateBucketIfNotExists([]byte("date")) + if err != nil { + return err + } + + todayKey := stats.TodayDate.Format("2006-1-2") + bval = bucket.Get([]byte(todayKey)) + stats.Today = MakeUint(bval, "date", todayKey) + + // Load user counters + stats.ByUserCount = make(map[string]uint64) + b, err = tx.CreateBucketIfNotExists([]byte("users-count")) + if err != nil { + return err + } + b.ForEach(func(user, messages []byte) error { + stats.ByUserCount[string(user)] = MakeUint(messages, "users-count", string(user)) + }) + + stats.ByUserAvgLen = make(map[string]uint64) + b, err = tx.CreateBucketIfNotExists([]byte("users-avg")) + if err != nil { + return err + } + b.ForEach(func(user, messages []byte) error { + stats.ByUserAvgLen[string(user)] = MakeUint(messages, "users-avg", string(user)) + }) + + // Load type counters + b, err = tx.CreateBucketIfNotExists([]byte("types")) + if err != nil { + return err + } + for i := 0; i < MessageTypeMax; i++ { + bval = bucket.Get([]byte(i)) + stats.ByType[i] = MakeUint(bval, "types", strconv.Itoa(i)) + } + + return nil + }) + assert(err) +}