errplane 0.5.4 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/errplane.rb CHANGED
@@ -65,7 +65,7 @@ module Errplane
65
65
  log :info, "Ignorable Exception? #{ignorable_exception?(e)}"
66
66
  log :info, "Environment: #{ENV.to_hash}"
67
67
 
68
- transmitter.relay(black_box) unless ignorable_exception?(e)
68
+ transmitter.enqueue(black_box) unless ignorable_exception?(e)
69
69
  rescue => e
70
70
  log :info, "[Errplane] Something went terribly wrong. Exception failed to take off! #{e.class}: #{e.message}"
71
71
  end
@@ -82,7 +82,7 @@ module Errplane
82
82
  log :info, "Transmitter: #{transmitter.inspect}"
83
83
  log :info, "Black Box: #{black_box.to_json}"
84
84
  log :info, "Environment: #{ENV.to_hash}"
85
- transmitter.relay(black_box)
85
+ transmitter.enqueue(black_box)
86
86
  rescue => e
87
87
  log :info, "[Errplane] Something went terribly wrong. Exception failed to take off! #{e.class}: #{e.message}"
88
88
  end
@@ -24,6 +24,12 @@ module Errplane
24
24
  attr_accessor :debug
25
25
  attr_accessor :reraise_global_exceptions
26
26
 
