Skip to content
This repository has been archived by the owner on Dec 18, 2019. It is now read-only.

Added client/server specific memcached connection counts #9

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ traffic statistics for each key seen. It currently reports on the following met
* **req/sec** - the number of requests per second for the key
* **bw (kbps)** - the estimated netowrk bandwidth consumed by this key in kilobits-per-second

Optional metrics:
When used with the -c or --detailed-calls flag
* **server calls** - the number of times the key has been requested from the local memcached server since mctop started
* **client calls** - the number of times the key has been requested from this server to an external memcached server since mctop started


## Getting it running

the quickest way to get it running is to:
Expand All @@ -42,13 +48,17 @@ the quickest way to get it running is to:
-p, --port=PORT Network port to sniff on (default 11211)
-d, --discard=THRESH Discard keys with request/sec rate below THRESH
-r, --refresh=MS Refresh the stats display every MS milliseconds
-c, --detailed-calls Detailed client/server call stats
-a, --ip-address=1.1.1.1 IP address of memcached instance (used for client/server stats)
-h, --help Show usage info

## User interface commands

The following key commands are available in the console UI:

* `C` - sort by number of calls
* `E` - sort by number of server calls
* `L` - sort by number of client calls
* `S` - sort by object size
* `R` - sort by requests/sec
* `B` - sort by bandwidth
Expand Down
8 changes: 8 additions & 0 deletions bin/mctop
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ until done do
done = true
when /[Cc]/
sort_mode = :calls
when /[Ee]/
if @config[:detailed_calls]
sort_mode = :server_calls
end
when /[Ll]/
if @config[:detailed_calls]
sort_mode = :client_calls
end
when /[Ss]/
sort_mode = :objsize
when /[Rr]/
Expand Down
15 changes: 13 additions & 2 deletions lib/cmdline.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'optparse'
require 'pcap'
require 'socket'

class CmdLine
def self.parse(args)
Expand All @@ -16,15 +17,25 @@ def self.parse(args)
end

@config[:discard_thresh] = 0
opt.on '-d', '--discard=THRESH', Float, 'Discard keys with request/sec rate below THRESH' do |discard_thresh|
opt.on('-d', '--discard=THRESH', Float, 'Discard keys with request/sec rate below THRESH') do |discard_thresh|
@config[:discard_thresh] = discard_thresh
end

@config[:refresh_rate] = 500
opt.on '-r', '--refresh=MS', Float, 'Refresh the stats display every MS milliseconds' do |refresh_rate|
opt.on('-r', '--refresh=MS', Float, 'Refresh the stats display every MS milliseconds') do |refresh_rate|
@config[:refresh_rate] = refresh_rate
end

@config[:detailed_calls] = false
opt.on('-c', '--detailed-calls', 'Detailed client/server call stats') do |detailed_calls|
@config[:detailed_calls] = true
end

@config[:ip_address] = IPSocket.getaddress(Socket.gethostname)
opt.on('-a', '--ip-address=1.1.1.1', 'IP address of memcached instance (used for client/server stats)') do |ip_address|
@config[:ip_address] = ip_address
end

opt.on_tail '-h', '--help', 'Show usage info' do
puts opts
exit
Expand Down
39 changes: 31 additions & 8 deletions lib/sniffer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@ class MemcacheSniffer
attr_accessor :metrics, :semaphore

def initialize(config)
@source = config[:nic]
@port = config[:port]
@source = config[:nic]
@port = config[:port]
@detailed_calls = config[:detailed_calls]
@ip = config[:ip_address]


@metrics = {}
@metrics[:calls] = {}
@metrics[:objsize] = {}
@metrics[:reqsec] = {}
@metrics[:bw] = {}
@metrics[:stats] = { :recv => 0, :drop => 0 }
@metrics[:calls] = {}
@metrics[:client_calls] = {}
@metrics[:server_calls] = {}
@metrics[:objsize] = {}
@metrics[:reqsec] = {}
@metrics[:bw] = {}
@metrics[:stats] = { :recv => 0, :drop => 0 }

@semaphore = Mutex.new
end
Expand All @@ -40,8 +45,26 @@ def start
else
@metrics[:calls][key] = 1
end

@metrics[:objsize][key] = bytes.to_i

if @detailed_calls
# Break down keys by server requests and client requests
if @ip == packet.src.to_s
if @metrics[:server_calls].has_key?(key)
@metrics[:server_calls][key] += 1
else
@metrics[:server_calls][key] = 1
end
end

if @ip == packet.dst.to_s
if @metrics[:client_calls].has_key?(key)
@metrics[:client_calls][key] += 1
else
@metrics[:client_calls][key] = 1
end
end
end
end
end

Expand Down
54 changes: 43 additions & 11 deletions lib/ui.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,33 @@ def initialize(config)
init_pair(2, COLOR_WHITE, COLOR_RED)
end

@stat_cols = %w[ calls objsize req/sec bw(kbps) ]
@stat_col_width = 10
if @config[:detailed_calls]
@stat_cols = %w[ calls server client objsize req/sec bw(kbps) ]
else
@stat_cols = %w[ calls objsize req/sec bw(kbps) ]
end

@stat_col_width = 10
@key_col_width = 0

@commands = {
'Q' => "quit",
'C' => "sort by calls",
'C' => "sort by calls"
}

if @config[:detailed_calls]
@commands.merge!({
'E' => "sort by server calls",
'L' => "sort by client calls"
})
end

@commands.merge!({
'S' => "sort by size",
'R' => "sort by req/sec",
'B' => "sort by bandwidth",
'T' => "toggle sort order (asc|desc)"
}
})
end

def header
Expand Down Expand Up @@ -124,14 +139,31 @@ def render_stats(sniffer, sort_mode, sort_order = :desc)
else
display_key = k
end

if @config[:detailed_calls]
# Set default values for these if they're not currently set
sniffer.metrics[:server_calls][k] = 0 if sniffer.metrics[:server_calls][k].nil?
sniffer.metrics[:client_calls][k] = 0 if sniffer.metrics[:client_calls][k].nil?

# render each key
line = sprintf "%-#{@key_col_width}s %9.d %9.d %9.2f %9.2f",
display_key,
sniffer.metrics[:calls][k],
sniffer.metrics[:objsize][k],
sniffer.metrics[:reqsec][k],
sniffer.metrics[:bw][k]
# render each key
line = sprintf "%-#{@key_col_width}s %9.d %9.d %9.d %9.d %9.2f %9.2f",
display_key,
sniffer.metrics[:calls][k],
sniffer.metrics[:server_calls][k],
sniffer.metrics[:client_calls][k],
sniffer.metrics[:objsize][k],
sniffer.metrics[:reqsec][k],
sniffer.metrics[:bw][k]
else
# render each key
line = sprintf "%-#{@key_col_width}s %9.d %9.d %9.2f %9.2f",
display_key,
sniffer.metrics[:calls][k],
sniffer.metrics[:objsize][k],
sniffer.metrics[:reqsec][k],
sniffer.metrics[:bw][k]
end

else
# we're not clearing the display between renders so erase past
# keys with blank lines if there's < maxlines of results
Expand Down