custodian 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2012 Johannes Gorset
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,23 +1,39 @@
1
1
  # Custodian
2
2
 
3
- Custodian is a lightweight resource monitor that is easy to use and augment.
3
+ Custodian is a lightweight resource monitor that makes it really easy
4
+ and really awesome to sample metrics.
4
5
 
5
6
  ## Usage
6
7
 
7
- Start Custodian and configure it to sample metrics every 60 seconds and expose
8
- them on port 5100:
8
+ ### Server
9
9
 
10
- $ custodian start 127.0.0.1:5100 --interval=60
10
+ Start Custodian and configure it to expose its metrics on port 5100:
11
11
 
12
- ## Augmenting Custodian
12
+ $ custodian --port=5100
13
13
 
14
- Custodian convenes statistics from *samplers*, which are just simple Ruby classes:
14
+ ![Example](https://github.com/jgorset/custodian/raw/master/docs/images/example.png)
15
15
 
16
- class Who << Custodian::Sampler
16
+ #### Samplers
17
17
 
18
- # Return a list of usernames describing logged-in users.
19
- def sample
20
- `who`.lines.collect { |line| line.split.first }
21
- end
18
+ Custodian aggregates metrics from *samplers*, and ships with samplers for popular figures
19
+ such as logged in users and load averages. That's interesting and all, but custom
20
+ samplers are all the rage.
22
21
 
23
- end
22
+ ```ruby
23
+ class RegisteredUsers < Custodian::Samplers::Sampler
24
+ describe "Registered users"
25
+
26
+ def self.sample
27
+ Users.count
28
+ end
29
+ end
30
+ ```
31
+
32
+ You can load your own samplers with the `--samplers` option.
33
+
34
+ $ custodian --samplers=~/.samplers
35
+
36
+ ### Clients
37
+
38
+ Unless you're crazy about JSON, you'll want to consume Custodian's API with a
39
+ *client*. Unfortunately, there are no clients for Custodian yet — you should make one!
data/Rakefile CHANGED
@@ -1 +1,7 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.test_files = FileList["test/*_test.rb"]
6
+ t.verbose = true
7
+ end
data/bin/custodian ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "custodian"
4
+
5
+ Custodian::CLI.new ARGV
data/custodian.gemspec CHANGED
@@ -19,6 +19,8 @@ Gem::Specification.new do |s|
19
19
  s.require_paths = ["lib"]
20
20
 
21
21
  # specify any dependencies here; for example:
22
- # s.add_development_dependency "rspec"
23
- # s.add_runtime_dependency "rest-client"
22
+ s.add_development_dependency "rspec"
23
+ s.add_runtime_dependency "thin"
24
+ s.add_runtime_dependency "rack"
25
+ s.add_runtime_dependency "active_support"
24
26
  end
Binary file
data/lib/custodian.rb CHANGED
@@ -1,5 +1,7 @@
1
- require "custodian/version"
2
-
3
1
  module Custodian
4
- # Your code goes here...
2
+ autoload :VERSION, "custodian/version"
3
+ autoload :Samplers, "custodian/samplers"
4
+ autoload :API, "custodian/api"
5
+ autoload :CLI, "custodian/cli"
6
+ autoload :OS, "custodian/os"
5
7
  end
@@ -0,0 +1,33 @@
1
+ require "json"
2
+
3
+ module Custodian
4
+
5
+ # The API class is a Rack-compatible* application that encapsulates
6
+ # Custodian's interface.
7
+ #
8
+ # * http://rack.rubyforge.org/doc/files/SPEC.html.
9
+ class API
10
+
11
+ # Render the JSON representation of each sample.
12
+ #
13
+ # env - A Hash of CGI-like headers describing the
14
+ # environment under which the request was received.
15
+ #
16
+ # Returns an Array describing the HTTP response.
17
+ def call(env)
18
+ status = 200
19
+
20
+ headers = {
21
+ "Content-Type" => "application/json"
22
+ }
23
+
24
+ body = Custodian::Samplers.list.collect do |sampler|
25
+ { description: sampler.description, sample: sampler.sample } if sampler.compatible?
26
+ end.compact.to_json
27
+
28
+ [status, headers, [body]]
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,158 @@
1
+ require "thin"
2
+ require "rack"
3
+ require "rack/auth/basic"
4
+ require "optparse"
5
+
6
+ module Custodian
7
+
8
+ # The CLI class encapsulates Custodian's command-line interface.
9
+ class CLI
10
+ DEFAULT_PORT = 5100
11
+
12
+ # Create a new command-line interface.
13
+ #
14
+ # arguments - An Array of String objects describing arguments
15
+ # passed to the program (see CLI#parse).
16
+ def initialize(arguments)
17
+ options = parse arguments
18
+
19
+ if samplers = options[:samplers]
20
+ load_samplers samplers
21
+ end
22
+
23
+ if options.include? :daemonize
24
+ deamonize
25
+ end
26
+
27
+ if pidfile = options[:pidfile]
28
+ write_pidfile pidfile
29
+ end
30
+
31
+ log "Custodian is accepting connections on port #{options[:port]}"
32
+
33
+ compatible_samplers = Custodian::Samplers.compatible
34
+ incompatible_samplers = Custodian::Samplers.incompatible
35
+
36
+ log "#{compatible_samplers.count} compatible samplers."
37
+ compatible_samplers.each do |s|
38
+ log " - #{s.description}"
39
+ end
40
+
41
+ log "#{incompatible_samplers.count} incompatible samplers."
42
+ incompatible_samplers.each do |s|
43
+ log " - #{s.description}"
44
+ end
45
+
46
+ log "CTRL+C to stop"
47
+
48
+ Thin::Logging.silent = true
49
+ Thin::Server.start '0.0.0.0', options[:port] do
50
+ use Rack::CommonLogger
51
+ use Rack::ShowExceptions
52
+ use Rack::Auth::Basic do |username, password|
53
+ [username, password] == [options[:username], options[:password]]
54
+ end if options.include? :username
55
+
56
+ run Custodian::API.new
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ # Load samplers from the given directories.
63
+ #
64
+ # directories - An Array of Strings describing paths to directories
65
+ # that contain samplers.
66
+ #
67
+ # Returns nothing.
68
+ def load_samplers(directories)
69
+ directories.each do |directory|
70
+ Custodian::Samplers.load directory
71
+ end
72
+ end
73
+
74
+ # Write the process id to the given file.
75
+ #
76
+ # file - A String describing a path to a file. If the file does not exist, it
77
+ # will be created. If the file already exists, it will be overwritten.
78
+ #
79
+ # Returns nothing.
80
+ def write_pidfile(file)
81
+ File.open file, "w" do |file|
82
+ file << Process.id
83
+ end
84
+ end
85
+
86
+ # Daemonize the process.
87
+ def deamonize
88
+ Process.daemon
89
+ end
90
+
91
+ # Parse the given arguments or exit with an error if they are malformed and/or invalid.
92
+ #
93
+ # arguments - An Array of String objects describing arguments passed to the program.
94
+ #
95
+ # Returns a Hash of options derived from the given arguments:
96
+ # :port - An Integer describing the port to listen on.
97
+ # :samplers - An Array of String objects describing paths to load samplers from.
98
+ # :daemonize - A Boolean describing whether or not to daemonize the process.
99
+ # :pidfile - A String describing a path to a file.
100
+ # :username - A String describing a username required by HTTP Basic authentication.
101
+ # :password - A String describing a password required by HTTP Basic authentication.
102
+ def parse(arguments)
103
+ options = {
104
+ port: DEFAULT_PORT
105
+ }
106
+
107
+ OptionParser.new do |o|
108
+ o.banner = "Usage: custodian [options]"
109
+ o.version = Custodian::VERSION
110
+
111
+ o.on "-p PORT", "--port PORT", "Listen on PORT (default #{options[:port]})" do |port|
112
+ options[:port] = port
113
+ end
114
+
115
+ o.on "-s DIR", "--samplers DIR", "Load samplers from DIR" do |samplers|
116
+ options[:samplers] = samplers.split(":")
117
+ end
118
+
119
+ o.on "--daemonize", "Daemonize the process" do
120
+ options[:daemonize] = true
121
+ end
122
+
123
+ o.on "--pidfile FILE", "Write the process id to FILE" do |pidfile|
124
+ options[:pidfile] = pidfile
125
+ end
126
+
127
+ o.on "--authenticate USERNAME:PASSWORD", "Authenticate clients with the given USERNAME and PASSWORD" do |credentials|
128
+ unless credentials.include? ":"
129
+ raise OptionParser::InvalidArgument, "must be a colon-separated string of username and password"
130
+ end
131
+
132
+ options[:username], options[:password] = credentials.split(":")
133
+ end
134
+ end.parse! arguments
135
+
136
+ options
137
+ rescue OptionParser::ParseError => e
138
+ error e
139
+ end
140
+
141
+ # Log a message to STDOUT.
142
+ #
143
+ # message - A String describing a message.
144
+ def log(message)
145
+ puts ">> #{message}"
146
+ end
147
+
148
+ # Print a message and exit with the given code.
149
+ #
150
+ # message - A String describing the message to print.
151
+ # code - An Integer describing the exit code (defaults to 1).
152
+ def error(message, code = 1)
153
+ puts "custodian: #{message}"
154
+ exit code
155
+ end
156
+ end
157
+
158
+ end
@@ -0,0 +1,25 @@
1
+ module Custodian
2
+
3
+ # The OS module encapsulates Custodian's operating
4
+ # system detection algorithms.
5
+ module OS
6
+
7
+ # Determine whether the operating system is darwin.
8
+ #
9
+ # Returns a boolean describing whether the operating system
10
+ # is darwin.
11
+ def self.darwin?
12
+ RUBY_PLATFORM.downcase.include? "darwin"
13
+ end
14
+
15
+ # Determine whether the operating system is linux.
16
+ #
17
+ # Returns a boolean describing whether the operating system
18
+ # is linux.
19
+ def self.linux?
20
+ RUBY_PLATFORM.downcase.include? "linux"
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,100 @@
1
+ require "pathname"
2
+
3
+ module Custodian
4
+
5
+ # The Samplers module encapsulates a collection of samplers
6
+ # for various metrics.
7
+ module Samplers
8
+ autoload :Sampler, "custodian/samplers/sampler"
9
+ autoload :Utilities, "custodian/samplers/utilities"
10
+
11
+ @samplers = []
12
+
13
+ # List all samplers.
14
+ #
15
+ # Returns an Array of Sampler objects.
16
+ def self.list
17
+ @samplers
18
+ end
19
+
20
+ # List compatible samplers.
21
+ #
22
+ # Returns an Array of Sampler objects that are compatible
23
+ # with this system.
24
+ def self.compatible
25
+ @samplers.select { |s| s.compatible? }
26
+ end
27
+
28
+ # List incompatible samplers.
29
+ #
30
+ # Returns an Array of Sampler objects that are incompatible
31
+ # with this system.
32
+ def self.incompatible
33
+ @samplers.reject { |s| s.compatible? }
34
+ end
35
+
36
+ # Register the given sampler.
37
+ #
38
+ # sampler - An object that inherits from Sampler.
39
+ #
40
+ # Returns nothing.
41
+ def self.register(sampler)
42
+ @samplers << sampler
43
+ end
44
+
45
+ # Remove the given sampler.
46
+ #
47
+ # sampler - An object that inherits from Sampler.
48
+ def self.remove(sampler)
49
+ @samplers.delete(sampler)
50
+ end
51
+
52
+ # Replace one sampler with another.
53
+ #
54
+ # a - An object that inherits from Sampler.
55
+ # b - Another object that inherits from Sampler.
56
+ #
57
+ # Returns nothing.
58
+ def self.replace(a, b)
59
+ remove a
60
+ register b
61
+ end
62
+
63
+ # Clear all samplers.
64
+ def self.clear
65
+ @samplers = []
66
+ end
67
+
68
+ # Restore stock samplers.
69
+ def self.stock
70
+ load File.dirname(__FILE__) + "/samplers/darwin" if OS.darwin?
71
+ load File.dirname(__FILE__) + "/samplers/linux" if OS.linux?
72
+ end
73
+
74
+ # Load samplers from the given directory.
75
+ #
76
+ # directory - A String describing a path to a directory. If the path is relative,
77
+ # it will be expanded from the current working directory. If the path
78
+ # is prefixed with a tilde, it will be expanded from the current user's
79
+ # home directory. If the path is prefixed with a tilde immediately followed
80
+ # by a username, it will be expanded from that user's home directory.
81
+ #
82
+ # Returns nothing.
83
+ def self.load(directory)
84
+ path = Pathname.new directory
85
+
86
+ # Allow referencing directories by relative and home path.
87
+ path = path.expand_path unless path.absolute?
88
+
89
+ unless path.directory?
90
+ raise StandardError, "#{directory} is not a directory"
91
+ end
92
+
93
+ path.each_child do |child|
94
+ require child if child.file?
95
+ end
96
+ end
97
+
98
+ stock
99
+ end
100
+ end
@@ -0,0 +1,19 @@
1
+ module Custodian
2
+ module Samplers
3
+
4
+ class CPU < Custodian::Samplers::Sampler
5
+ describe "CPU usage"
6
+
7
+ def self.sample
8
+ cpu = `top -l 1`.match /CPU usage: ([0-9]+\.[0-9]+%) user, ([0-9]+\.[0-9]+%) sys, ([0-9]+\.[0-9]+%) idle/
9
+
10
+ {
11
+ "User" => cpu[1],
12
+ "System" => cpu[2],
13
+ "Idle" => cpu[3]
14
+ }
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Custodian
2
+ module Samplers
3
+
4
+ class Load < Custodian::Samplers::Sampler
5
+ describe "Load averages"
6
+
7
+ def self.sample
8
+ uptime = `uptime`[/load averages: (.*)/, 1].split
9
+
10
+ {
11
+ "Last 5 minutes" => uptime[0],
12
+ "Last 10 minutes" => uptime[1],
13
+ "Last 15 minutes" => uptime[2]
14
+ }
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,29 @@
1
+ module Custodian
2
+ module Samplers
3
+
4
+ class RAM < Custodian::Samplers::Sampler
5
+ describe "RAM usage"
6
+
7
+ def self.sample
8
+ vmstat = `vm_stat`
9
+
10
+ pages_free = vmstat[/Pages free: +([0-9]+)/, 1].to_i + vmstat[/Pages speculative: +([0-9]+)/, 1].to_i
11
+ pages_inactive = vmstat[/Pages inactive: +([0-9]+)/, 1].to_i
12
+ pages_active = vmstat[/Pages active: +([0-9]+)/, 1].to_i
13
+ pages_wired = vmstat[/Pages wired down: +([0-9]+)/, 1].to_i
14
+ page_ins = vmstat[/Pageins: +([0-9]+)/, 1].to_i
15
+ page_outs = vmstat[/Pageouts: +([0-9]+)/, 1].to_i
16
+
17
+ {
18
+ "Free" => "#{pages_free * 4096 / 1024 / 1024} MB",
19
+ "Inactive" => "#{pages_inactive * 4096 / 1024 / 1024} MB",
20
+ "Active" => "#{pages_active * 4096 / 1024 / 1024} MB",
21
+ "Wired" => "#{pages_wired * 4096 / 1024 / 1024} MB",
22
+ "Page ins" => "#{page_ins * 4096 / 1024 / 1024} MB",
23
+ "Page outs" => "#{page_outs * 4096 / 1024 / 1024} MB"
24
+ }
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ module Custodian
2
+ module Samplers
3
+
4
+ class Who < Custodian::Samplers::Sampler
5
+ describe "Logged in users"
6
+
7
+ def self.sample
8
+ `who`.lines.collect { |line| line.split.first }.uniq
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ module Custodian
2
+ module Samplers
3
+
4
+ class CPU < Custodian::Samplers::Sampler
5
+ describe "CPU usage"
6
+
7
+ def self.sample
8
+ top = `top -b -n1`.match /Cpu\(s\): +([0-9.]+)%us, +([0-9.]+)%sy, +([0-9.%]+)ni, +([0-9.]+)%id, +([0-9.]+)%wa, +([0-9.]+)%hi, +([0-9.]+)%si, +([0-9.]+)%st/
9
+
10
+ us = top[1].to_f # User CPU time: The time the CPU has spent running users' processes that are not niced.
11
+ sy = top[2].to_f # System CPU time: The time the CPU has spent running the kernel and its processes.
12
+ ni = top[3].to_f # Nice CPU time: The time the CPU has spent running users' proccess that have been niced.
13
+ id = top[4].to_f # Hardware IRQ: The amount of time the CPU has been servicing hardware interrupts.
14
+ wa = top[5].to_f # iowait: Amount of time the CPU has been waiting for I/O to complete.
15
+ hi = top[6].to_f # Hardware IRQ: The amount of time the CPU has been servicing hardware interrupts.
16
+ si = top[7].to_f # Hardware Interrupts: The amount of time the CPU has been servicing software interrupts.
17
+ st = top[8].to_f # Steal Time: The amount of CPU 'stolen' from this virtual machine by the hypervisor for other tasks.
18
+
19
+ {
20
+ "User" => "#{us + ni}%",
21
+ "System" => "#{sy + wa + hi + si + st}%",
22
+ "Idle" => "#{id}%"
23
+ }
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+
@@ -0,0 +1,19 @@
1
+ module Custodian
2
+ module Samplers
3
+
4
+ class Load < Custodian::Samplers::Sampler
5
+ describe "Load averages"
6
+
7
+ def self.sample
8
+ uptime = `uptime`.match /load average: ([0-9.]+), ([0-9.]+), ([0-9.]+)/
9
+
10
+ {
11
+ "Last 5 minutes" => uptime[1],
12
+ "Last 10 minutes" => uptime[2],
13
+ "Last 15 minutes" => uptime[3]
14
+ }
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ module Custodian
2
+ module Samplers
3
+
4
+ class RAM < Custodian::Samplers::Sampler
5
+ describe "RAM usage"
6
+
7
+ def self.sample
8
+ free = `free -m`.match /Mem: +([0-9]+) +([0-9]+) +([0-9]+) +([0-9]+) +([0-9]+) +([0-9]+)/
9
+
10
+ {
11
+ "Total" => "#{free[1]} MB",
12
+ "Used" => "#{free[2]} MB",
13
+ "Free" => "#{free[3]} MB",
14
+ "Buffers" => "#{free[4]} MB",
15
+ "Cached" => "#{free[5]} MB"
16
+ }
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,58 @@
1
+ module Custodian
2
+ module Samplers
3
+
4
+ # Base class for samplers.
5
+ class Sampler
6
+ include Custodian::Samplers::Utilities
7
+
8
+ class << self
9
+
10
+ # Describe the sampler.
11
+ #
12
+ # description - A String describing the sampler.
13
+ #
14
+ # Returns nothing.
15
+ def describe(description)
16
+ @description = description
17
+ end
18
+
19
+ # Returns the sampler's description.
20
+ def description
21
+ @description
22
+ end
23
+
24
+ # Make a sample from this sampler.
25
+ #
26
+ # Examples
27
+ #
28
+ # CPU.sample # => { "User" => "10%", "System" => "5%", "Idle" => "85%" }
29
+ #
30
+ # Returns an Integer, Symbol, String, Hash or Array (or any combination thereof)
31
+ # describing the outcome of the sample.
32
+ def sample
33
+ nil
34
+ end
35
+
36
+ # Determine whether the sampler is compatible with this system.
37
+ #
38
+ # Returns true if it is compatible, or false if it isn't.
39
+ def compatible?
40
+ true
41
+ end
42
+
43
+ end
44
+
45
+ private
46
+
47
+ # Register samplers for classes that inherit from this class.
48
+ #
49
+ # sampler - The Class that inherited this class.
50
+ #
51
+ # Returns nothing.
52
+ def self.inherited(sampler)
53
+ Custodian::Samplers.register(sampler)
54
+ end
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,37 @@
1
+ module Custodian
2
+ module Samplers
3
+
4
+ # Utility methods for samplers.
5
+ module Utilities
6
+
7
+ # Determine whether the given program exists.
8
+ #
9
+ # program - A String describing the name of a program.
10
+ #
11
+ # Returns true if the program exists, or false if it doesn't.
12
+ def self.program_exists?(program)
13
+ system "which #{command} > /dev/null 2>&1"
14
+ end
15
+
16
+ # Determine whether the given directory exists.
17
+ #
18
+ # directory - A String describing the path to a directory.
19
+ #
20
+ # Returns true if the directory exists, or false if it doesn't.
21
+ def self.directory_exists?(directory)
22
+ Pathname.new(directory).directory?
23
+ end
24
+
25
+ # Determine whether the given file exists.
26
+ #
27
+ # file - A String describing the path to a file.
28
+ #
29
+ # Returns true if the file exists, or false if it doesn't.
30
+ def self.file_exists?(file)
31
+ Pathname.new(file).file?
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
@@ -1,3 +1,3 @@
1
1
  module Custodian
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/test/cli_test.rb ADDED
@@ -0,0 +1,24 @@
1
+ require "custodian"
2
+ require "minitest/spec"
3
+ require "minitest/autorun"
4
+ require "rack/test"
5
+
6
+ describe Custodian::API do
7
+ include Rack::Test::Methods
8
+
9
+ def app
10
+ Custodian::API.new
11
+ end
12
+
13
+ it "responds with HTTP 200 OK" do
14
+ get "/"
15
+
16
+ last_response.ok?.must_equal true
17
+ end
18
+
19
+ it "responds with valid JSON" do
20
+ get "/"
21
+
22
+ JSON.parse(last_response.body).must_be_instance_of Array
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ require "custodian"
2
+ require "minitest/spec"
3
+ require "minitest/autorun"
4
+
5
+ describe Custodian::Samplers::Sampler do
6
+
7
+ before do
8
+ @sampler = Custodian::Samplers::Sampler
9
+ end
10
+
11
+ it "can sample" do
12
+ @sampler.sample
13
+ end
14
+
15
+ it "can be described" do
16
+ @sampler.description.must_equal nil
17
+ end
18
+
19
+ it "can determine whether its compatible" do
20
+ @sampler.compatible?.must_equal true
21
+ end
22
+
23
+ end
@@ -0,0 +1,47 @@
1
+ require "custodian"
2
+ require "minitest/spec"
3
+ require "minitest/autorun"
4
+
5
+ describe Custodian::Samplers do
6
+
7
+ before do
8
+ Custodian::Samplers.clear
9
+ end
10
+
11
+ after do
12
+ Custodian::Samplers.stock
13
+ end
14
+
15
+ it "can list samplers" do
16
+ Custodian::Samplers.list.must_be_instance_of Array
17
+ end
18
+
19
+ it "can list compatible samplers" do
20
+ Custodian::Samplers.compatible.must_be_instance_of Array
21
+ end
22
+
23
+ it "can list incompatible samplers" do
24
+ Custodian::Samplers.incompatible.must_be_instance_of Array
25
+ end
26
+
27
+ it "can register new samplers" do
28
+ Custodian::Samplers::register Custodian::Samplers::CPU
29
+
30
+ Custodian::Samplers.list.must_include Custodian::Samplers::CPU
31
+ end
32
+
33
+ it "can remove samplers" do
34
+ Custodian::Samplers::remove Custodian::Samplers::CPU
35
+
36
+ Custodian::Samplers.list.wont_include Custodian::Samplers::CPU
37
+ end
38
+
39
+ it "can replace samplers" do
40
+ Custodian::Samplers.register Custodian::Samplers::CPU
41
+ Custodian::Samplers.replace Custodian::Samplers::CPU, Custodian::Samplers::RAM
42
+
43
+ Custodian::Samplers.list.must_include Custodian::Samplers::RAM
44
+ Custodian::Samplers.list.wont_include Custodian::Samplers::CPU
45
+ end
46
+
47
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: custodian
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,86 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-24 00:00:00.000000000 Z
13
- dependencies: []
12
+ date: 2012-02-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70234530717300 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70234530717300
25
+ - !ruby/object:Gem::Dependency
26
+ name: thin
27
+ requirement: &70234530713980 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70234530713980
36
+ - !ruby/object:Gem::Dependency
37
+ name: rack
38
+ requirement: &70234530708540 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70234530708540
47
+ - !ruby/object:Gem::Dependency
48
+ name: active_support
49
+ requirement: &70234536390620 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70234536390620
14
58
  description: Custodian is a lightweight resource monitor that is easy to use and augment
15
59
  email:
16
60
  - jgorset@gmail.com
17
- executables: []
61
+ executables:
62
+ - custodian
18
63
  extensions: []
19
64
  extra_rdoc_files: []
20
65
  files:
21
66
  - .gitignore
22
67
  - Gemfile
68
+ - LICENSE
23
69
  - README.md
24
70
  - Rakefile
71
+ - bin/custodian
25
72
  - custodian.gemspec
73
+ - docs/images/example.png
26
74
  - lib/custodian.rb
75
+ - lib/custodian/api.rb
76
+ - lib/custodian/cli.rb
77
+ - lib/custodian/os.rb
78
+ - lib/custodian/samplers.rb
79
+ - lib/custodian/samplers/darwin/cpu.rb
80
+ - lib/custodian/samplers/darwin/load.rb
81
+ - lib/custodian/samplers/darwin/ram.rb
82
+ - lib/custodian/samplers/darwin/who.rb
83
+ - lib/custodian/samplers/linux/cpu.rb
84
+ - lib/custodian/samplers/linux/load.rb
85
+ - lib/custodian/samplers/linux/ram.rb
86
+ - lib/custodian/samplers/sampler.rb
87
+ - lib/custodian/samplers/utilities.rb
27
88
  - lib/custodian/version.rb
89
+ - test/cli_test.rb
90
+ - test/sampler_test.rb
91
+ - test/samplers_test.rb
28
92
  homepage: http://github.com/jgorset/custodian
29
93
  licenses: []
30
94
  post_install_message:
@@ -49,4 +113,7 @@ rubygems_version: 1.8.11
49
113
  signing_key:
50
114
  specification_version: 3
51
115
  summary: Lightweight resource monitor
52
- test_files: []
116
+ test_files:
117
+ - test/cli_test.rb
118
+ - test/sampler_test.rb
119
+ - test/samplers_test.rb