fozzie 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
data/fozzie.gemspec CHANGED
@@ -17,7 +17,6 @@ Gem::Specification.new do |s|
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
19
 
20
- s.add_dependency 'statsd-ruby'
21
20
  s.add_development_dependency 'rake'
22
21
  s.add_development_dependency 'rspec'
23
22
  s.add_development_dependency 'mocha'
@@ -26,4 +25,6 @@ Gem::Specification.new do |s|
26
25
  s.add_development_dependency 'simplecov'
27
26
  s.add_development_dependency 'sinatra'
28
27
  s.add_development_dependency 'actionpack'
28
+ s.add_development_dependency 'guard'
29
+ s.add_development_dependency 'guard-rspec'
29
30
  end
@@ -1,39 +1,89 @@
1
- require 'statsd'
2
-
3
1
  module Fozzie
4
2
  module Classes
5
3
 
6
- class AbstractFozzie < Statsd
4
+ class AbstractFozzie
5
+
6
+ RESERVED_CHARS_REGEX = /[\:\|\@]/
7
7
 
8
8
  attr_reader :prefix, :configuration
9
9
 
10
- def initialize
11
- @namespace = Fozzie.c.data_prefix
12
- super Fozzie.c.host, Fozzie.c.port
10
+ # Sends an increment (count = 1) for the given stat to the statsd server.
11
+ #
12
+ # @param stat (see #count)
13
+ # @param sample_rate (see #count)
14
+ # @see #count
15
+ def increment(stat, sample_rate=1)
16
+ count(stat, 1, sample_rate)
17
+ end
18
+
19
+ # Sends a decrement (count = -1) for the given stat to the statsd server.
20
+ #
21
+ # @param stat (see #count)
22
+ # @param sample_rate (see #count)
23
+ # @see #count
24
+ def decrement(stat, sample_rate=1)
25
+ count(stat, -1, sample_rate)
26
+ end
27
+
28
+ # Sends an arbitrary count for the given stat to the statsd server.
29
+ #
30
+ # @param [String] stat stat name
31
+ # @param [Integer] count count
32
+ # @param [Integer] sample_rate sample rate, 1 for always
33
+ def count(stat, count, sample_rate=1)
34
+ send(stat, count, 'c', sample_rate)
35
+ end
36
+
37
+ # Sends a timing (in ms) for the given stat to the statsd server. The
38
+ # sample_rate determines what percentage of the time this report is sent. The
39
+ # statsd server then uses the sample_rate to correctly track the average
40
+ # timing for the stat.
41
+ #
42
+ # @param stat stat name
43
+ # @param [Integer] ms timing in milliseconds
44
+ # @param [Integer] sample_rate sample rate, 1 for always
45
+ def timing(stat, ms, sample_rate=1)
46
+ send(stat, ms, 'ms', sample_rate)
47
+ end
48
+
49
+ # Reports execution time of the provided block using {#timing}.
50
+ #
51
+ # @param stat (see #timing)
52
+ # @param sample_rate (see #timing)
53
+ # @yield The operation to be timed
54
+ # @see #timing
55
+ # @example Report the time (in ms) taken to activate an account
56
+ # $statsd.time('account.activate') { @account.activate! }
57
+ def time(stat, sample_rate=1)
58
+ stat = stat.flatten.join('.') if stat.kind_of?(Array)
59
+ start = Time.now
60
+ result = yield
61
+ timing(stat, ((Time.now - start) * 1000).round, sample_rate)
62
+ result
63
+ end
13
64
 
14
- self
65
+ def time_to_do(stat, sample_rate=1, &block)
66
+ time_for(stat, sample_rate, &block)
15
67
  end
16
68
 
17
- def time_to_do(stat, sample_rate=1, &block); time_for(stat, sample_rate, &block); end
18
69
  def time_for(stat, sample_rate=1, &block)
19
- stat = stat.flatten.join('.') if stat.kind_of?(Array)
20
70
  time(stat, sample_rate, &block)
21
71
  end
22
72
 
23
- def committed; commit; end
24
73
  def commit
25
74
  event :commit
26
75
  end
76
+ def committed; commit; end
27
77
 
28
- def build; built; end
29
78
  def built
