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 CHANGED
@@ -1,24 +1,44 @@
1
1
  # Tcptop
2
2
 
3
- TODO: Write a gem description
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
- Add this line to your application's Gemfile:
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
- TODO: Write usage instructions here
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
@@ -1 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << "test"
8
+ t.test_files = FileList['test/*_test.rb']
9
+ t.verbose = true
10
+ end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Tcptop
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
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 sockets.empty?
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
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
+ require 'tcptop'
3
+ require 'test/unit'
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
- version: 0.0.1
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
- date: 2013-04-24 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
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
- version_requirements: !ruby/object:Gem::Requirement
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
- - !ruby/object:Gem::Dependency
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
- version_requirements: !ruby/object:Gem::Requirement
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
41
  none: false
42
- requirements:
42
+ requirements:
43
43
  - - ~>
44
- - !ruby/object:Gem::Version
45
- version: '1.3'
46
- - !ruby/object:Gem::Dependency
47
- name: rake
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
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
- version_requirements: !ruby/object:Gem::Requirement
55
+ requirement: &id003 !ruby/object:Gem::Requirement
57
56
  none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
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
- files:
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
- require_paths:
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
- version: '0'
92
- required_rubygems_version: !ruby/object:Gem::Requirement
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
- version: '0'
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.8.25
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