tcptop 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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