1
0
mirror of https://github.com/mxpv/podsync.git synced 2024-05-11 05:55:04 +00:00

Track top metrics

This commit is contained in:
Maksym Pavlenko
2017-11-04 21:22:25 -07:00
parent cb00281213
commit 2e45ae3437
2 changed files with 84 additions and 8 deletions

@ -12,24 +12,63 @@ type RedisStats struct {
}
func (r RedisStats) Inc(metric, hashID string) (int64, error) {
key := r.makeKey(hashID)
return r.client.HIncrBy(key, metric, 1).Result()
now := time.Now().UTC()
key := r.makeKey(now, hashID)
top := r.makeTop(now, metric)
var cmd *redis.IntCmd
_, err := r.client.TxPipelined(func(p redis.Pipeliner) error {
cmd = p.HIncrBy(key, metric, 1)
p.ZIncrBy(top, 1, hashID)
return nil
})
if err != nil {
return 0, err
}
return cmd.Result()
}
func (r RedisStats) Get(metric, hashID string) (int64, error) {
key := r.makeKey(hashID)
now := time.Now().UTC()
key := r.makeKey(now, hashID)
return r.client.HGet(key, metric).Int64()
}
func (r RedisStats) Top(metric string) (map[string]int64, error) {
now := time.Now().UTC()
top := r.makeTop(now, metric)
zrange, err := r.client.ZRevRangeWithScores(top, 0, 10).Result()
if err != nil {
return nil, err
}
ret := make(map[string]int64)
for _, x := range zrange {
key := x.Member.(string)
val := int64(x.Score)
ret[key] = val
}
return ret, nil
}
func (r RedisStats) makeKey(now time.Time, hashID string) string {
return fmt.Sprintf("stats/%d/%d/%s", now.Year(), now.Month(), hashID)
}
func (r RedisStats) makeTop(now time.Time, metric string) string {
return fmt.Sprintf("stats/top/%d/%d/%s", now.Year(), now.Month(), metric)
}
func (r RedisStats) Close() error {
return r.client.Close()
}
func (r RedisStats) makeKey(hashID string) string {
now := time.Now().UTC()
return fmt.Sprintf("stats/%d/%d/%s", now.Year(), now.Month(), hashID)
}
func NewRedisStats(redisUrl string) (*RedisStats, error) {
opts, err := redis.ParseURL(redisUrl)
if err != nil {

@ -27,6 +27,43 @@ func TestRedisStats_IncAndGet(t *testing.T) {
require.Equal(t, int64(2), v)
}
func TestRedisStats_Top(t *testing.T) {
t.Skip("run redis tests manually")
s := createRedisClient(t)
// 3
s.Inc(metric, "123")
s.Inc(metric, "123")
s.Inc(metric, "123")
// 2
s.Inc(metric, "321")
s.Inc(metric, "321")
// 1
s.Inc(metric, "213")
top, err := s.Top(metric)
require.NoError(t, err)
require.Len(t, top, 3)
// 3
h3, ok := top["123"]
require.True(t, ok)
require.Equal(t, int64(3), h3)
// 2
h2, ok := top["321"]
require.True(t, ok)
require.Equal(t, int64(2), h2)
// 1
h1, ok := top["213"]
require.True(t, ok)
require.Equal(t, int64(1), h1)
}
func createRedisClient(t *testing.T) *RedisStats {
client, err := NewRedisStats("redis://localhost")
require.NoError(t, err)