30
79
  event :build
31
80
  end
81
+ def build; built; end
32
82
 
33
- def deploy(app = nil); deployed(app); end
34
83
  def deployed(app = nil)
35
84
  event :deploy, app
36
85
  end
86
+ def deploy(app = nil); deployed(app); end
37
87
 
38
88
  def increment_on(stat, perf, sample_rate=1)
39
89
  key = "#{stat}.%s" % (perf ? "success" : "fail")
@@ -41,6 +91,14 @@ module Fozzie
41
91
  perf
42
92
  end
43
93
 
94
+ def logger
95
+ self.class.logger
96
+ end
97
+
98
+ def self.logger
99
+ @logger
100
+ end
101
+
44
102
  private
45
103
 
46
104
  def event(type, app = nil)
@@ -50,18 +108,30 @@ module Fozzie
50
108
  end
51
109
 
52
110
  def send_to_socket(message)
111
+ return false if Fozzie.c.ip_from_host.blank?
53
112
  begin
54
- ip = Fozzie.c.ip_from_host
55
- raise RuntimeError, "Could not locate IP" unless ip
56
-
57
113
  self.class.logger.debug {"Statsd: #{message}"} if self.class.logger
58
- socket.send(message, 0, ip, Fozzie.c.port)
59
- rescue SocketError, RuntimeError => exc
114
+ socket.send(message, 0, Fozzie.c.ip_from_host, Fozzie.c.port)
115
+ rescue SocketError, RuntimeError, Errno::EADDRNOTAVAIL, Timeout::Error => exc
60
116
  self.class.logger.debug {"Statsd Failure: #{exc.message}"} if self.class.logger
61
117
  nil
62
118
  end
63
119
  end
64
120
 
121
+ def sampled(sample_rate)
122
+ yield unless sample_rate < 1 and rand > sample_rate
123
+ end
124
+
125
+ def send(stat, delta, type, sample_rate)
126
+ prefix = "#{Fozzie.c.data_prefix}." unless Fozzie.c.data_prefix.nil?
127
+ stat = stat.to_s.gsub('::', '.').gsub(RESERVED_CHARS_REGEX, '_')
128
+ sampled(sample_rate) { send_to_socket("#{prefix}#{stat}:#{delta}|#{type}#{'|@' << sample_rate.to_s if sample_rate < 1}") }
129
+ end
130
+
131
+ def socket
132
+ @socket ||= UDPSocket.new
133
+ end
134
+
65
135
  end
66
136
 
67
137
  def self.included(klass)
@@ -1,5 +1,6 @@
1
1
  require 'core_ext/hash'
2
2
  require 'resolv'
3
+ require 'timeout'
3
4
 
4
5
  module Fozzie
5
6
 
@@ -7,11 +8,12 @@ module Fozzie
7
8
  # that will be used within the Fozzie codebase.
8
9
  class Configuration
9
10
 
10
- attr_accessor :env, :config_path, :host, :port, :appname, :namespaces
11
+ attr_accessor :env, :config_path, :host, :port, :appname, :namespaces, :timeout
11
12
 
12
13
  def initialize(args = {})
13
14
  merge_and_assign_config(args)
14
-
15
+ self.ip_from_host
16
+ self.origin_name
15
17
  self
16
18
  end
17
19
 
@@ -50,14 +52,19 @@ module Fozzie
50
52
  :config_path => '',
51
53
  :env => (ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'),
52
54
  :appname => '',
53
- :namespaces => %w{Stats S Statistics Warehouse}
55
+ :namespaces => %w{Stats S Statistics Warehouse},
56
+ :timeout => 5
54
57
  }.dup
55
58
  end
56
59
 
57
60
  def host_to_ip
58
61
  return self.host unless self.host.match(ip_address_regex).nil?
59
- ips = Resolv.getaddresses(self.host)
60
- ips.compact.reject {|ip| ip.to_s.match(ip_address_regex).nil? }.first unless ips.nil?
62
+ ips = begin
63
+ Timeout.timeout(self.timeout) { Resolv.getaddresses(self.host) }
64
+ rescue Timeout::Error => exc
65
+ []
66
+ end
67
+ (ips.empty? ? "" : ips.compact.reject {|ip| ip.to_s.match(ip_address_regex).nil? }.first || "")
61
68
  end
