tcptop 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +31 -11
- data/Rakefile +9 -0
- data/lib/tcptop/collectd.rb +10 -0
- data/lib/tcptop/version.rb +1 -1
- data/lib/tcptop.rb +35 -5
- data/test/collectd_test.rb +13 -0
- data/test/test_helper.rb +3 -0
- metadata +80 -60
data/README.md
CHANGED
@@ -1,24 +1,44 @@
|
|
1
1
|
# Tcptop
|
2
2
|
|
3
|
-
|
3
|
+
A TCP connection monitor that builds upon [raindrops](http://raindrops.bogomips.org/). Useful for monitoring a pool of unicorn workers.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
gem 'tcptop'
|
10
|
-
|
11
|
-
And then execute:
|
12
|
-
|
13
|
-
$ bundle
|
14
|
-
|
15
|
-
Or install it yourself as:
|
7
|
+
Install it using:
|
16
8
|
|
17
9
|
$ gem install tcptop
|
18
10
|
|
19
11
|
## Usage
|
20
12
|
|
21
|
-
|
13
|
+
$ tcptop -h
|
14
|
+
Usage: tcptop [options]
|
15
|
+
-t, --tcp SOCKET tcp socket to filter, can be used multiple times
|
16
|
+
-u, --unix PATH domain socket to filter, can be used multiple times, will not show by default
|
17
|
+
-1, --once print once and exit
|
18
|
+
-n, --interval SECONDS seconds between stat collection, DEFAULT: 2
|
19
|
+
--queued sort on queued requests, defaults to active
|
20
|
+
--collectd LABEL print output suitable for collectd, must also provide socket or path
|
21
|
+
-v, --version prints the version and exits
|
22
|
+
|
23
|
+
Output:
|
24
|
+
|
25
|
+
$ tcptop -1
|
26
|
+
Socket Active* Queued
|
27
|
+
0.0.0.0:22 3 0
|
28
|
+
0.0.0.0:8080 1 1
|
29
|
+
[::%2510935584]:22 0 0
|
30
|
+
[::%2510935584]:80 0 0
|
31
|
+
[::1%2510935584]:25 0 0
|
32
|
+
127.0.0.1:25 0 0
|
33
|
+
127.0.0.1:11211 0 0
|
34
|
+
|
35
|
+
## Domain Sockets
|
36
|
+
|
37
|
+
Unix sockets do not show up by default, if you wish to monitor a unix socket, you must pass the --unix flag
|
38
|
+
|
39
|
+
$ tcptop -1 --unix /tmp/foo.sock
|
40
|
+
Socket Active* Queued
|
41
|
+
/tmp/foo.sock 0 0
|
22
42
|
|
23
43
|
## Contributing
|
24
44
|
|
data/Rakefile
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
module Tcptop
|
2
|
+
class Collectd
|
3
|
+
def self.reading(active, queued, hostname, label, io=STDOUT)
|
4
|
+
time = Time.now.to_i
|
5
|
+
io.write "PUTVAL #{hostname}/#{label}/absolute-active #{time}:#{active}\n"
|
6
|
+
io.write "PUTVAL #{hostname}/#{label}/absolute-queued #{time}:#{queued}\n"
|
7
|
+
io.flush
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/tcptop/version.rb
CHANGED
data/lib/tcptop.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "tcptop/version"
|
2
|
+
require "tcptop/collectd"
|
2
3
|
require 'rubygems'
|
3
4
|
require 'raindrops'
|
4
5
|
require 'optparse'
|
@@ -7,13 +8,16 @@ LAYOUT = "%-20s %-8s %-8s"
|
|
7
8
|
|
8
9
|
module Tcptop
|
9
10
|
def self.parse_options!
|
10
|
-
options = {:tcp => [], :interval => 2, :sort => :active}
|
11
|
+
options = {:tcp => [], :unix => [], :interval => 2, :sort => :active}
|
11
12
|
OptionParser.new do |opts|
|
12
13
|
opts.banner = "Usage: tcptop [options]"
|
13
14
|
|
14
15
|
opts.on("-t", "--tcp SOCKET", "tcp socket to filter, can be used multiple times") do |sock|
|
15
16
|
options[:tcp] << sock
|
16
17
|
end
|
18
|
+
opts.on("-u", "--unix PATH", "domain socket to filter, can be used multiple times, will not show by default") do |path|
|
19
|
+
options[:unix] << path
|
20
|
+
end
|
17
21
|
opts.on("-1", "--once", "print once and exit") do
|
18
22
|
options[:once] = true
|
19
23
|
end
|
@@ -23,6 +27,9 @@ module Tcptop
|
|
23
27
|
opts.on("--queued", "sort on queued requests, defaults to active") do
|
24
28
|
options[:sort] = :queued
|
25
29
|
end
|
30
|
+
opts.on("--collectd LABEL", "print output suitable for collectd, must also provide socket or path") do |label|
|
31
|
+
options[:collectd] = label
|
32
|
+
end
|
26
33
|
opts.on("-v", "--version", "prints the version and exits") do
|
27
34
|
options[:version] = true
|
28
35
|
end
|
@@ -36,8 +43,29 @@ module Tcptop
|
|
36
43
|
puts "tcptop: version #{Tcptop::VERSION}"
|
37
44
|
exit 0
|
38
45
|
elsif options[:once]
|
39
|
-
print_info(options[:tcp], options[:sort])
|
46
|
+
print_info(options[:tcp], options[:unix], options[:sort])
|
40
47
|
exit 0
|
48
|
+
elsif options[:collectd]
|
49
|
+
unless options[:tcp].size == 1 || options[:unix].size == 1
|
50
|
+
puts "the --tcp or --unix option must be used once to identify the socket"
|
51
|
+
exit 1
|
52
|
+
end
|
53
|
+
|
54
|
+
Signal.trap("INT") { exit 0 }
|
55
|
+
hostname = ENV["COLLECTD_HOSTNAME"] || 'localhost'
|
56
|
+
interval = (ENV["COLLECTD_INTERVAL"] || '60').to_i
|
57
|
+
label = options[:collectd]
|
58
|
+
|
59
|
+
loop do
|
60
|
+
stats = nil
|
61
|
+
if options[:tcp].size > 0
|
62
|
+
_, stats = Raindrops::Linux.tcp_listener_stats(options[:tcp]).first
|
63
|
+
else
|
64
|
+
_, stats = Raindrops::Linux.unix_listener_stats(options[:unix]).first
|
65
|
+
end
|
66
|
+
Collectd.reading(stats.active, stats.queued, hostname, label)
|
67
|
+
sleep interval
|
68
|
+
end
|
41
69
|
else
|
42
70
|
Signal.trap("INT") { exit 0 }
|
43
71
|
|
@@ -45,19 +73,21 @@ module Tcptop
|
|
45
73
|
system "clear"
|
46
74
|
puts "Updated: #{Time.now}, checking every #{options[:interval]} seconds"
|
47
75
|
puts
|
48
|
-
print_info(options[:tcp], options[:sort])
|
76
|
+
print_info(options[:tcp], options[:unix], options[:sort])
|
49
77
|
sleep options[:interval]
|
50
78
|
end
|
51
79
|
end
|
52
80
|
end
|
53
81
|
|
54
|
-
def self.print_info(sockets, sort)
|
82
|
+
def self.print_info(sockets, paths, sort)
|
55
83
|
puts LAYOUT % [
|
56
84
|
"Socket",
|
57
85
|
"Active" + (sort == :active ? "*" : ""),
|
58
86
|
"Queued" + (sort == :queued ? "*" : "")
|
59
87
|
]
|
60
|
-
responses = if
|
88
|
+
responses = if paths.any?
|
89
|
+
Raindrops::Linux.unix_listener_stats(paths)
|
90
|
+
elsif sockets.empty?
|
61
91
|
Raindrops::Linux.tcp_listener_stats
|
62
92
|
else
|
63
93
|
Raindrops::Linux.tcp_listener_stats(sockets)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
class CollectdTest < Test::Unit::TestCase
|
4
|
+
def test_outputs_two_putvals_for_active_and_queued
|
5
|
+
s = ""
|
6
|
+
Tcptop::Collectd.reading(10, 2, 'localhost', 'unicorn', StringIO.new(s))
|
7
|
+
|
8
|
+
lines = s.split("\n")
|
9
|
+
assert_equal 2, lines.size
|
10
|
+
assert_match %r{PUTVAL localhost/unicorn/absolute-active \d+:10}, lines.first
|
11
|
+
assert_match %r{PUTVAL localhost/unicorn/absolute-queued \d+:2}, lines.last
|
12
|
+
end
|
13
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,72 +1,78 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: tcptop
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Tony Pitluga
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2013-10-30 00:00:00 +00:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
15
22
|
name: raindrops
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: 0.11.0
|
22
|
-
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
|
-
requirements:
|
26
|
+
requirements:
|
27
27
|
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 51
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 11
|
33
|
+
- 0
|
29
34
|
version: 0.11.0
|
30
|
-
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
31
38
|
name: bundler
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ~>
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: '1.3'
|
38
|
-
type: :development
|
39
39
|
prerelease: false
|
40
|
-
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
|
-
requirements:
|
42
|
+
requirements:
|
43
43
|
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
requirements:
|
51
|
-
- - ! '>='
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 9
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 3
|
49
|
+
version: "1.3"
|
54
50
|
type: :development
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: rake
|
55
54
|
prerelease: false
|
56
|
-
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
56
|
none: false
|
58
|
-
requirements:
|
59
|
-
- -
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
type: :development
|
65
|
+
version_requirements: *id003
|
62
66
|
description: A monitoring tool for TCP connections
|
63
|
-
email:
|
67
|
+
email:
|
64
68
|
- tony.pitluga@gmail.com
|
65
|
-
executables:
|
69
|
+
executables:
|
66
70
|
- tcptop
|
67
71
|
extensions: []
|
72
|
+
|
68
73
|
extra_rdoc_files: []
|
69
|
-
|
74
|
+
|
75
|
+
files:
|
70
76
|
- .gitignore
|
71
77
|
- Gemfile
|
72
78
|
- LICENSE.txt
|
@@ -74,31 +80,45 @@ files:
|
|
74
80
|
- Rakefile
|
75
81
|
- bin/tcptop
|
76
82
|
- lib/tcptop.rb
|
83
|
+
- lib/tcptop/collectd.rb
|
77
84
|
- lib/tcptop/version.rb
|
78
85
|
- tcptop.gemspec
|
86
|
+
- test/collectd_test.rb
|
87
|
+
- test/test_helper.rb
|
88
|
+
has_rdoc: true
|
79
89
|
homepage: http://github.com/pitluga/tcptop
|
80
|
-
licenses:
|
90
|
+
licenses:
|
81
91
|
- MIT
|
82
92
|
post_install_message:
|
83
93
|
rdoc_options: []
|
84
|
-
|
94
|
+
|
95
|
+
require_paths:
|
85
96
|
- lib
|
86
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
98
|
none: false
|
88
|
-
requirements:
|
89
|
-
- -
|
90
|
-
- !ruby/object:Gem::Version
|
91
|
-
|
92
|
-
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
hash: 3
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
107
|
none: false
|
94
|
-
requirements:
|
95
|
-
- -
|
96
|
-
- !ruby/object:Gem::Version
|
97
|
-
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
version: "0"
|
98
115
|
requirements: []
|
116
|
+
|
99
117
|
rubyforge_project:
|
100
|
-
rubygems_version: 1.
|
118
|
+
rubygems_version: 1.3.7
|
101
119
|
signing_key:
|
102
120
|
specification_version: 3
|
103
121
|
summary: A monitoring tool for TCP connections
|
104
|
-
test_files:
|
122
|
+
test_files:
|
123
|
+
- test/collectd_test.rb
|
124
|
+
- test/test_helper.rb
|