instrumental 0.1.4

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/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'rake', '0.8.7'
4
+ gem 'rspec'
5
+ gem 'jeweler'
@@ -0,0 +1,26 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ git (1.2.5)
6
+ jeweler (1.6.2)
7
+ bundler (~> 1.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rake (0.8.7)
11
+ rspec (2.6.0)
12
+ rspec-core (~> 2.6.0)
13
+ rspec-expectations (~> 2.6.0)
14
+ rspec-mocks (~> 2.6.0)
15
+ rspec-core (2.6.2)
16
+ rspec-expectations (2.6.0)
17
+ diff-lcs (~> 1.1.2)
18
+ rspec-mocks (2.6.0)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ jeweler
25
+ rake (= 0.8.7)
26
+ rspec
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Shearer Consultancy Ltd.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,3 @@
1
+ For setup and configuration information, please see:
2
+
3
+ http://imperialapp.com/pages/ruby_on_rails
@@ -0,0 +1,34 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :spec
7
+
8
+ RSpec::Core::RakeTask.new do |t|
9
+ t.pattern = 'spec/**/*_spec.rb'
10
+ end
11
+
12
+ desc 'Generate documentation for the instrumental plugin.'
13
+ Rake::RDocTask.new(:rdoc) do |rdoc|
14
+ rdoc.rdoc_dir = 'rdoc'
15
+ rdoc.title = 'Instrumental'
16
+ rdoc.options << '--line-numbers' << '--inline-source'
17
+ rdoc.rdoc_files.include('README')
18
+ rdoc.rdoc_files.include('lib/**/*.rb')
19
+ end
20
+
21
+ desc "Default: run the specs"
22
+ task :default => [:spec]
23
+
24
+ begin
25
+ require 'jeweler'
26
+ Jeweler::Tasks.new do |s|
27
+ s.name = "instrumental"
28
+ s.summary = s.description = "Rails instrumentation and client for imperialapp.com"
29
+ s.email = "support@imperialapp.com"
30
+ s.homepage = "http://github.com/imperialapp/instrumental"
31
+ s.authors = ["Douglas F Shearer"]
32
+ s.files = `git ls-files`.split("\n")
33
+ end
34
+ end
data/TODO ADDED
@@ -0,0 +1,3 @@
1
+ Allow to be loaded in any rack app.
2
+ specs for everything
3
+ generator for config
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.4
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'instrumental'
@@ -0,0 +1,66 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{instrumental}
8
+ s.version = "0.1.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Douglas F Shearer"]
12
+ s.date = %q{2011-06-06}
13
+ s.description = %q{Rails instrumentation and client for imperialapp.com}
14
+ s.email = %q{support@imperialapp.com}
15
+ s.extra_rdoc_files = [
16
+ "README",
17
+ "TODO"
18
+ ]
19
+ s.files = [
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "MIT-LICENCE",
23
+ "README",
24
+ "Rakefile",
25
+ "TODO",
26
+ "VERSION",
27
+ "init.rb",
28
+ "instrumental.gemspec",
29
+ "lib/instrumental.rb",
30
+ "lib/instrumental/agent.rb",
31
+ "lib/instrumental/configuration.rb",
32
+ "lib/instrumental/instrument.rb",
33
+ "lib/instrumental/intervalometer.rb",
34
+ "lib/tasks/install.rake",
35
+ "lib/tasks/templates/instrumental.rb.erb",
36
+ "spec/instrumental/agent_spec.rb",
37
+ "spec/instrumental/configuration_spec.rb",
38
+ "spec/instrumental/instrument_methods_spec.rb",
39
+ "spec/instrumental/intervalometer_spec.rb",
40
+ "spec/instrumental/setup_methods_spec.rb",
41
+ "spec/spec_helper.rb"
42
+ ]
43
+ s.homepage = %q{http://github.com/imperialapp/instrumental}
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = %q{1.6.2}
46
+ s.summary = %q{Rails instrumentation and client for imperialapp.com}
47
+
48
+ if s.respond_to? :specification_version then
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
+ s.add_runtime_dependency(%q<rake>, ["= 0.8.7"])
53
+ s.add_runtime_dependency(%q<rspec>, [">= 0"])
54
+ s.add_runtime_dependency(%q<jeweler>, [">= 0"])
55
+ else
56
+ s.add_dependency(%q<rake>, ["= 0.8.7"])
57
+ s.add_dependency(%q<rspec>, [">= 0"])
58
+ s.add_dependency(%q<jeweler>, [">= 0"])
59
+ end
60
+ else
61
+ s.add_dependency(%q<rake>, ["= 0.8.7"])
62
+ s.add_dependency(%q<rspec>, [">= 0"])
63
+ s.add_dependency(%q<jeweler>, [">= 0"])
64
+ end
65
+ end
66
+
@@ -0,0 +1,53 @@
1
+ require 'instrumental/agent'
2
+ require 'instrumental/configuration'
3
+ require 'instrumental/intervalometer'
4
+ require 'instrumental/instrument'
5
+
6
+ module Instrumental
7
+
8
+ @config = Configuration.new
9
+
10
+ def self.configure
11
+ yield @config
12
+ end
13
+
14
+ def self.boot!
15
+ if @config.enabled?
16
+
17
+ if defined?(PhusionPassenger)
18
+ PhusionPassenger.on_event(:starting_worker_process) do
19
+ @config.logger.debug('Starting a new worker process')
20
+ Agent.instance.setup_and_run
21
+ end
22
+
23
+ PhusionPassenger.on_event(:stopping_worker_process) do
24
+ @config.logger.debug('Killing worker process')
25
+ Agent.instance.stop
26
+ end
27
+
28
+ else
29
+ @config.logger.debug('Starting a new worker process')
30
+ Agent.instance.setup_and_run
31
+ end
32
+ end
33
+ end
34
+
35
+ def self.config
36
+ @config
37
+ end
38
+
39
+ def self.count(name, value=1)
40
+ Agent.instance.report(:count, name, value)
41
+ end
42
+
43
+ def self.measure(name, value)
44
+ Agent.instance.report(:measure, name, value)
45
+ end
46
+
47
+ def self.timer(name)
48
+ start_time = Time.now
49
+ yield
50
+ self.measure(name, Time.now - start_time)
51
+ end
52
+
53
+ end
@@ -0,0 +1,100 @@
1
+ require 'singleton'
2
+ require 'net/http'
3
+ require 'cgi'
4
+
5
+ module Instrumental
6
+ class Agent
7
+ include Singleton
8
+
9
+ @@queue = { :count => {}, :measure => {} }
10
+ @@queue_mutex = Mutex.new
11
+
12
+ def report(type, name, value)
13
+ # TODO: Print this to log?
14
+ return nil unless config && config.enabled?
15
+
16
+ type = type.to_sym
17
+ @@queue_mutex.synchronize do
18
+ if type == :count
19
+ @@queue[:count][name] ||= 0
20
+ @@queue[:count][name] += value
21
+ else
22
+ @@queue[:measure][name] ||= []
23
+ @@queue[:measure][name] << value
24
+ end
25
+ end
26
+ end
27
+
28
+ def setup_and_run
29
+ @intervalometer = Intervalometer.new(config.report_interval)
30
+
31
+ config.logger.debug("Starting agent. Reporting every #{config.report_interval} seconds")
32
+ @thread = Thread.new do
33
+ begin
34
+ @intervalometer.run do
35
+ config.logger.debug('Intervalometer run')
36
+ new_queue_items = {}
37
+ @@queue_mutex.synchronize do
38
+ new_queue_items = @@queue.dup
39
+ @@queue[:count] = {}
40
+ @@queue[:measure] = {}
41
+ config.logger.debug("Queue contains #{new_queue_items.inspect}")
42
+ end
43
+
44
+ new_queue_items[:count].each do |name, value|
45
+ send_report(:count, name, value)
46
+ end
47
+
48
+ new_queue_items[:measure].each do |name, values|
49
+ send_report(:measure, name, values.join(','))
50
+ end
51
+ end
52
+ rescue => e
53
+ config.logger.error e
54
+ config.logger.error e.backtrace.join("\n")
55
+ end
56
+ end
57
+ end
58
+
59
+ def stop
60
+ # If the app crashes, Passenger calls halt as it winds-down the process.
61
+ # Only call halt if intervalometer exists.
62
+ @intervalometer && @intervalometer.halt
63
+ end
64
+
65
+ protected
66
+
67
+ def config
68
+ Instrumental.config
69
+ end
70
+
71
+ def send_report(type, name, value)
72
+ if type == :measure
73
+ attributes = { :values => value }
74
+ else
75
+ attributes = { :value => value }
76
+ end
77
+
78
+ attributes[:name] = URI.escape("#{ config.name_prefix }#{ name }")
79
+ attributes[:api_key] = config.api_key
80
+
81
+ # attributes_string = attributes.to_a.map{ |a| a.join('=') }.join('&')
82
+
83
+ path = "#{ config.path }#{ type }"
84
+ # config.logger.debug("Calling #{ path }")
85
+
86
+ response = post_response(path, attributes)
87
+
88
+ unless response.is_a?(Net::HTTPSuccess)
89
+ config.logger.error "[Instrumental] Unexpected response from server (#{ response.code }): #{ response.message }"
90
+ end
91
+ end
92
+
93
+ def post_response(path, params)
94
+ req = Net::HTTP::Post.new(path)
95
+ req.set_form_data(params)
96
+ Net::HTTP.new(config.host, config.port).start { |h| h.request(req) }
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,70 @@
1
+ require 'logger'
2
+
3
+ module Instrumental
4
+ class Configuration
5
+
6
+ DEFAULT_REPORT_INTERVAL = 15.0
7
+
8
+ attr_reader :host
9
+ attr_reader :port
10
+ attr_reader :path
11
+ attr_reader :report_interval
12
+ attr_accessor :enabled
13
+ attr_writer :logger
14
+ attr_accessor :name_prefix
15
+
16
+ def initialize
17
+ @enabled = defined?(::Rails.env) ? Rails.env.production? : true
18
+ @host = 'in.imperialapp.com'
19
+ @port = 80
20
+ @name_prefix = ''
21
+ @path = '/in/'
22
+ @report_interval = DEFAULT_REPORT_INTERVAL
23
+ end
24
+
25
+ def enabled?
26
+ !!@enabled
27
+ end
28
+
29
+ def host=(val)
30
+ @host = val
31
+
32
+ raise(ArgumentError, "host is invalid") unless @host =~ /^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?)?$/ix
33
+ end
34
+
35
+ def port=(val)
36
+ @port = val
37
+
38
+ raise(ArgumentError, "port must be an integer greater than 0") unless @port.to_i > 0
39
+ end
40
+
41
+ def path=(val)
42
+ @path = val
43
+
44
+ raise(ArgumentError, 'path is invalid') unless @path =~ /^\/(.+\/)?$/
45
+ end
46
+
47
+ def report_interval=(val)
48
+ @report_interval = val.to_f
49
+
50
+ raise(ArgumentError, "report_interval should be greater than or equal to #{DEFAULT_REPORT_INTERVAL}") if @report_interval < DEFAULT_REPORT_INTERVAL
51
+ end
52
+
53
+ def api_key=(val)
54
+ @api_key = val
55
+
56
+ raise(ArgumentError, 'API key is invalid') unless @api_key =~ /^[a-f\d]{32}$/
57
+ end
58
+
59
+ def api_key
60
+ @api_key || raise(ArgumentError, 'API key must be set in configuration')
61
+ end
62
+
63
+ def logger
64
+ # The Rails logger is not available in an initializer, so we have to look for on-demand.
65
+ @logger ||= defined?(::Rails.logger) ? Rails.logger : Logger.new(STDOUT)
66
+ @logger
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,19 @@
1
+ module Instrumental
2
+ module Instrument
3
+
4
+ def self.count(name, value=1)
5
+ Agent.instance.report(:count, name, value)
6
+ end
7
+
8
+ def self.measure(name, value)
9
+ Agent.instance.report(:measure, name, value)
10
+ end
11
+
12
+ def self.timer(name)
13
+ start_time = Time.now
14
+ yield
15
+ self.measure(name, Time.now - start_time)
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ module Instrumental
2
+ class Intervalometer
3
+
4
+ def initialize(period=60.0)
5
+ @period = period.to_f
6
+ @running = true
7
+ @run_next = Time.now
8
+ end
9
+
10
+ def halt
11
+ # TODO: See if it would be possible for the intervalometer to do a
12
+ # final run before the thread exits.
13
+ @running = false
14
+ end
15
+
16
+ # Runs a passed block at intervals defined by the period set during
17
+ # initialization. Uses intervalometer to keep reasonably precise intervals.
18
+ def run
19
+ while @running
20
+ if Time.now < @run_next
21
+ sleep @run_next - Time.now
22
+ end
23
+
24
+ @run_next = Time.now + @period
25
+ yield
26
+ end
27
+ end # run
28
+
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ namespace :instrumental do
2
+
3
+ desc 'Installs the configuration initializer'
4
+ task :install do
5
+ unless ENV.include?('api_key')
6
+ raise "usage: rake instrumental:install api_key=YOUR_API_KEY"
7
+ end
8
+
9
+ api_key = ENV['api_key']
10
+ template_path = File.expand_path(File.join(File.dirname(__FILE__), 'templates', 'instrumental.rb.erb'))
11
+ template = ERB.new(File.read(template_path))
12
+ location = File.join('config', 'initializers', 'instrumental.rb')
13
+
14
+ File.open(location, 'w+') do |f|
15
+ f.write template.result(binding)
16
+ end
17
+
18
+ puts 'Instrumental Installed!'
19
+ puts "Configuration written to #{location}"
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,4 @@
1
+ Instrumental.configure do |config|
2
+ config.api_key = "<%= api_key %>"
3
+ end
4
+ Instrumental.boot!
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'instrumental/agent'
3
+
4
+ include Instrumental
5
+
6
+ describe Instrumental::Agent do
7
+
8
+ describe "report" do
9
+
10
+ end
11
+
12
+ describe "setup_and_run" do
13
+
14
+ end
15
+
16
+ describe "stop" do
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,245 @@
1
+ require 'spec_helper'
2
+ require 'instrumental/configuration'
3
+
4
+ include Instrumental
5
+
6
+ class Rails;end # Used for testing the logger.
7
+
8
+ describe Instrumental::Configuration do
9
+
10
+ before(:each) do
11
+ @config = Configuration.new
12
+ end
13
+
14
+ describe "in the default state" do
15
+ it "should raise an argument error for the missing API key" do
16
+ lambda { @config.api_key }.should raise_error(ArgumentError, 'API key must be set in configuration')
17
+ end
18
+
19
+ it "should have a host" do
20
+ @config.host.should == 'in.imperialapp.com'
21
+ end
22
+
23
+ it "should have a port" do
24
+ @config.port.should == 80
25
+ end
26
+
27
+ it "should have a path" do
28
+ @config.path.should == '/in/'
29
+ end
30
+
31
+ it "should have a report interval" do
32
+ @config.report_interval.should == 15.0
33
+ end
34
+
35
+ it "should have a logger" do
36
+ @config.logger.should be_a(Logger)
37
+ end
38
+
39
+ it "should have enabled set to true" do
40
+ @config.logger.should be_true
41
+ end
42
+
43
+ it "should have an empty name prefix" do
44
+ @config.name_prefix.should be_empty
45
+ end
46
+ end
47
+
48
+ describe "where Rails is defined" do
49
+ context "production environment" do
50
+ before(:each) do
51
+ Rails.stub(:logger).and_return(@mock_logger = mock(:logger))
52
+ Rails.stub(:env).and_return(mock(:environment, :production? => true))
53
+ @rails_config = Configuration.new
54
+ end
55
+
56
+ it "should be the mock logger" do
57
+ @rails_config.logger.should == @mock_logger
58
+ end
59
+
60
+ it "should have enabled as true" do
61
+ @rails_config.enabled.should be_true
62
+ end
63
+ end
64
+
65
+ context "non-production environment" do
66
+ before(:each) do
67
+ Rails.stub(:env).and_return(mock(:environment, :production? => false))
68
+ @rails_config = Configuration.new
69
+ end
70
+
71
+ it "should have enabled as false" do
72
+ @rails_config.enabled.should be_false
73
+ end
74
+ end
75
+ end
76
+
77
+ describe "Setting the API key" do
78
+ context "with a valid key" do
79
+ before(:each) do
80
+ @config.api_key = '01e694159b73a5f3784bbe9d63412b8d'
81
+ end
82
+
83
+ it "should not raise an error" do
84
+ lambda { @config.api_key }.should_not raise_error
85
+ end
86
+
87
+ it "should have an API key" do
88
+ @config.api_key.should == '01e694159b73a5f3784bbe9d63412b8d'
89
+ end
90
+ end
91
+
92
+ %w{cheese 123 01e694159b73a5f3784bbe9d63412b8 01e694159b73a5f3784bbe9d63412b8D}.each do |invalid_key|
93
+ context "with invalid key, #{invalid_key}," do
94
+ it "should raise an argument error" do
95
+ lambda { @config.api_key = invalid_key }.should raise_error(ArgumentError, 'API key is invalid')
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ describe "Setting the report_interval" do
102
+ context "with a valid value" do
103
+ it "should not raise an error" do
104
+ lambda { @config.report_interval = 20.1 }.should_not raise_error
105
+ end
106
+
107
+ it "should have the report_interval set" do
108
+ @config.report_interval = 20.1
109
+ @config.report_interval.should == 20.1
110
+ end
111
+ end
112
+ end
113
+
114
+ describe "Setting the host" do
115
+ %w{in.imperialapp.com foo.bar.com foo.bar.rar.me}.each do |valid_host|
116
+ context "with a valid host, #{valid_host}" do
117
+ it "should not raise an error" do
118
+ lambda { @config.host = valid_host }.should_not raise_error
119
+ end
120
+
121
+ it "should have the host set" do
122
+ @config.host = valid_host
123
+ @config.host.should == valid_host
124
+ end
125
+ end
126
+ end
127
+
128
+ %w{in.imperialapp.com/ http://in.imperialapp.com mince}.each do |invalid_host|
129
+ context "with invalid host, #{invalid_host}," do
130
+ it "should raise an argument error" do
131
+ lambda { @config.host = invalid_host }.should raise_error(ArgumentError, 'host is invalid')
132
+ end
133
+ end
134
+ end
135
+
136
+ context "with a blank host" do
137
+ it "should raise an argument error" do
138
+ lambda { @config.host = '' }.should raise_error(ArgumentError, 'host is invalid')
139
+ end
140
+ end
141
+ end
142
+
143
+ describe "Setting the port" do
144
+ context "with a valid port" do
145
+ it "should not raise an error" do
146
+ lambda { @config.port = 3000 }.should_not raise_error
147
+ end
148
+
149
+ it "should have the port set" do
150
+ @config.port = 3000
151
+ @config.port.should == 3000
152
+ end
153
+ end
154
+
155
+ context "with an invalid port" do
156
+ it "should raise an argument error for a string" do
157
+ lambda { @config.port = 'mince' }.should raise_error(ArgumentError, 'port must be an integer greater than 0')
158
+ end
159
+
160
+ it "should raise an argument error for nil" do
161
+ lambda { @config.port = nil }.should raise_error(ArgumentError, 'port must be an integer greater than 0')
162
+ end
163
+
164
+ it "should raise an argument error for 0" do
165
+ lambda { @config.port = 0 }.should raise_error(ArgumentError, 'port must be an integer greater than 0')
166
+ end
167
+ end
168
+ end
169
+
170
+ describe "Setting the path" do
171
+ %w{/ /foo/ /bar/rar/ /23/}.each do |valid_path|
172
+ context "with a valid path, #{valid_path}" do
173
+ it "should not raise an error" do
174
+ lambda { @config.path = valid_path }.should_not raise_error
175
+ end
176
+
177
+ it "should have the path set" do
178
+ @config.path = valid_path
179
+ @config.path.should == valid_path
180
+ end
181
+ end
182
+ end
183
+
184
+ %w{// bar/ /bar bar}.each do |invalid_path|
185
+ context "with invalid path, #{invalid_path}," do
186
+ it "should raise an argument error" do
187
+ lambda { @config.path = invalid_path }.should raise_error(ArgumentError, 'path is invalid')
188
+ end
189
+ end
190
+ end
191
+
192
+ context "with a blank path" do
193
+ it "should raise an argument error" do
194
+ lambda { @config.path = '' }.should raise_error(ArgumentError, 'path is invalid')
195
+ end
196
+ end
197
+ end
198
+
199
+ describe "setting the logger" do
200
+ it "should have the logger set" do
201
+ @config.logger = 'foo'
202
+ @config.logger.should == 'foo'
203
+ end
204
+ end
205
+
206
+ describe "setting enabled" do
207
+ before(:each) do
208
+ @config.enabled = 'non nil value'
209
+ end
210
+
211
+ it "should have the enabled status set" do
212
+ @config.enabled.should == 'non nil value'
213
+ end
214
+ end
215
+
216
+ describe "enabled?" do
217
+ it "should be false for nil" do
218
+ @config.enabled = nil
219
+ @config.should_not be_enabled
220
+ end
221
+
222
+ it "should be false for false" do
223
+ @config.enabled = false
224
+ @config.should_not be_enabled
225
+ end
226
+
227
+ it "should be true for true" do
228
+ @config.enabled = true
229
+ @config.should be_enabled
230
+ end
231
+
232
+ it "should be true for other values" do
233
+ @config.enabled = 'non nil value'
234
+ @config.should be_enabled
235
+ end
236
+ end
237
+
238
+ describe "setting the name_prefix" do
239
+ it "should have the name_prefix set" do
240
+ @config.name_prefix = 'my prefix'
241
+ @config.name_prefix.should == 'my prefix'
242
+ end
243
+ end
244
+
245
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ require 'instrumental'
3
+
4
+ class Agent;end
5
+
6
+ describe 'public instrument methods' do
7
+
8
+ before(:each) do
9
+ Agent.stub(:instance).and_return(@mock_agent_instance = mock(:agent_instance))
10
+ end
11
+
12
+ describe "count" do
13
+ context "without a value" do
14
+ it "should send a value of 1" do
15
+ @mock_agent_instance.should_receive(:report).with(:count, 'my name', 1)
16
+
17
+ Instrument.count('my name')
18
+ end
19
+ end
20
+
21
+ context "with a value" do
22
+ it "should send the passed value" do
23
+ @mock_agent_instance.should_receive(:report).with(:count, 'my name', 23)
24
+
25
+ Instrument.count('my name', 23)
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "measure" do
31
+ it "should send the passed value" do
32
+ @mock_agent_instance.should_receive(:report).with(:measure, 'my name', 19.2)
33
+
34
+ Instrument.measure('my name', 19.2)
35
+ end
36
+ end
37
+
38
+ describe "timer" do
39
+ it "should send the calculated time" do
40
+ delta = 1.574
41
+ Time.should_receive(:now).and_return(0)
42
+ Time.should_receive(:now).and_return(delta)
43
+
44
+ @mock_agent_instance.should_receive(:report).with(:measure, 'my name', delta)
45
+
46
+ Instrument.timer('my name') { 'do stuff' }
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'instrumental/intervalometer'
3
+
4
+ include Instrumental
5
+
6
+ describe Instrumental::Intervalometer do
7
+
8
+ describe "initialize" do
9
+
10
+ end
11
+
12
+ describe "halt" do
13
+
14
+ end
15
+
16
+ describe "run" do
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'instrumental'
3
+
4
+ describe 'setup methods' do
5
+
6
+ describe "configure" do
7
+
8
+ # Speccing yield. http://awesomeful.net/posts/75-spec-your-yields-in-rspec
9
+ it "should call yield" do
10
+ # Instrumental.should_receive(:yield).with(instance_of(Instrumental::Configuration))
11
+ #
12
+ # Instrumental.configure do |c|
13
+ # c.api_key = 'foo foo'
14
+ # end
15
+ end
16
+
17
+
18
+ end
19
+
20
+ describe "boot" do
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1 @@
1
+ require 'rspec/core'
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: instrumental
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 4
10
+ version: 0.1.4
11
+ platform: ruby
12
+ authors:
13
+ - Douglas F Shearer
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-06-06 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rake
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - "="
28
+ - !ruby/object:Gem::Version
29
+ hash: 49
30
+ segments:
31
+ - 0
32
+ - 8
33
+ - 7
34
+ version: 0.8.7
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rspec
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: jeweler
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ type: :runtime
64
+ version_requirements: *id003
65
+ description: Rails instrumentation and client for imperialapp.com
66
+ email: support@imperialapp.com
67
+ executables: []
68
+
69
+ extensions: []
70
+
71
+ extra_rdoc_files:
72
+ - README
73
+ - TODO
74
+ files:
75
+ - Gemfile
76
+ - Gemfile.lock
77
+ - MIT-LICENCE
78
+ - README
79
+ - Rakefile
80
+ - TODO
81
+ - VERSION
82
+ - init.rb
83
+ - instrumental.gemspec
84
+ - lib/instrumental.rb
85
+ - lib/instrumental/agent.rb
86
+ - lib/instrumental/configuration.rb
87
+ - lib/instrumental/instrument.rb
88
+ - lib/instrumental/intervalometer.rb
89
+ - lib/tasks/install.rake
90
+ - lib/tasks/templates/instrumental.rb.erb
91
+ - spec/instrumental/agent_spec.rb
92
+ - spec/instrumental/configuration_spec.rb
93
+ - spec/instrumental/instrument_methods_spec.rb
94
+ - spec/instrumental/intervalometer_spec.rb
95
+ - spec/instrumental/setup_methods_spec.rb
96
+ - spec/spec_helper.rb
97
+ has_rdoc: true
98
+ homepage: http://github.com/imperialapp/instrumental
99
+ licenses: []
100
+
101
+ post_install_message:
102
+ rdoc_options: []
103
+
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ hash: 3
112
+ segments:
113
+ - 0
114
+ version: "0"
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ hash: 3
121
+ segments:
122
+ - 0
123
+ version: "0"
124
+ requirements: []
125
+
126
+ rubyforge_project:
127
+ rubygems_version: 1.6.2
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: Rails instrumentation and client for imperialapp.com
131
+ test_files: []
132
+