62
69
 
63
70
  def ip_address_regex
@@ -11,8 +11,8 @@ module Fozzie
11
11
  begin
12
12
  routing = (rails_version == 3 ? ::Rails.application.routes : ::ActionController::Routing::Routes)
13
13
  path = routing.recognize_path(path_str)
14
-
15
- [path[:controller], path[:action], "render"].join('.')
14
+ stat = [path[:controller], path[:action], "render"].join('.')
15
+ stat
16
16
  rescue ActionController::RoutingError => exc
17
17
  S.increment "routing.error"
18
18
  nil
@@ -1,3 +1,3 @@
1
1
  module Fozzie
2
- VERSION = "0.0.13"
2
+ VERSION = "0.0.14"
3
3
  end
@@ -59,11 +59,10 @@ describe Fozzie::Configuration do
59
59
  end
60
60
 
61
61
  it "assigns nil on miss" do
62
- Resolv.expects(:getaddresses).with('some.awesome.log.server').returns([]).twice
63
-
62
+ Resolv.expects(:getaddresses).with('some.awesome.log.server').returns([])
64
63
  c = Fozzie::Configuration.new({:env => 'test', :config_path => nil, :host => 'some.awesome.log.server'})
65
- c.ip_from_host.should == nil
66
- c.ip_from_host.should == nil
64
+ c.ip_from_host.should == ""
65
+ c.ip_from_host.should == ""
67
66
  end
68
67
 
69
68
  it "looks up ip from host" do
@@ -74,7 +73,13 @@ describe Fozzie::Configuration do
74
73
  it "caches the ip once it is retrieved" do
75
74
  Resolv.expects(:getaddresses).with('lonelyplanet.com').returns(["1.1.1.1"])
76
75
  c = Fozzie::Configuration.new({:env => 'test', :config_path => nil, :host => 'lonelyplanet.com'})
77
- c.ip_from_host.should == c.ip_from_host
76
+ c.ip_from_host.should == "1.1.1.1"
77
+ end
78
+
79
+ it "raises Timeout on slow lookup" do
80
+ Resolv.stubs(:getaddresses).with('lonelyplanet.com') {|val| sleep 0.6; [] }
81
+ c = Fozzie::Configuration.new(:env => 'test', :config_path => nil, :host => 'lonelyplanet.com', :timeout => 0.5)
82
+ c.ip_from_host.should == ""
78
83
  end
79
84
 
80
85
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fozzie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.0.14
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-14 00:00:00.000000000 Z
12
+ date: 2012-03-02 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: statsd-ruby
16
- requirement: &70101336334120 !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: *70101336334120
25
14
  - !ruby/object:Gem::Dependency
26
15
  name: rake
27
- requirement: &70101336333380 !ruby/object:Gem::Requirement
16
+ requirement: &70330128630360 !ruby/object:Gem::Requirement
28
17
  none: false
29
18
  requirements:
30
19
  - - ! '>='
@@ -32,10 +21,10 @@ dependencies:
32
21
  version: '0'
33
22
  type: :development
34
23
  prerelease: false
35
- version_requirements: *70101336333380
24
+ version_requirements: *70330128630360
36
25
  - !ruby/object:Gem::Dependency
37
26
  name: rspec
38
- requirement: &70101336332560 !ruby/object:Gem::Requirement
27
+ requirement: &70330128629920 !ruby/object:Gem::Requirement
39
28
  none: false
40
29
  requirements:
41
30
  - - ! '>='
@@ -43,10 +32,10 @@ dependencies:
43
32
  version: '0'
44
33
  type: :development
45
34
  prerelease: false
46
- version_requirements: *70101336332560
35
+ version_requirements: *70330128629920
47
36
  - !ruby/object:Gem::Dependency
48
37
  name: mocha
49
- requirement: &70101336331840 !ruby/object:Gem::Requirement
38
+ requirement: &70330128629460 !ruby/object:Gem::Requirement
50
39
  none: false
51
40
  requirements:
52
41
  - - ! '>='
