errplane 0.4.12 → 0.5.0
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/README.md +1 -1
- data/Rakefile +0 -1
- data/lib/errplane.rb +35 -3
- data/lib/errplane/black_box.rb +1 -1
- data/lib/errplane/configuration.rb +6 -0
- data/lib/errplane/instrumentation.rb +101 -0
- data/lib/errplane/rails/air_traffic_controller.rb +5 -1
- data/lib/errplane/railtie.rb +14 -2
- data/lib/errplane/transmitter.rb +4 -0
- data/lib/errplane/version.rb +1 -1
- data/spec/spec_helper.rb +0 -1
- metadata +25 -24
data/README.md
CHANGED
|
@@ -21,7 +21,7 @@ Start by adding the gem to your Gemfile:
|
|
|
21
21
|
Then, issue the following commands in your application's root directory:
|
|
22
22
|
|
|
23
23
|
bundle
|
|
24
|
-
rails g errplane
|
|
24
|
+
rails g errplane your-api-key-goes-here
|
|
25
25
|
|
|
26
26
|
This will create `config/initializers/errplane.rb` for you automatically. If you want to make sure that everything's working correctly, just run:
|
|
27
27
|
|
data/Rakefile
CHANGED
data/lib/errplane.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
1
|
+
require "net/http"
|
|
2
|
+
require "net/https"
|
|
3
|
+
require "rubygems"
|
|
4
|
+
require "socket"
|
|
4
5
|
|
|
5
6
|
require "json" unless Hash.respond_to?(:to_json)
|
|
6
7
|
|
|
@@ -30,6 +31,32 @@ module Errplane
|
|
|
30
31
|
@configuration ||= Configuration.new
|
|
31
32
|
end
|
|
32
33
|
|
|
34
|
+
def report(name, params = {})
|
|
35
|
+
Errplane::Relay.queue.push({
|
|
36
|
+
:name => name,
|
|
37
|
+
:source => "custom",
|
|
38
|
+
:timestamp => current_timestamp
|
|
39
|
+
}.merge(params))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def heartbeat(name, interval)
|
|
43
|
+
log :debug, "Starting heartbeat '#{name}' on a #{interval} second interval."
|
|
44
|
+
Thread.new do
|
|
45
|
+
while true do
|
|
46
|
+
log :debug, "Sleeping '#{name}' for #{interval} seconds."
|
|
47
|
+
sleep(interval)
|
|
48
|
+
report(name)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def time(name = nil)
|
|
54
|
+
start_time = Time.now
|
|
55
|
+
yield
|
|
56
|
+
elapsed_time = Time.now - start_time
|
|
57
|
+
report("timed_blocks/#{(name || Socket.gethostname)}", :value => (elapsed_time*1000).ceil)
|
|
58
|
+
end
|
|
59
|
+
|
|
33
60
|
def transmit_unless_ignorable(e, env)
|
|
34
61
|
begin
|
|
35
62
|
black_box = assemble_black_box_for(e, env)
|
|
@@ -61,6 +88,10 @@ module Errplane
|
|
|
61
88
|
end
|
|
62
89
|
end
|
|
63
90
|
|
|
91
|
+
def current_timestamp
|
|
92
|
+
Time.now.utc.to_i
|
|
93
|
+
end
|
|
94
|
+
|
|
64
95
|
def ignorable_exception?(e)
|
|
65
96
|
configuration.ignore_current_environment? || configuration.ignored_exceptions.include?(e.class.to_s)
|
|
66
97
|
end
|
|
@@ -95,4 +126,5 @@ module Errplane
|
|
|
95
126
|
end
|
|
96
127
|
end
|
|
97
128
|
|
|
129
|
+
require "errplane/instrumentation"
|
|
98
130
|
require "errplane/sinatra" if defined?(Sinatra::Request)
|
data/lib/errplane/black_box.rb
CHANGED
|
@@ -40,7 +40,7 @@ module Errplane
|
|
|
40
40
|
|
|
41
41
|
Errplane.configuration.add_custom_exception_data(self)
|
|
42
42
|
|
|
43
|
-
payload[:request_data] = request_data if @controller || @action ||
|
|
43
|
+
payload[:request_data] = request_data if @controller || @action || !@params.blank?
|
|
44
44
|
payload[:hash] = hash if hash
|
|
45
45
|
|
|
46
46
|
payload.to_json
|
|
@@ -20,6 +20,7 @@ module Errplane
|
|
|
20
20
|
|
|
21
21
|
attr_accessor :environment_variables
|
|
22
22
|
|
|
23
|
+
attr_accessor :instrumentation_enabled
|
|
23
24
|
attr_accessor :debug
|
|
24
25
|
attr_accessor :reraise_global_exceptions
|
|
25
26
|
|
|
@@ -54,12 +55,17 @@ module Errplane
|
|
|
54
55
|
@backtrace_filters = DEFAULTS[:backtrace_filters].dup
|
|
55
56
|
@debug = false
|
|
56
57
|
@rescue_global_exceptions = false
|
|
58
|
+
@instrumentation_enabled = true
|
|
57
59
|
end
|
|
58
60
|
|
|
59
61
|
def debug?
|
|
60
62
|
!!@debug
|
|
61
63
|
end
|
|
62
64
|
|
|
65
|
+
def instrumentation_enabled?
|
|
66
|
+
!!@instrumentation_enabled
|
|
67
|
+
end
|
|
68
|
+
|
|
63
69
|
def reraise_global_exceptions?
|
|
64
70
|
!!@reraise_global_exceptions
|
|
65
71
|
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
require "net/http"
|
|
3
|
+
require "uri"
|
|
4
|
+
require "base64"
|
|
5
|
+
|
|
6
|
+
module Errplane
|
|
7
|
+
class Relay
|
|
8
|
+
@@queue = Queue.new
|
|
9
|
+
|
|
10
|
+
def self.queue
|
|
11
|
+
return @@queue
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.initialize
|
|
15
|
+
@@queue = Queue.new
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class Instrumentation
|
|
20
|
+
class << self
|
|
21
|
+
include Errplane::Logger
|
|
22
|
+
|
|
23
|
+
def indent_lines(lines, num)
|
|
24
|
+
lines.split("\n").map {|line| (" " * num) + line}.join("\n")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def post_data(data)
|
|
28
|
+
if Errplane.configuration.ignore_current_environment?
|
|
29
|
+
log :debug, "Current environment is ignored, skipping POST."
|
|
30
|
+
else
|
|
31
|
+
log :info, "Posting data:\n#{indent_lines(data, 13)}"
|
|
32
|
+
http = Net::HTTP.new("api1.errplane.com", "8086")
|
|
33
|
+
url = "/api/v2/time_series/applications/#{Errplane.configuration.application_id}/environments/#{Errplane.configuration.rails_environment}?api_key=ignored"
|
|
34
|
+
response = http.post(url, data)
|
|
35
|
+
log :info, "Posting to: #{url}"
|
|
36
|
+
log :info, "Response code: #{response.code}"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def spawn_thread()
|
|
41
|
+
Thread.new do
|
|
42
|
+
log :debug, "Spawning background thread."
|
|
43
|
+
while true
|
|
44
|
+
log :debug, "Checking background queue."
|
|
45
|
+
sleep 5
|
|
46
|
+
begin
|
|
47
|
+
data = [].tap do |line|
|
|
48
|
+
while !Errplane::Relay.queue.empty?
|
|
49
|
+
log :debug, "Found data in the queue."
|
|
50
|
+
n = Errplane::Relay.queue.pop
|
|
51
|
+
|
|
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 }"
|
|
60
|
+
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
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
post_data(data.join("\n")) unless data.empty?
|
|
69
|
+
rescue => e
|
|
70
|
+
log :info, "Instrumentation Error! #{e.inspect}"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
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
|
+
end
|
|
@@ -2,8 +2,12 @@ module Errplane
|
|
|
2
2
|
module Rails
|
|
3
3
|
module AirTrafficController
|
|
4
4
|
def errplane_request_data
|
|
5
|
+
use_params = params.to_hash
|
|
6
|
+
if respond_to?(:filter_parameters)
|
|
7
|
+
use_params = filter_parameters(use_params)
|
|
8
|
+
end
|
|
5
9
|
{
|
|
6
|
-
:params =>
|
|
10
|
+
:params => use_params,
|
|
7
11
|
:session_data => errplane_session_data,
|
|
8
12
|
:controller => params[:controller],
|
|
9
13
|
:action => params[:action],
|
data/lib/errplane/railtie.rb
CHANGED
|
@@ -42,7 +42,13 @@ module Errplane
|
|
|
42
42
|
response = ::Rails.application.call(env)
|
|
43
43
|
|
|
44
44
|
if response.try(:first) == 500
|
|
45
|
-
|
|
45
|
+
if Errplane.transmitter.last_response.nil?
|
|
46
|
+
puts "Uh oh. Your app threw an exception, but we didn't get a response. Check your network connection and try again."
|
|
47
|
+
elsif Errplane.transmitter.last_response.code == "201"
|
|
48
|
+
puts "Done. Check your email or http://errplane.com for the exception notice."
|
|
49
|
+
else
|
|
50
|
+
puts "That didn't work. The Errplane API said: #{Errplane.transmitter.last_response.body}"
|
|
51
|
+
end
|
|
46
52
|
else
|
|
47
53
|
puts "Request failed: #{response}"
|
|
48
54
|
|
|
@@ -51,7 +57,13 @@ module Errplane
|
|
|
51
57
|
response = ::Rails.application.call(env)
|
|
52
58
|
|
|
53
59
|
if response.try(:first) == 500
|
|
54
|
-
|
|
60
|
+
if Errplane.transmitter.last_response.nil?
|
|
61
|
+
puts "Uh oh. Your app threw an exception, but we didn't get a response. Check your network connection and try again."
|
|
62
|
+
elsif Errplane.transmitter.last_response.code == "201"
|
|
63
|
+
puts "Done. Check your email or http://errplane.com for the exception notice."
|
|
64
|
+
else
|
|
65
|
+
puts "That didn't work. The Errplane API said: #{Errplane.transmitter.last_response.body}"
|
|
66
|
+
end
|
|
55
67
|
else
|
|
56
68
|
puts "Request failed: #{response}"
|
|
57
69
|
puts "We didn't get the exception we were expecting. Contact support@errplane.com and send them all of this output."
|
data/lib/errplane/transmitter.rb
CHANGED
|
@@ -2,6 +2,8 @@ module Errplane
|
|
|
2
2
|
class Transmitter
|
|
3
3
|
include Errplane::Logger
|
|
4
4
|
|
|
5
|
+
attr_reader :last_response
|
|
6
|
+
|
|
5
7
|
HTTP_ERRORS = [ EOFError,
|
|
6
8
|
Errno::ECONNREFUSED,
|
|
7
9
|
Errno::ECONNRESET,
|
|
@@ -12,6 +14,7 @@ module Errplane
|
|
|
12
14
|
Timeout::Error ].freeze
|
|
13
15
|
|
|
14
16
|
def initialize(params = {})
|
|
17
|
+
@last_response = nil
|
|
15
18
|
end
|
|
16
19
|
|
|
17
20
|
def relay(black_box, deployment = false)
|
|
@@ -26,6 +29,7 @@ module Errplane
|
|
|
26
29
|
log :error, "HTTP error contacting Errplane API! #{e.class}: #{e.message}"
|
|
27
30
|
end
|
|
28
31
|
|
|
32
|
+
@last_response = response
|
|
29
33
|
if response.is_a?(Net::HTTPSuccess)
|
|
30
34
|
log :info, "Request Succeeded: #{response.inspect}"
|
|
31
35
|
else
|
data/lib/errplane/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
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.
|
|
4
|
+
version: 0.5.0
|
|
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-
|
|
12
|
+
date: 2012-11-02 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: json
|
|
16
|
-
requirement: &
|
|
16
|
+
requirement: &70165371262220 !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: *
|
|
24
|
+
version_requirements: *70165371262220
|
|
25
25
|
- !ruby/object:Gem::Dependency
|
|
26
26
|
name: activesupport
|
|
27
|
-
requirement: &
|
|
27
|
+
requirement: &70165371261120 !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: *
|
|
35
|
+
version_requirements: *70165371261120
|
|
36
36
|
- !ruby/object:Gem::Dependency
|
|
37
37
|
name: actionpack
|
|
38
|
-
requirement: &
|
|
38
|
+
requirement: &70165371260600 !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: *
|
|
46
|
+
version_requirements: *70165371260600
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
48
|
name: bundler
|
|
49
|
-
requirement: &
|
|
49
|
+
requirement: &70165371259960 !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: *
|
|
57
|
+
version_requirements: *70165371259960
|
|
58
58
|
- !ruby/object:Gem::Dependency
|
|
59
59
|
name: fakeweb
|
|
60
|
-
requirement: &
|
|
60
|
+
requirement: &70165371259200 !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: *
|
|
68
|
+
version_requirements: *70165371259200
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: guard
|
|
71
|
-
requirement: &
|
|
71
|
+
requirement: &70165371258360 !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: *
|
|
79
|
+
version_requirements: *70165371258360
|
|
80
80
|
- !ruby/object:Gem::Dependency
|
|
81
81
|
name: guard-rspec
|
|
82
|
-
requirement: &
|
|
82
|
+
requirement: &70165371257800 !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: *
|
|
90
|
+
version_requirements: *70165371257800
|
|
91
91
|
- !ruby/object:Gem::Dependency
|
|
92
92
|
name: rake
|
|
93
|
-
requirement: &
|
|
93
|
+
requirement: &70165371257320 !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: *
|
|
101
|
+
version_requirements: *70165371257320
|
|
102
102
|
- !ruby/object:Gem::Dependency
|
|
103
103
|
name: rdoc
|
|
104
|
-
requirement: &
|
|
104
|
+
requirement: &70165371256800 !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: *
|
|
112
|
+
version_requirements: *70165371256800
|
|
113
113
|
- !ruby/object:Gem::Dependency
|
|
114
114
|
name: rspec
|
|
115
|
-
requirement: &
|
|
115
|
+
requirement: &70165371256240 !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: *
|
|
123
|
+
version_requirements: *70165371256240
|
|
124
124
|
- !ruby/object:Gem::Dependency
|
|
125
125
|
name: tzinfo
|
|
126
|
-
requirement: &
|
|
126
|
+
requirement: &70165371255740 !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: *
|
|
134
|
+
version_requirements: *70165371255740
|
|
135
135
|
description: This gem provides exception reporting with Errplane for Rails 3.x applications.
|
|
136
136
|
email:
|
|
137
137
|
- todd@errplane.com
|
|
@@ -159,6 +159,7 @@ files:
|
|
|
159
159
|
- lib/errplane/capistrano.rb
|
|
160
160
|
- lib/errplane/configuration.rb
|
|
161
161
|
- lib/errplane/errplane_chef_handler.rb
|
|
162
|
+
- lib/errplane/instrumentation.rb
|
|
162
163
|
- lib/errplane/logger.rb
|
|
163
164
|
- lib/errplane/rack.rb
|
|
164
165
|
- lib/errplane/rails.rb
|