Skip to content
This repository was archived by the owner on Dec 18, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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