hoover 0.0.5 → 0.0.6

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.
@@ -1,3 +1,10 @@
1
+ ## Version 0.0.6 - Oct 26, 2011
2
+
3
+ * Remove ActionView log subscriber contents (not useful to me, and triggers the loggly hash-in-array bug)
4
+ * Polish and specs for ActionController, ActiveResource, and ActionMailer log subscribers (derived from live test
5
+ against Rails 3.0.9
6
+ * Send an INFO message to main Rails logger so you can see what was sent to Loggly
7
+
1
8
  ## Version 0.0.5 - Oct 24, 2011
2
9
 
3
10
  * Sanitize hash objects coming in instead of relying on implicit to_json which sometimes crashes.
data/README.md CHANGED
@@ -17,6 +17,12 @@ If you are using Rails 3, then there are prewritten log subscribers that pass mo
17
17
  the normal rails log in a simplified and convenient JSON format.
18
18
 
19
19
 
20
+ ## Requirements
21
+
22
+ Hoover is designed to work w/ Ruby 1.8.7 or 1.9.2+ and any Rack framework. That said, it has been developed under Rails
23
+ 3.0.9 with 1.8.7. Other Rack frameworks are probably pretty rough at this point (but please send suggestions!).
24
+
25
+
20
26
  ## Installation
21
27
 
22
28
  You're using bundler right?
@@ -54,12 +60,19 @@ If you add with the same key more than once, Hoover automatically rolls it up in
54
60
 
55
61
  ## Todo
56
62
 
63
+ * Provide sensible defaults for generic Rack logging. Any ideas?
57
64
  * Provide config option to set the logglier during Rails initialization, thus guaranteeing its presence beyond what is
58
65
  possible with simple ActionController filters.
59
- * Write specs for Rails components.
60
66
  * Provide config option to choose which log subscribers to enable.
61
67
 
62
68
 
69
+ ## Known Issues
70
+
71
+ * As of this writing, Loggly's JSON API does not handle hashes nested inside arrays properly. Each hash ends up looking
72
+ like [object Object] in the search console. This totally breaks Hoover's automatic stacking of duplicate adds, but
73
+ hopefully they'll have it fixed soon.
74
+
75
+
63
76
  ## Contributing to Hoover
64
77
 
65
78
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
@@ -17,10 +17,11 @@ Gem::Specification.new do |s|
17
17
 
18
18
  s.require_paths = [%q{lib}]
19
19
 
20
- s.add_dependency "logglier", ["~> 0.2.6"]
20
+ s.add_dependency "logglier", ["~> 0.2.5"]
21
21
 
22
22
  s.add_development_dependency "bundler"
23
23
  s.add_development_dependency "rake"
24
24
  s.add_development_dependency "minitest"
25
25
  s.add_development_dependency "mocha"
26
+ s.add_development_dependency "rails", ["~> 3.1.0"]
26
27
  end
@@ -3,6 +3,12 @@ require 'hoover/job'
3
3
  require 'hoover/railtie' if defined?(Rails)
4
4
 
5
5
  module Hoover
6
+ autoload :ActionControllerLogSubscriber, 'hoover/log_subscribers/action_controller_log_subscriber'
7
+ autoload :ActionMailerLogSubscriber, 'hoover/log_subscribers/action_mailer_log_subscriber'
8
+ autoload :ActionViewLogSubscriber, 'hoover/log_subscribers/action_view_log_subscriber'
9
+ autoload :ActiveResourceLogSubscriber, 'hoover/log_subscribers/active_resource_log_subscriber'
10
+ autoload :ActiveRecordLogSubscriber, 'hoover/log_subscribers/active_record_log_subscriber'
11
+
6
12
  class << self
7
13
  def init(logglier = nil)
8
14
  self.active_job = Job.new(logglier)
@@ -25,6 +31,11 @@ module Hoover
25
31
  active_job.add(*args)
26
32
  end
27
33
 
34
+ def hash(*args)
35
+ raise "Must init Hoover before calling hash" unless active_job
36
+ active_job.hash
37
+ end
38
+
28
39
  def logglier=(logglier)
29
40
  raise "Must init Hoover before setting logglier" unless active_job
30
41
  active_job.logglier = logglier
@@ -25,6 +25,7 @@ module Hoover
25
25
  def post
26
26
  raise "cannot post until logglier is set" unless ready_to_post?
27
27
  @hash.each{ |k,v| @hash[k] = @hash[k].first if v.size == 1 }
28
+ Rails.logger.info " Hoover sending keys #{@hash.keys.inspect} to Loggly" if defined?(Rails) && Rails.logger
28
29
  @logglier.info(@hash)
29
30
  end
30
31
 
@@ -42,7 +43,7 @@ module Hoover
42
43
 
43
44
  def sanitize_object(value)
44
45
  case value
45
- when String, Fixnum, Date, Time, NilClass
46
+ when String, Fixnum, Float, Date, Time, NilClass
46
47
  value
47
48
  else
48
49
  value.to_s
@@ -1,3 +1,6 @@
1
+ require 'action_controller'
2
+ require 'active_support/core_ext/hash/except'
3
+
1
4
  module Hoover
2
5
  class ActionControllerLogSubscriber < ActiveSupport::LogSubscriber
3
6
  INTERNAL_PARAMS = %w(controller action format _method only_path)
@@ -16,26 +19,32 @@ module Hoover
16
19
  payload = event.payload
17
20
  additions = ActionController::Base.log_process_action(payload)
18
21
 
22
+ runtimes = additions.inject({}) do |hash, string|
23
+ name, time = string.split(':')
24
+ hash[name] = time.to_f
25
+ hash
26
+ end
27
+
19
28
  status = payload[:status]
20
29
  if status.nil? && payload[:exception].present?
21
30
  status = Rack::Utils.status_code(ActionDispatch::ShowExceptions.rescue_responses[payload[:exception].first]) rescue nil
22
31
  end
23
32
 
24
- Hoover.add(:status => "#{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}",
25
- :duration => "%.0f" % event.duration)
26
- Hoover.add :additions => additions.join(" | ") unless additions.blank?
33
+ Hoover.add(:status => status,
34
+ :duration => event.duration)
35
+ Hoover.add :runtimes => runtimes unless runtimes.blank?
27
36
  end
28
37
 
29
38
  def send_file(event)
30
- Hoover.add(:sent_file, "%s (%.1fms)" % [event.payload[:path], event.duration])
39
+ Hoover.add(:sent_file => { :path => event.payload[:path], :runtime => event.duration })
31
40
  end
32
41
 
33
42
  def redirect_to(event)
34
- Hoover.add(:redirected_to, event.payload[:location])
43
+ Hoover.add(:redirected_to => event.payload[:location])
35
44
  end
36
45
 
37
46
  def send_data(event)
38
- Hoover.add(:sent_data, "%s (%.1fms)" % [event.payload[:filename], event.duration])
47
+ Hoover.add(:sent_data => { :filename => event.payload[:filename], :runtime => event.duration })
39
48
  end
40
49
 
41
50
  %w(write_fragment read_fragment exist_fragment?
@@ -43,8 +52,7 @@ module Hoover
43
52
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
44
53
  def #{method}(event)
45
54
  key_or_path = event.payload[:key] || event.payload[:path]
46
- human_name = #{method.to_s.humanize.inspect}
47
- Hoover.add(method.to_sym, "\#{key_or_path} (%.1fms)" % event.duration)
55
+ Hoover.add(#{method.to_sym.inspect} => { :key => key_or_path, :runtime => event.duration })
48
56
  end
49
57
  METHOD
50
58
  end
@@ -2,8 +2,8 @@ module Hoover
2
2
  class ActionMailerLogSubscriber < ActiveSupport::LogSubscriber
3
3
  def deliver(event)
4
4
  recipients = Array.wrap(event.payload[:to])
5
- Hoover.add(:sent_mail_to, recipients)
6
- Hoover.add(:sent_mail_duration, "%1.f" % event.duration)
5
+ Hoover.add(:sent_mail_to => recipients)
6
+ Hoover.add(:sent_mail_duration => event.duration)
7
7
  end
8
8
  end
9
9
  end
@@ -1,19 +1,5 @@
1
1
  module Hoover
2
2
  class ActionViewLogSubscriber < ActiveSupport::LogSubscriber
3
- def render_template(event)
4
- rendered = { :identifier => from_rails_root(event.payload[:identifier]),
5
- :duration => event.duration }
6
- rendered[:layout] = from_rails_root(event.payload[:layout]) if event.payload[:layout]
7
-
8
- Hoover.add :rendered => rendered
9
- end
10
- alias :render_partial :render_template
11
- alias :render_collection :render_template
12
-
13
- protected
14
-
15
- def from_rails_root(string)
16
- string.sub("#{Rails.root}/", "").sub(/^app\/views\//, "")
17
- end
3
+ # I have no need to log this to Loggly, implementations welcome.
18
4
  end
19
5
  end
@@ -4,7 +4,7 @@ module Hoover
4
4
  result = event.payload[:result]
5
5
  request = { :method => event.payload[:method].to_s.upcase,
6
6
  :request_uri => event.payload[:request_uri],
7
- :result_code => result.code,
7
+ :result_code => result.code.to_i,
8
8
  :result_message => result.message,
9
9
  :result_length => result.body.to_s.length,
10
10
  :duration => event.duration }
@@ -22,6 +22,7 @@ module Hoover
22
22
  Hoover.add :method => request.request_method,
23
23
  :path => request.filtered_path
24
24
  else
25
+ # TODO: Figure out sane logging defaults for the average rack app and make this configurable
25
26
  Hoover.add env
26
27
  end
27
28
 
@@ -1,10 +1,4 @@
1
1
  module Hoover
2
- autoload :ActionControllerLogSubscriber, 'hoover/log_subscribers/action_controller_log_subscriber'
3
- autoload :ActionMailerLogSubscriber, 'hoover/log_subscribers/action_mailer_log_subscriber'
4
- autoload :ActionViewLogSubscriber, 'hoover/log_subscribers/action_view_log_subscriber'
5
- autoload :ActiveResourceLogSubscriber, 'hoover/log_subscribers/active_resource_log_subscriber'
6
- autoload :ActiveRecordLogSubscriber, 'hoover/log_subscribers/active_record_log_subscriber'
7
-
8
2
  class Railtie < Rails::Railtie
9
3
  def self.all_rails_log_subscribers
10
4
  [:action_controller, :action_mailer, :action_view, :active_resource, :active_record]
@@ -1,3 +1,3 @@
1
1
  module Hoover
2
- VERSION = '0.0.5'
2
+ VERSION = '0.0.6'
3
3
  end
@@ -0,0 +1,177 @@
1
+ require 'helper'
2
+ require 'rails'
3
+
4
+ describe Hoover::ActionControllerLogSubscriber do
5
+ before do
6
+ Hoover.init
7
+ @subscriber = Hoover::ActionControllerLogSubscriber.new
8
+ end
9
+
10
+ describe "start_processing" do
11
+ before do
12
+ @subscriber.start_processing(start_processing_stub)
13
+ end
14
+
15
+ it "sets controller" do
16
+ Hoover.hash[:controller].first.must_equal "AboutController"
17
+ end
18
+
19
+ it "sets action" do
20
+ Hoover.hash[:action].first.must_equal "index"
21
+ end
22
+
23
+ it "sets params" do
24
+ Hoover.hash[:params].first.must_equal "with_param" => "1"
25
+ end
26
+
27
+ it "sets format" do
28
+ Hoover.hash[:format].first.must_equal "HTML"
29
+ end
30
+ end
31
+
32
+ describe "process_action" do
33
+ before do
34
+ @subscriber.process_action(process_action_stub)
35
+ end
36
+
37
+ it "sets status" do
38
+ Hoover.hash[:status].first.must_equal 200
39
+ end
40
+
41
+ it "sets duration" do
42
+ Hoover.hash[:duration].first.must_equal 475.987
43
+ end
44
+
45
+ it "sets runtimes" do
46
+ Hoover.hash[:runtimes].first.must_equal "Views" => 138.4
47
+ end
48
+ end
49
+
50
+ describe "send_file" do
51
+ before do
52
+ @subscriber.send_file(send_file_stub)
53
+ end
54
+
55
+ it "sets sent_file" do
56
+ Hoover.hash[:sent_file].first.must_equal :path => '/apath', :runtime => 100.1
57
+ end
58
+ end
59
+
60
+ describe "redirect_to" do
61
+ before do
62
+ @subscriber.redirect_to(redirect_to_stub)
63
+ end
64
+
65
+ it "sets sent_file" do
66
+ Hoover.hash[:redirected_to].first.must_equal '/newlocation'
67
+ end
68
+ end
69
+
70
+ describe "send_data" do
71
+ before do
72
+ @subscriber.send_data(send_data_stub)
73
+ end
74
+
75
+ it "sets sent_data" do
76
+ Hoover.hash[:sent_data].first.must_equal :filename => 'somefile.txt', :runtime => 200.1
77
+ end
78
+ end
79
+
80
+ describe "write_fragment" do
81
+ before do
82
+ @subscriber.write_fragment(fragment_stub)
83
+ end
84
+
85
+ it "sets write_fragment" do
86
+ Hoover.hash[:write_fragment].first.must_equal :key => 'thefrag', :runtime => 123.1
87
+ end
88
+ end
89
+
90
+ describe "read_fragment" do
91
+ before do
92
+ @subscriber.read_fragment(fragment_stub)
93
+ end
94
+
95
+ it "sets read_fragment" do
96
+ Hoover.hash[:read_fragment].first.must_equal :key => 'thefrag', :runtime => 123.1
97
+ end
98
+ end
99
+
100
+ describe "exist_fragment" do
101
+ before do
102
+ @subscriber.exist_fragment?(fragment_stub)
103
+ end
104
+
105
+ it "sets exist_fragment" do
106
+ Hoover.hash[:exist_fragment?].first.must_equal :key => 'thefrag', :runtime => 123.1
107
+ end
108
+ end
109
+
110
+ describe "expire_fragment" do
111
+ before do
112
+ @subscriber.expire_fragment(fragment_stub)
113
+ end
114
+
115
+ it "sets expire_fragment" do
116
+ Hoover.hash[:expire_fragment].first.must_equal :key => 'thefrag', :runtime => 123.1
117
+ end
118
+ end
119
+
120
+ describe "expire_page" do
121
+ before do
122
+ @subscriber.expire_page(page_stub)
123
+ end
124
+
125
+ it "sets expire_page" do
126
+ Hoover.hash[:expire_page].first.must_equal :key => '/thepath', :runtime => 124.1
127
+ end
128
+ end
129
+
130
+ private
131
+
132
+ def start_processing_stub
133
+ payload = { :controller => "AboutController", :action => "index", :path => "/about?with_param=1",
134
+ :params => { "with_param" => "1", "action" => "index", "controller" => "about" },
135
+ :formats => [:html], :method=>"GET" }
136
+ duration = 0.005
137
+ stub(:payload => payload, :duration => duration)
138
+ end
139
+
140
+ def process_action_stub
141
+ payload = { :controller => "AboutController", :action => "index", :status => 200,
142
+ :params => { "with_param" => "1", "action" => "index", "controller" => "about" },
143
+ :path => "/about?with_param=1", :formats => [:html], :method => "GET",
144
+ :query_runtime => 0, :db_runtime => 4.542, :view_runtime => 138.39879927063 }
145
+ duration = 475.987
146
+ stub(:payload => payload, :duration => duration)
147
+ end
148
+
149
+ def send_file_stub
150
+ payload = { :path => '/apath' }
151
+ duration = 100.1
152
+ stub(:payload => payload, :duration => duration)
153
+ end
154
+
155
+ def redirect_to_stub
156
+ payload = { :location => '/newlocation' }
157
+ stub(:payload => payload)
158
+ end
159
+
160
+ def send_data_stub
161
+ payload = { :filename => 'somefile.txt' }
162
+ duration = 200.1
163
+ stub(:payload => payload, :duration => duration)
164
+ end
165
+
166
+ def fragment_stub
167
+ payload = { :key => 'thefrag' }
168
+ duration = 123.1
169
+ stub(:payload => payload, :duration => duration)
170
+ end
171
+
172
+ def page_stub
173
+ payload = { :path => '/thepath' }
174
+ duration = 124.1
175
+ stub(:payload => payload, :duration => duration)
176
+ end
177
+ end
@@ -0,0 +1,26 @@
1
+ require 'helper'
2
+ require 'rails'
3
+
4
+ describe Hoover::ActionMailerLogSubscriber do
5
+ before do
6
+ Hoover.init
7
+ @subscriber = Hoover::ActionMailerLogSubscriber.new
8
+ end
9
+
10
+ describe 'deliver' do
11
+ before do
12
+ @subscriber.deliver(deliver_stub)
13
+ end
14
+
15
+ it "sets sent_mail_to" do
16
+ Hoover.hash[:sent_mail_to].first.must_equal ['email@example.com']
17
+ end
18
+ end
19
+ private
20
+
21
+ def deliver_stub
22
+ payload = { :to => 'email@example.com' }
23
+ duration = 1.1
24
+ stub(:payload => payload, :duration => duration)
25
+ end
26
+ end
@@ -0,0 +1,47 @@
1
+ require 'helper'
2
+ require 'rails'
3
+
4
+ describe Hoover::ActiveResourceLogSubscriber do
5
+ before do
6
+ Hoover.init
7
+ @subscriber = Hoover::ActiveResourceLogSubscriber.new
8
+ end
9
+
10
+ describe 'request' do
11
+ before do
12
+ @subscriber.request(request_stub)
13
+ end
14
+
15
+ it "sets method" do
16
+ Hoover.hash[:active_resource_request].first[:method].must_equal 'GET'
17
+ end
18
+
19
+ it "sets request_uri" do
20
+ Hoover.hash[:active_resource_request].first[:request_uri].must_equal 'http://localhost/test.xml'
21
+ end
22
+
23
+ it "sets result_code" do
24
+ Hoover.hash[:active_resource_request].first[:result_code].must_equal 200
25
+ end
26
+
27
+ it "sets result_message" do
28
+ Hoover.hash[:active_resource_request].first[:result_message].must_equal 'OK'
29
+ end
30
+
31
+ it "sets result_length" do
32
+ Hoover.hash[:active_resource_request].first[:result_length].must_equal 4
33
+ end
34
+
35
+ it "sets duration" do
36
+ Hoover.hash[:active_resource_request].first[:duration].must_equal 21.12
37
+ end
38
+ end
39
+ private
40
+
41
+ def request_stub
42
+ result = stub(:code => '200', :message => 'OK', :body => 'body')
43
+ payload = { :method => :get, :result => result, :request_uri => "http://localhost/test.xml" }
44
+ duration = 21.12
45
+ stub(:payload => payload, :duration => duration)
46
+ end
47
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hoover
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-24 00:00:00.000000000Z
12
+ date: 2011-10-26 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: logglier
16
- requirement: &70110723980740 !ruby/object:Gem::Requirement
16
+ requirement: &70138783509820 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 0.2.6
21
+ version: 0.2.5
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70110723980740
24
+ version_requirements: *70138783509820
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &70110723980320 !ruby/object:Gem::Requirement
27
+ requirement: &70138783509400 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70110723980320
35
+ version_requirements: *70138783509400
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &70110723979860 !ruby/object:Gem::Requirement
38
+ requirement: &70138783508940 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70110723979860
46
+ version_requirements: *70138783508940
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: minitest
49
- requirement: &70110723979440 !ruby/object:Gem::Requirement
49
+ requirement: &70138783508520 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70110723979440
57
+ version_requirements: *70138783508520
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: mocha
60
- requirement: &70110723979020 !ruby/object:Gem::Requirement
60
+ requirement: &70138770853240 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,18 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70110723979020
68
+ version_requirements: *70138770853240
69
+ - !ruby/object:Gem::Dependency
70
+ name: rails
71
+ requirement: &70138770852720 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 3.1.0
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70138770852720
69
80
  description: Sets up a hash at the beginning of each request and flushes it to Loggly
70
81
  at the end of the request. Also comes with standard Rails 3 log subscribers.
71
82
  email:
@@ -93,6 +104,9 @@ files:
93
104
  - lib/hoover/rack_logger.rb
94
105
  - lib/hoover/railtie.rb
95
106
  - lib/hoover/version.rb
107
+ - spec/action_controller_log_subscrier_spec.rb
108
+ - spec/action_mailer_log_subscriber_spec.rb
109
+ - spec/active_resource_log_subscriber_spec.rb
96
110
  - spec/helper.rb
97
111
  - spec/hoover_spec.rb
98
112
  - spec/job_spec.rb
@@ -123,6 +137,9 @@ specification_version: 3
123
137
  summary: Rack-based support for collecting a single hash per request to be sent to
124
138
  Loggly
125
139
  test_files:
140
+ - spec/action_controller_log_subscrier_spec.rb
141
+ - spec/action_mailer_log_subscriber_spec.rb
142
+ - spec/active_resource_log_subscriber_spec.rb
126
143
  - spec/helper.rb
127
144
  - spec/hoover_spec.rb
128
145
  - spec/job_spec.rb