27
+ attr_accessor :queue_worker_threads
28
+ attr_accessor :queue_worker_polling_interval
29
+ attr_accessor :queue_sweeper_polling_interval
30
+ attr_accessor :queue_maximum_depth
31
+ attr_accessor :queue_maximum_post
32
+
27
33
  DEFAULTS = {
28
34
  :api_host => "api.errplane.com",
29
35
  :app_host => "app.errplane.com",
@@ -56,6 +62,11 @@ module Errplane
56
62
  @debug = false
57
63
  @rescue_global_exceptions = false
58
64
  @instrumentation_enabled = true
65
+ @queue_worker_threads = 3
66
+ @queue_worker_polling_interval = 5
67
+ @queue_sweeper_polling_interval = 0.25
68
+ @queue_maximum_depth = 10_000
69
+ @queue_maximum_post = 500
59
70
  end
60
71
 
61
72
  def debug?
@@ -29,73 +29,78 @@ module Errplane
29
29
  log :debug, "Current environment is ignored, skipping POST."
30
30
  else
31
31
  log :info, "Posting data:\n#{indent_lines(data, 13)}"
32
- http = Net::HTTP.new("api1.errplane.com", "8086")
33
32
  url = "/api/v2/time_series/applications/#{Errplane.configuration.application_id}/environments/#{Errplane.configuration.rails_environment}?api_key=#{Errplane.configuration.api_key}"
34
- response = http.post(url, data)
35
33
  log :info, "Posting to: #{url}"
36
- log :info, "Response code: #{response.code}"
34
+
35
+ retry_count = 5
36
+ begin
37
+ http = Net::HTTP.new("api.errplane.com", "80")
38
+ response = http.post(url, data)
39
+ log :info, "Response code: #{response.code}"
40
+ rescue => e
41
+ retry_count -= 1
42
+ unless retry_count.zero?
43
+ log :info, "POST failed, retrying."
44
+ sleep 10
45
+ retry
46
+ end
47
+ log :info, "Unable to POST after retrying, aborting!"
48
+ end
37
49
  end
38
50
  end
39
51
 
40
- def spawn_thread()
52
+ def spawn_sweeper_thread()
53
+ log :debug, "Spawning background sweeper thread."
41
54
  Thread.new do
42
- log :debug, "Spawning background thread."
43
55
  while true
44
- log :debug, "Checking background queue."
45
- sleep 5
46
- begin
56
+ sleep Errplane.configuration.queue_sweeper_polling_interval
57
+ while Errplane::Relay.queue.size > Errplane.configuration.queue_maximum_depth
58
+ Errplane::Relay.queue.pop
59
+ end
60
+ end
61
+ end
62
+ end
63
+ def spawn_worker_threads()
64
+ Errplane.configuration.queue_worker_threads.times do
65
+ log :debug, "Spawning background worker thread."
66
+ Thread.new do
67
+ while true
68
+ log :debug, "Checking background queue."
69
+ sleep Errplane.configuration.queue_worker_polling_interval
70
+
47
71
  data = [].tap do |line|
48
72
  while !Errplane::Relay.queue.empty?
49
73
  log :debug, "Found data in the queue."
50
74
  n = Errplane::Relay.queue.pop
51
75
 
52
- case n[:source]
53
- when "active_support"
54
- case n[:name].to_s
55
- when "process_action.action_controller"
56
- timediff = n[:finish] - n[:start]
57
- line << "controllers/#{n[:payload][:controller]}/#{n[:payload][:action]} #{(timediff*1000).ceil} #{n[:finish].utc.to_i}"
58
- line << "views #{n[:payload][:view_runtime].ceil} #{n[:finish].utc.to_i }"
59
- line << "db #{n[:payload][:db_runtime].ceil} #{n[:finish].utc.to_i }"
76
+ begin
77
+ case n[:source]
78
+ when "active_support"
79
+ case n[:name].to_s
80
+ when "process_action.action_controller"
81
+ timediff = n[:finish] - n[:start]
82
+ line << "controllers/#{n[:payload][:controller]}/#{n[:payload][:action]} #{(timediff*1000).ceil} #{n[:finish].utc.to_i}"
83
+ line << "views #{n[:payload][:view_runtime].ceil} #{n[:finish].utc.to_i }"
84
+ line << "db #{n[:payload][:db_runtime].ceil} #{n[:finish].utc.to_i }"
85
+ end
86
+ when "exception"
87
+ Errplane.transmitter.deliver n[:data], n[:url]
88
+ when "custom"
89
+ s = "#{n[:name]} #{n[:value] || 1} #{n[:timestamp]}"
90
+ s << " #{Base64.encode64(n[:message])}" if n[:message]
91
+ line << s
60
92
  end
61
- when "custom"
62
- s = "#{n[:name]} #{n[:value] || 1} #{n[:timestamp]}"
63
- s << " #{Base64.encode64(n[:message])}" if n[:message]
64
- line << s
93
+ rescue => e
94
+ log :info, "Instrumentation Error! #{e.inspect}"
65
95
  end
66
96
  end
67
97
  end
98
+
68
99
  post_data(data.join("\n")) unless data.empty?
69
- rescue => e
70
- log :info, "Instrumentation Error! #{e.inspect}"
71
100
  end
72
101
  end
73
102
  end
74
103
  end
75
104
  end
76
105
  end
77
-
78
- if defined?(ActiveSupport::Notifications) #&& Errplane.configuration.instrumentation_enabled?
79
- ActiveSupport::Notifications.subscribe do |name, start, finish, id, payload|
80
- h = { :name => name,
81
- :start => start,
82
- :finish => finish,
83
- :nid => id,
84
- :payload => payload,
85
- :source => "active_support"}
86
- Errplane::Relay.queue.push h
87
- end
88
- end
89
-
90
- if defined?(PhusionPassenger)
91
- PhusionPassenger.on_event(:starting_worker_process) do |forked|
92
- if forked
93
- Errplane::Relay.initialize
94
- Errplane::Instrumentation.spawn_thread()
95
- end
96
- end
97
- else
98
- Errplane::Relay.initialize
99
- Errplane::Instrumentation.spawn_thread()
100
- end
101
106
  end
@@ -99,6 +99,32 @@ module Errplane
99
99
  require 'errplane/rails/middleware/hijack_render_exception'
100
100
  ::ActionDispatch::ShowExceptions.send(:include, Errplane::Rails::Middleware::HijackRenderException)
101
101
  end
102
+
103
+ if defined?(ActiveSupport::Notifications) && Errplane.configuration.instrumentation_enabled?
104
+ ActiveSupport::Notifications.subscribe do |name, start, finish, id, payload|
105
+ h = { :name => name,
106
+ :start => start,
107
+ :finish => finish,
108
+ :nid => id,
109
+ :payload => payload,
110
+ :source => "active_support"}
111
+ Errplane::Relay.queue.push h
112
+ end
113
+ end
114
+
115
+ if defined?(PhusionPassenger)
116
+ PhusionPassenger.on_event(:starting_worker_process) do |forked|
117
+ if forked
118
+ Errplane::Relay.initialize
119
+ Errplane::Instrumentation.spawn_worker_threads()
120
+ Errplane::Instrumentation.spawn_sweeper_thread()
121
+ end
122
+ end
123
+ else
124
+ Errplane::Relay.initialize
125
+ Errplane::Instrumentation.spawn_worker_threads()
126
+ Errplane::Instrumentation.spawn_sweeper_thread()
127
+ end
102
128
  end
103
129
  end
104
130
  end
@@ -17,6 +17,34 @@ module Errplane
17
17
  @last_response = nil
18
18
  end
19
19
 
20
+ def enqueue(black_box)
21
+ log :info, "Adding exception to the queue."
22
+ url = "/api/v1/applications/#{Errplane.configuration.application_id}/exceptions/#{Errplane.configuration.rails_environment}?api_key=#{Errplane.configuration.api_key}"
23
+ exception = { :data => black_box.to_json,
24
+ :url => url,
25
+ :source => "exception" }
26
+
27
+ Errplane::Relay.queue.push exception
28
+ end
29
+
30
+ def deliver(data, url)
31
+ http = initialize_http_connection
32
+ response = begin
33
+ log :info, "URL: #{url}"
34
+ log :info, "Data: #{data.inspect}"
35
+ http.post(url, data)
36
+ rescue *HTTP_ERRORS => e
37
+ log :error, "HTTP error contacting Errplane API! #{e.class}: #{e.message}"
38
+ end
39
+
40
+ @last_response = response
41
+ if response.is_a?(Net::HTTPSuccess)
42
+ log :info, "Exception POST Succeeded: #{response.inspect}"
43
+ else
44
+ log :error, "Exception POST Failed: #{response.inspect}"
45
+ end
46
+ end
47
+
20
48
  def relay(black_box, deployment = false)
21
49
  http = initialize_http_connection
22
50
  data = black_box.to_json
@@ -1,3 +1,3 @@
1
1
  module Errplane
2
- VERSION = "0.5.4"
2
+ VERSION = "0.5.5"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: errplane
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-08 00:00:00.000000000 Z
12
+ date: 2012-11-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &70198728405200 !ruby/object:Gem::Requirement
16
+ requirement: &70156446180960 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70198728405200
24
+ version_requirements: *70156446180960
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activesupport
27
- requirement: &70198728404600 !ruby/object:Gem::Requirement
27
+ requirement: &70156446180420 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 2.3.14
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70198728404600
35
+ version_requirements: *70156446180420
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: actionpack
38
- requirement: &70198728403960 !ruby/object:Gem::Requirement
38
+ requirement: &70156446179840 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 2.3.14
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70198728403960
46
+ version_requirements: *70156446179840
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bundler
49
- requirement: &70198728403420 !ruby/object:Gem::Requirement
49
+ requirement: &70156446174660 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.0.0
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70198728403420
57
+ version_requirements: *70156446174660
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: fakeweb
60
- requirement: &70198728402760 !ruby/object:Gem::Requirement
60
+ requirement: &70156446174100 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70198728402760
68
+ version_requirements: *70156446174100
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: guard
71
- requirement: &70198728401780 !ruby/object:Gem::Requirement
71
+ requirement: &70156446173560 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70198728401780
79
+ version_requirements: *70156446173560
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: guard-rspec
82
- requirement: &70198728400400 !ruby/object:Gem::Requirement
82
+ requirement: &70156446173020 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70198728400400
90
+ version_requirements: *70156446173020
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: rake
93
- requirement: &70198728399500 !ruby/object:Gem::Requirement
93
+ requirement: &70156446172540 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70198728399500
101
+ version_requirements: *70156446172540
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: rdoc
104
- requirement: &70198728398520 !ruby/object:Gem::Requirement
104
+ requirement: &70156446171940 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70198728398520
112
+ version_requirements: *70156446171940
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: rspec
115
- requirement: &70198728397380 !ruby/object:Gem::Requirement
115
+ requirement: &70156446171220 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: '0'
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *70198728397380
123
+ version_requirements: *70156446171220
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: tzinfo
126
- requirement: &70198728396200 !ruby/object:Gem::Requirement
126
+ requirement: &70156446170460 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ! '>='
@@ -131,7 +131,7 @@ dependencies:
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *70198728396200
134
+ version_requirements: *70156446170460
135
135
  description: This gem provides exception reporting with Errplane for Rails 3.x applications.
136
136
  email:
137
137
  - todd@errplane.com