@@ -54,10 +43,10 @@ dependencies:
54
43
  version: '0'
55
44
  type: :development
56
45
  prerelease: false
57
- version_requirements: *70101336331840
46
+ version_requirements: *70330128629460
58
47
  - !ruby/object:Gem::Dependency
59
48
  name: syntax
60
- requirement: &70101336496260 !ruby/object:Gem::Requirement
49
+ requirement: &70330128629020 !ruby/object:Gem::Requirement
61
50
  none: false
62
51
  requirements:
63
52
  - - ! '>='
@@ -65,10 +54,10 @@ dependencies:
65
54
  version: '0'
66
55
  type: :development
67
56
  prerelease: false
68
- version_requirements: *70101336496260
57
+ version_requirements: *70330128629020
69
58
  - !ruby/object:Gem::Dependency
70
59
  name: rack-test
71
- requirement: &70101336495340 !ruby/object:Gem::Requirement
60
+ requirement: &70330128628580 !ruby/object:Gem::Requirement
72
61
  none: false
73
62
  requirements:
74
63
  - - ! '>='
@@ -76,10 +65,10 @@ dependencies:
76
65
  version: '0'
77
66
  type: :development
78
67
  prerelease: false
79
- version_requirements: *70101336495340
68
+ version_requirements: *70330128628580
80
69
  - !ruby/object:Gem::Dependency
81
70
  name: simplecov
82
- requirement: &70101336494540 !ruby/object:Gem::Requirement
71
+ requirement: &70330128628160 !ruby/object:Gem::Requirement
83
72
  none: false
84
73
  requirements:
85
74
  - - ! '>='
@@ -87,10 +76,10 @@ dependencies:
87
76
  version: '0'
88
77
  type: :development
89
78
  prerelease: false
90
- version_requirements: *70101336494540
79
+ version_requirements: *70330128628160
91
80
  - !ruby/object:Gem::Dependency
92
81
  name: sinatra
93
- requirement: &70101336493560 !ruby/object:Gem::Requirement
82
+ requirement: &70330128627720 !ruby/object:Gem::Requirement
94
83
  none: false
95
84
  requirements:
96
85
  - - ! '>='
@@ -98,10 +87,32 @@ dependencies:
98
87
  version: '0'
99
88
  type: :development
100
89
  prerelease: false
101
- version_requirements: *70101336493560
90
+ version_requirements: *70330128627720
102
91
  - !ruby/object:Gem::Dependency
103
92
  name: actionpack
104
- requirement: &70101336492460 !ruby/object:Gem::Requirement
93
+ requirement: &70330128627260 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *70330128627260
102
+ - !ruby/object:Gem::Dependency
103
+ name: guard
104
+ requirement: &70330128626840 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: *70330128626840
113
+ - !ruby/object:Gem::Dependency
114
+ name: guard-rspec
115
+ requirement: &70330128626400 !ruby/object:Gem::Requirement
105
116
  none: false
106
117
  requirements:
107
118
  - - ! '>='
@@ -109,7 +120,7 @@ dependencies:
109
120
  version: '0'
110
121
  type: :development
111
122
  prerelease: false
112
- version_requirements: *70101336492460
123
+ version_requirements: *70330128626400
113
124
  description: Gem allows statistics gathering from Ruby and Ruby on Rails applications
114
125
  to Statsd
115
126
  email:
@@ -121,6 +132,7 @@ files:
121
132
  - .gitignore
122
133
  - .rvmrc
123
134
  - Gemfile
135
+ - Guardfile
124
136
  - README.md
125
137
  - Rakefile
126
138
  - fozzie.gemspec
@@ -156,7 +168,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
156
168
  version: '0'
157
169
  segments:
158
170
  - 0
159
- hash: 2372667692060957828
171
+ hash: -2167407767466603242
160
172
  required_rubygems_version: !ruby/object:Gem::Requirement
161
173
  none: false
162
174
  requirements:
@@ -165,7 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
177
  version: '0'
166
178
  segments:
167
179
  - 0
168
- hash: 2372667692060957828
180
+ hash: -2167407767466603242
169
181
  requirements: []
170
182
  rubyforge_project: fozzie
171
183
  rubygems_version: 1.8.10