Class: Daikon::Monitor

Inherits:
Object
  • Object
show all
Defined in:
lib/daikon/monitor.rb

Constant Summary collapse

NO_ARG_COMMANDS =
["BGREWRITEAOF", "BGSAVE", "CONFIG RESETSTAT", "DBSIZE", "DEBUG SEGFAULT", "DISCARD", "EXEC", "FLUSHALL", "FLUSHDB", "INFO", "LASTSAVE", "MONITOR", "MULTI", "PING", "QUIT", "RANDOMKEY", "SAVE", "SHUTDOWN", "SYNC", "UNWATCH"]
READ_COMMANDS =
["EXISTS", "GET", "GETBIT", "GETRANGE", "HEXISTS", "HGET", "HGETALL", "HKEYS", "HLEN", "HMGET", "HVALS", "KEYS", "LINDEX", "LLEN", "LRANGE", "MGET", "SCARD", "SDIFF", "SINTER", "SISMEMBER", "SMEMBERS", "SORT", "SRANDMEMBER", "STRLEN", "SUNION", "TTL", "TYPE", "ZCARD", "ZCOUNT", "ZRANGE", "ZRANGEBYSCORE", "ZRANK", "ZREVRANGE", "ZREVRANGEBYSCORE", "ZREVRANK", "ZSCORE"].to_set
WRITE_COMMANDS =
["APPEND", "BLPOP", "BRPOP", "BRPOPLPUSH", "DECR", "DECRBY", "DEL", "GETSET", "EXPIRE", "EXPIREAT", "HDEL", "HINCRBY", "HMSET", "HSET", "HSETNX", "INCR", "INCRBY", "LINSERT", "LPOP", "LPUSH", "LPUSHX", "LREM", "LSET", "LTRIM", "MOVE", "MSET", "MSETNX", "PERSIST", "RENAME", "RENAMENX", "RPOP", "RPOPLPUSH", "RPUSH", "RPUSHX", "SADD", "SDIFFSTORE", "SET", "SETBIT", "SETEX", "SETNX", "SETRANGE", "SINTERSTORE", "SMOVE", "SPOP", "SREM", "SUNIONSTORE", "ZADD", "ZINCRBY", "ZINTERSTORE", "ZREM", "ZREMRANGEBYRANK", "ZREMRANGEBYSCORE", "ZUNIONSTORE"].to_set
OTHER_COMMANDS =
["AUTH", "BGREWRITEAOF", "BGSAVE", "CONFIG GET", "CONFIG SET", "CONFIG RESETSTAT", "DBSIZE", "DEBUG OBJECT", "DEBUG SEGFAULT", "DISCARD", "ECHO", "EXEC", "FLUSHALL", "FLUSHDB", "INFO", "LASTSAVE", "MONITOR", "MULTI", "PING", "PSUBSCRIBE", "PUBLISH", "PUNSUBSCRIBE", "QUIT", "RANDOMKEY", "SAVE", "SELECT", "SHUTDOWN", "SUBSCRIBE", "SYNC", "UNSUBSCRIBE", "UNWATCH", "WATCH"].to_set
ALL_COMMANDS =
READ_COMMANDS + WRITE_COMMANDS + OTHER_COMMANDS
NEW_FORMAT =
/^\+?\d+\.\d+ (?:\(db \d+\) )?"(.*)"$/i
OLD_SINGLE_FORMAT =
/^(#{NO_ARG_COMMANDS.join('|')})$/i
OLD_MORE_FORMAT =
/^[A-Z]+ .*$/i

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(redis = nil, logger = nil) ⇒ Monitor

Returns a new instance of Monitor.



15
16
17
18
19
20
# File 'lib/daikon/monitor.rb', line 15

def initialize(redis = nil, logger = nil)
  @data   = data_hash
  @redis  = redis
  @logger = logger
  @mutex  = Mutex.new
end

Instance Attribute Details

#dataObject

Returns the value of attribute data.



3
4
5
# File 'lib/daikon/monitor.rb', line 3

def data
  @data
end

Instance Method Details

#data_hashObject



22
23
24
25
26
27
# File 'lib/daikon/monitor.rb', line 22

def data_hash
  {"commands"   => Hash.new(0),
   "keys"       => Hash.new(0),
   "namespaces" => Hash.new(0),
   "totals"     => Hash.new(0)}
end

#incr_command(command) ⇒ Object



92
93
94
# File 'lib/daikon/monitor.rb', line 92

def incr_command(command)
  data["commands"][command] += 1
end

#incr_global_namespaceObject



88
89
90
# File 'lib/daikon/monitor.rb', line 88

def incr_global_namespace
  data["namespaces"]["global"] += 1
end

#incr_key(key) ⇒ Object



96
97
98
# File 'lib/daikon/monitor.rb', line 96

def incr_key(key)
  data["keys"][key] += 1
end

#incr_namespace(key) ⇒ Object



80
81
82
83
84
85
86
# File 'lib/daikon/monitor.rb', line 80

def incr_namespace(key)
  if marker = key =~ /:|-/
    data["namespaces"][key[0...marker]] += 1
  else
    incr_global_namespace
  end
end

#incr_total(command) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/daikon/monitor.rb', line 100

def incr_total(command)
  data["totals"]["all"] += 1

  if READ_COMMANDS.member?(command)
    data["totals"]["read"] += 1
  elsif WRITE_COMMANDS.member?(command)
    data["totals"]["write"] += 1
  elsif OTHER_COMMANDS.member?(command)
    data["totals"]["other"] += 1
  end
end

#lock(&block) ⇒ Object



37
38
39
# File 'lib/daikon/monitor.rb', line 37

def lock(&block)
  @mutex.synchronize(&block)
end

#parse(line) ⇒ Object



51
52
53
54
55
56
57
# File 'lib/daikon/monitor.rb', line 51

def parse(line)
  if line =~ NEW_FORMAT
    push($1.split('" "'))
  elsif line =~ OLD_SINGLE_FORMAT || line =~ OLD_MORE_FORMAT
    push(line.split)
  end
end

#push(split_command) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/daikon/monitor.rb', line 59

def push(split_command)
  command, key, *rest = split_command
  command.upcase!

  return unless ALL_COMMANDS.member?(command)

  lock do
    incr_command(command)
    incr_total(command)
    if key
      key.gsub!(".", "{PERIOD}") if key.include?('.')
      key.gsub!("$", "{DOLLAR}") if key.include?('$')

      incr_key(key)
      incr_namespace(key)
    else
      incr_global_namespace
    end
  end
end

#rotateObject



41
42
43
44
45
46
47
48
49
# File 'lib/daikon/monitor.rb', line 41

def rotate
  this_data = nil
  lock do
    this_data = self.data.dup
    self.data.replace(data_hash)
  end
  this_data["keys"] = Hash[*this_data["keys"].sort { |a, b| a.last <=> b.last }.reverse[0..99].flatten]
  this_data
end

#startObject



29
30
31
32
33
34
35
# File 'lib/daikon/monitor.rb', line 29

def start
  Thread.new do
    @redis.monitor do |line|
      parse(line)
    end
  end
end