1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
| | # -*- encoding: binary -*-
# For reporting TCP ListenStats, users of older \Linux kernels need to ensure
# that the the "inet_diag" and "tcp_diag" kernel modules are loaded as they do
# not autoload correctly. The inet_diag facilities of \Raindrops is useful
# for periodic snapshot reporting of listen queue sizes.
#
# Instead of snapshotting, Raindrops::Aggregate::LastDataRecv may be used
# to aggregate statistics from +all+ accepted sockets as they arrive
# based on the +last_data_recv+ field in Raindrops::TCP_Info
module Raindrops::Linux
# The standard proc path for active UNIX domain sockets, feel free to call
# String#replace on this if your /proc is mounted in a non-standard location
# for whatever reason
PROC_NET_UNIX_ARGS = %w(/proc/net/unix)
defined?(::Encoding) and PROC_NET_UNIX_ARGS.push({ :encoding => "binary" })
# Get ListenStats from an array of +paths+
#
# Socket state mapping from integer => symbol, based on socket_state
# enum from include/linux/net.h in the \Linux kernel:
# typedef enum {
# SS_FREE = 0, /* not allocated */
# SS_UNCONNECTED, /* unconnected to any socket */
# SS_CONNECTING, /* in process of connecting */
# SS_CONNECTED, /* connected to socket */
# SS_DISCONNECTING /* in process of disconnecting */
# } socket_state;
# * SS_CONNECTING maps to ListenStats#active
# * SS_CONNECTED maps to ListenStats#queued
#
# This method may be significantly slower than its tcp_listener_stats
# counterpart due to the latter being able to use inet_diag via netlink.
# This parses /proc/net/unix as there is no other (known) way
# to expose Unix domain socket statistics over netlink.
def unix_listener_stats(paths = nil)
rv = Hash.new { |h,k| h[k.freeze] = Raindrops::ListenStats.new(0, 0) }
if nil == paths
paths = [ '[^\n]+' ]
else
paths = paths.map do |path|
path = path.dup
path.force_encoding(Encoding::BINARY) if defined?(Encoding)
rv[path]
Regexp.escape(path)
end
end
paths = /^\w+: \d+ \d+ 00000000 \d+ (\d+)\s+\d+ (#{paths.join('|')})$/n
# no point in pread since we can't stat for size on this file
File.read(*PROC_NET_UNIX_ARGS).scan(paths) do |s|
path = s[-1]
case s[0].to_i
when 2 then rv[path].queued += 1
when 3 then rv[path].active += 1
end
end
rv
end
module_function :unix_listener_stats
end # Raindrops::Linux
|