errplane 0.5.30 → 0.6.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/lib/errplane.rb +41 -48
- data/lib/errplane/api.rb +65 -0
- data/lib/errplane/capistrano.rb +3 -4
- data/lib/errplane/configuration.rb +2 -2
- data/lib/errplane/{black_box.rb → exception_presenter.rb} +34 -10
- data/lib/errplane/rails.rb +1 -1
- data/lib/errplane/railtie.rb +32 -15
- data/lib/errplane/sinatra.rb +1 -1
- data/lib/errplane/version.rb +1 -1
- data/lib/errplane/worker.rb +9 -49
- metadata +26 -29
- data/errplane-0.5.29.gem +0 -0
- data/lib/errplane/transmitter.rb +0 -76
- data/spec/unit/transmitter_spec.rb +0 -4
data/lib/errplane.rb
CHANGED
@@ -3,15 +3,16 @@ require "net/https"
|
|
3
3
|
require "rubygems"
|
4
4
|
require "socket"
|
5
5
|
require "thread"
|
6
|
+
require "base64"
|
6
7
|
|
7
8
|
require "json" unless Hash.respond_to?(:to_json)
|
8
9
|
|
9
10
|
require "errplane/version"
|
10
11
|
require "errplane/logger"
|
11
|
-
require "errplane/
|
12
|
+
require "errplane/exception_presenter"
|
12
13
|
require "errplane/max_queue"
|
13
14
|
require "errplane/configuration"
|
14
|
-
require "errplane/
|
15
|
+
require "errplane/api"
|
15
16
|
require "errplane/backtrace"
|
16
17
|
require "errplane/worker"
|
17
18
|
require "errplane/rack"
|
@@ -23,11 +24,11 @@ module Errplane
|
|
23
24
|
include Logger
|
24
25
|
|
25
26
|
attr_writer :configuration
|
26
|
-
attr_accessor :
|
27
|
+
attr_accessor :api
|
27
28
|
|
28
29
|
def configure(silent = false)
|
29
30
|
yield(configuration)
|
30
|
-
self.
|
31
|
+
self.api = Api.new
|
31
32
|
end
|
32
33
|
|
33
34
|
def configuration
|
@@ -38,28 +39,37 @@ module Errplane
|
|
38
39
|
@queue ||= MaxQueue.new(configuration.queue_maximum_depth)
|
39
40
|
end
|
40
41
|
|
41
|
-
def report(name, params = {})
|
42
|
+
def report(name, params = {}, async = true)
|
42
43
|
unless configuration.ignored_reports.find{ |msg| /#{msg}/ =~ name }
|
43
|
-
|
44
|
+
data = {
|
44
45
|
:name => name.gsub(/\s+/, "_"),
|
45
|
-
:
|
46
|
-
|
47
|
-
|
46
|
+
:timestamp => "now"
|
47
|
+
}.merge(params)
|
48
|
+
|
49
|
+
if async
|
50
|
+
Errplane.queue.push(data)
|
51
|
+
else
|
52
|
+
Errplane.api.post(Errplane.process_line(data))
|
53
|
+
end
|
48
54
|
end
|
49
55
|
end
|
50
56
|
|
57
|
+
def report_deployment(context = nil, async = false)
|
58
|
+
report("deployments", {:context => context}, async)
|
59
|
+
end
|
60
|
+
|
51
61
|
def heartbeat(name, interval)
|
52
62
|
log :debug, "Starting heartbeat '#{name}' on a #{interval} second interval."
|
53
63
|
Thread.new do
|
54
64
|
while true do
|
55
65
|
log :debug, "Sleeping '#{name}' for #{interval} seconds."
|
56
66
|
sleep(interval)
|
57
|
-
report(name)
|
67
|
+
report(name, :timestamp => "now")
|
58
68
|
end
|
59
69
|
end
|
60
70
|
end
|
61
71
|
|
62
|
-
def time(name
|
72
|
+
def time(name, params = {})
|
63
73
|
value = if block_given?
|
64
74
|
start_time = Time.now
|
65
75
|
yield
|
@@ -68,35 +78,22 @@ module Errplane
|
|
68
78
|
params[:value] || 0
|
69
79
|
end
|
70
80
|
|
71
|
-
report(
|
81
|
+
report(name, :value => value)
|
72
82
|
end
|
73
83
|
|
74
84
|
def transmit_unless_ignorable(e, env)
|
75
|
-
|
76
|
-
black_box = assemble_black_box_for(e, env)
|
77
|
-
log :info, "Transmitter: #{transmitter.inspect}"
|
78
|
-
log :info, "Black Box: #{black_box.to_json}"
|
79
|
-
log :info, "Ignorable Exception? #{ignorable_exception?(e)}"
|
80
|
-
log :info, "Environment: #{ENV.to_hash}"
|
81
|
-
|
82
|
-
transmitter.enqueue(black_box) unless ignorable_exception?(e)
|
83
|
-
rescue => e
|
84
|
-
log :info, "[Errplane] Something went terribly wrong. Exception failed to take off! #{e.class}: #{e.message}"
|
85
|
-
end
|
85
|
+
transmit(e, env) unless ignorable_exception?(e)
|
86
86
|
end
|
87
87
|
|
88
88
|
def transmit(e, env = {})
|
89
89
|
begin
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
log :info, "Black Box: #{black_box.to_json}"
|
98
|
-
log :info, "Environment: #{ENV.to_hash}"
|
99
|
-
transmitter.enqueue(black_box)
|
90
|
+
exception_presenter = ExceptionPresenter.new(e, env)
|
91
|
+
log :info, "Exception: #{exception_presenter.to_json[0..512]}..."
|
92
|
+
|
93
|
+
Errplane.queue.push({
|
94
|
+
:name => exception_presenter.time_series_name,
|
95
|
+
:context => exception_presenter
|
96
|
+
})
|
100
97
|
rescue => e
|
101
98
|
log :info, "[Errplane] Something went terribly wrong. Exception failed to take off! #{e.class}: #{e.message}"
|
102
99
|
end
|
@@ -106,8 +103,16 @@ module Errplane
|
|
106
103
|
Time.now.utc.to_i
|
107
104
|
end
|
108
105
|
|
106
|
+
def process_line(line)
|
107
|
+
data = "#{line[:name]} #{line[:value] || 1} #{line[:timestamp] || "now"}"
|
108
|
+
data = "#{data} #{Base64.strict_encode64(line[:context].to_json)}" if line[:context]
|
109
|
+
data
|
110
|
+
end
|
111
|
+
|
109
112
|
def ignorable_exception?(e)
|
110
|
-
configuration.ignore_current_environment? ||
|
113
|
+
configuration.ignore_current_environment? ||
|
114
|
+
!!configuration.ignored_exception_messages.find{ |msg| /.*#{msg}.*/ =~ e.message } ||
|
115
|
+
configuration.ignored_exceptions.include?(e.class.to_s)
|
111
116
|
end
|
112
117
|
|
113
118
|
def rescue(&block)
|
@@ -116,28 +121,16 @@ module Errplane
|
|
116
121
|
if configuration.ignore_current_environment?
|
117
122
|
raise(e)
|
118
123
|
else
|
119
|
-
transmit_unless_ignorable(e, {})
|
124
|
+
transmit_unless_ignorable(e, {}) unless ignorable_exception?(e)
|
120
125
|
end
|
121
126
|
end
|
122
127
|
|
123
128
|
def rescue_and_reraise(&block)
|
124
129
|
block.call
|
125
130
|
rescue StandardError => e
|
126
|
-
transmit_unless_ignorable(e, {})
|
131
|
+
transmit_unless_ignorable(e, {}) unless ignorable_exception?(e)
|
127
132
|
raise(e)
|
128
133
|
end
|
129
|
-
|
130
|
-
private
|
131
|
-
|
132
|
-
def assemble_black_box_for(e, opts = {})
|
133
|
-
opts ||= {}
|
134
|
-
log :info, "OPTS: #{opts}"
|
135
|
-
e = e.continued_exception if e.respond_to?(:continued_exception)
|
136
|
-
e = e.original_exception if e.respond_to?(:original_exception)
|
137
|
-
opts = opts.merge(:exception => e)
|
138
|
-
opts[:environment_variables] = ENV.to_hash
|
139
|
-
black_box = BlackBox.new(opts)
|
140
|
-
end
|
141
134
|
end
|
142
135
|
end
|
143
136
|
|
data/lib/errplane/api.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
module Errplane
|
2
|
+
class Api
|
3
|
+
include Errplane::Logger
|
4
|
+
|
5
|
+
attr_reader :last_response
|
6
|
+
|
7
|
+
POST_RETRIES = 5
|
8
|
+
READ_TIMEOUT = 3
|
9
|
+
OPEN_TIMEOUT = 3
|
10
|
+
|
11
|
+
HTTP_ERRORS = [ EOFError,
|
12
|
+
Errno::ECONNREFUSED,
|
13
|
+
Errno::ECONNRESET,
|
14
|
+
Errno::EINVAL,
|
15
|
+
Net::HTTPBadResponse,
|
16
|
+
Net::HTTPHeaderSyntaxError,
|
17
|
+
Net::ProtocolError,
|
18
|
+
Timeout::Error ].freeze
|
19
|
+
|
20
|
+
def post(data)
|
21
|
+
https = initialize_secure_connection
|
22
|
+
retry_count = POST_RETRIES
|
23
|
+
log :debug, "POSTing to #{url}"
|
24
|
+
|
25
|
+
response = begin
|
26
|
+
https.post(url, data)
|
27
|
+
rescue *HTTP_ERRORS => e
|
28
|
+
log :error, "HTTP error contacting API! #{e.class}: #{e.message}"
|
29
|
+
retry_count -= 1
|
30
|
+
unless retry_count.zero?
|
31
|
+
log :info, "Retrying failed POST..."
|
32
|
+
sleep 1
|
33
|
+
retry
|
34
|
+
end
|
35
|
+
log :info, "Unable to POST after #{POST_RETRIES} attempts. Aborting!"
|
36
|
+
end
|
37
|
+
|
38
|
+
if response.is_a?(Net::HTTPSuccess)
|
39
|
+
log :info, "POST Succeeded: #{response.inspect}"
|
40
|
+
else
|
41
|
+
log :error, "POST Failed: #{response.inspect}"
|
42
|
+
end
|
43
|
+
|
44
|
+
@last_response = response
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def url
|
49
|
+
"/databases/" \
|
50
|
+
+ Errplane.configuration.application_id \
|
51
|
+
+ Errplane.configuration.environment \
|
52
|
+
+ "/points?api_key=" \
|
53
|
+
+ Errplane.configuration.api_key
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize_secure_connection
|
57
|
+
connection = Net::HTTP.new("apiv2.errplane.com", 443)
|
58
|
+
connection.use_ssl = true
|
59
|
+
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
60
|
+
connection.read_timeout = READ_TIMEOUT
|
61
|
+
connection.open_timeout = OPEN_TIMEOUT
|
62
|
+
connection
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/errplane/capistrano.rb
CHANGED
@@ -16,9 +16,9 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
16
16
|
load File.join(Dir.pwd, "config/initializers/errplane.rb")
|
17
17
|
|
18
18
|
Errplane.configuration.logger = Logger.new("/dev/null")
|
19
|
-
Errplane.configuration.
|
19
|
+
Errplane.configuration.environment = framework_env
|
20
20
|
|
21
|
-
|
21
|
+
context = {
|
22
22
|
:environment => framework_env,
|
23
23
|
:revision => current_revision,
|
24
24
|
:repository => repository,
|
@@ -30,8 +30,7 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
30
30
|
:scm_user_email => deploying_user_email
|
31
31
|
}
|
32
32
|
|
33
|
-
Errplane
|
34
|
-
puts 'Done.'
|
33
|
+
Errplane.report_deployment(context)
|
35
34
|
end
|
36
35
|
end
|
37
36
|
end
|
@@ -9,7 +9,7 @@ module Errplane
|
|
9
9
|
attr_accessor :application_root
|
10
10
|
|
11
11
|
attr_accessor :logger
|
12
|
-
attr_accessor :
|
12
|
+
attr_accessor :environment
|
13
13
|
attr_accessor :framework
|
14
14
|
attr_accessor :framework_version
|
15
15
|
attr_accessor :language
|
@@ -101,7 +101,7 @@ module Errplane
|
|
101
101
|
end
|
102
102
|
|
103
103
|
def ignore_current_environment?
|
104
|
-
self.ignored_environments.include?(self.
|
104
|
+
self.ignored_environments.include?(self.environment)
|
105
105
|
end
|
106
106
|
|
107
107
|
def define_custom_exception_data(&block)
|
@@ -1,7 +1,12 @@
|
|
1
|
+
require "base64"
|
2
|
+
require "socket"
|
3
|
+
|
1
4
|
module Errplane
|
2
|
-
class
|
5
|
+
class ExceptionPresenter
|
3
6
|
attr_accessor :hash
|
7
|
+
|
4
8
|
attr_reader :exception
|
9
|
+
attr_reader :backtrace
|
5
10
|
attr_reader :params
|
6
11
|
attr_reader :session_data
|
7
12
|
attr_reader :controller
|
@@ -10,8 +15,12 @@ module Errplane
|
|
10
15
|
attr_reader :user_agent
|
11
16
|
attr_reader :custom_data
|
12
17
|
|
13
|
-
def initialize(params = {})
|
14
|
-
|
18
|
+
def initialize(e, params = {})
|
19
|
+
e = e.continued_exception if e.respond_to?(:continued_exception)
|
20
|
+
e = e.original_exception if e.respond_to?(:original_exception)
|
21
|
+
|
22
|
+
@exception = e.is_a?(String) ? Exception.new(e) : e
|
23
|
+
@backtrace = Errplane::Backtrace.new(@exception.backtrace).to_a || []
|
15
24
|
@params = params[:params]
|
16
25
|
@session_data = params[:session_data]
|
17
26
|
@controller = params[:controller]
|
@@ -19,7 +28,7 @@ module Errplane
|
|
19
28
|
@request_url = params[:request_url]
|
20
29
|
@user_agent = params[:user_agent]
|
21
30
|
@custom_data = params[:custom_data] || {}
|
22
|
-
@environment_variables =
|
31
|
+
@environment_variables = ENV.to_hash || {}
|
23
32
|
end
|
24
33
|
|
25
34
|
def to_json
|
@@ -30,11 +39,12 @@ module Errplane
|
|
30
39
|
:framework => Errplane.configuration.framework,
|
31
40
|
:framework_version => Errplane.configuration.framework_version,
|
32
41
|
:message => @exception.message,
|
33
|
-
:backtrace =>
|
42
|
+
:backtrace => @backtrace,
|
34
43
|
:exception_class => @exception.class.to_s,
|
35
44
|
:language => "Ruby",
|
36
45
|
:language_version => "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}",
|
37
46
|
:reporter => reporter,
|
47
|
+
:hostname => Socket.gethostname,
|
38
48
|
:custom_data => @custom_data
|
39
49
|
}
|
40
50
|
|
@@ -45,19 +55,33 @@ module Errplane
|
|
45
55
|
Errplane.configuration.add_custom_exception_data(self)
|
46
56
|
|
47
57
|
payload[:request_data] = request_data if @controller || @action || !@params.blank?
|
48
|
-
payload[:hash] =
|
49
|
-
|
50
|
-
|
58
|
+
payload[:hash] = calculate_hash
|
59
|
+
payload.to_json
|
60
|
+
end
|
61
|
+
|
62
|
+
def calculate_hash
|
63
|
+
if hash
|
64
|
+
hash
|
65
|
+
elsif Errplane.configuration.aggregated_exception_classes.include?(@exception.class.to_s)
|
66
|
+
Digest::SHA1.hexdigest(@exception.class.to_s)
|
67
|
+
else
|
68
|
+
Digest::SHA1.hexdigest(@exception.class.to_s + @backtrace.first.to_s)
|
51
69
|
end
|
70
|
+
end
|
52
71
|
|
53
|
-
|
72
|
+
def time_series_name
|
73
|
+
"exceptions/" + calculate_hash
|
74
|
+
end
|
75
|
+
|
76
|
+
def context
|
77
|
+
Base64.strict_encode64(to_json)
|
54
78
|
end
|
55
79
|
|
56
80
|
def reporter
|
57
81
|
{
|
58
82
|
:name => "Errplane",
|
59
83
|
:version => Errplane::VERSION,
|
60
|
-
:url => "https://github.com/errplane/
|
84
|
+
:url => "https://github.com/errplane/errplane-ruby"
|
61
85
|
}
|
62
86
|
end
|
63
87
|
|
data/lib/errplane/rails.rb
CHANGED
@@ -18,7 +18,7 @@ module Errplane
|
|
18
18
|
Errplane.configure(true) do |config|
|
19
19
|
config.logger ||= ::Rails.logger
|
20
20
|
config.debug = true
|
21
|
-
config.
|
21
|
+
config.environment ||= ::Rails.env
|
22
22
|
config.application_root ||= ::Rails.root
|
23
23
|
config.application_name ||= "Application"
|
24
24
|
config.framework = "Rails"
|
data/lib/errplane/railtie.rb
CHANGED
@@ -63,16 +63,16 @@ module Errplane
|
|
63
63
|
|
64
64
|
10.times do
|
65
65
|
sleep 1
|
66
|
-
break unless Errplane.
|
66
|
+
break unless Errplane.api.last_response.nil?
|
67
67
|
end
|
68
68
|
|
69
69
|
if response.try(:first) == 500
|
70
|
-
if Errplane.
|
70
|
+
if Errplane.api.last_response.nil?
|
71
71
|
puts "Uh oh. Your app threw an exception, but we didn't get a response. Check your network connection and try again."
|
72
|
-
elsif Errplane.
|
72
|
+
elsif Errplane.api.last_response.code == "201"
|
73
73
|
puts "Done. Check your email or http://errplane.com for the exception notice."
|
74
74
|
else
|
75
|
-
puts "That didn't work. The Errplane API said: #{Errplane.
|
75
|
+
puts "That didn't work. The Errplane API said: #{Errplane.api.last_response.body}"
|
76
76
|
end
|
77
77
|
else
|
78
78
|
puts "Request failed: #{response}"
|
@@ -82,12 +82,12 @@ module Errplane
|
|
82
82
|
response = ::Rails.application.call(env)
|
83
83
|
|
84
84
|
if response.try(:first) == 500
|
85
|
-
if Errplane.
|
85
|
+
if Errplane.api.last_response.nil?
|
86
86
|
puts "Uh oh. Your app threw an exception, but we didn't get a response. Check your network connection and try again."
|
87
|
-
elsif Errplane.
|
87
|
+
elsif Errplane.api.last_response.code == "201"
|
88
88
|
puts "Done. Check your email or http://errplane.com for the exception notice."
|
89
89
|
else
|
90
|
-
puts "That didn't work. The Errplane API said: #{Errplane.
|
90
|
+
puts "That didn't work. The Errplane API said: #{Errplane.api.last_response.body}"
|
91
91
|
end
|
92
92
|
else
|
93
93
|
puts "Request failed: #{response}"
|
@@ -105,7 +105,7 @@ module Errplane
|
|
105
105
|
config.after_initialize do
|
106
106
|
Errplane.configure(true) do |config|
|
107
107
|
config.logger ||= ::Rails.logger
|
108
|
-
config.
|
108
|
+
config.environment ||= ::Rails.env
|
109
109
|
config.application_root ||= ::Rails.root
|
110
110
|
config.application_name ||= ::Rails.application.class.parent_name
|
111
111
|
config.framework = "Rails"
|
@@ -130,13 +130,30 @@ module Errplane
|
|
130
130
|
if defined?(ActiveSupport::Notifications)
|
131
131
|
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |name, start, finish, id, payload|
|
132
132
|
if Errplane.configuration.instrumentation_enabled?
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
133
|
+
timestamp = finish.utc.to_i
|
134
|
+
controller_runtime = ((finish - start)*1000).ceil
|
135
|
+
view_runtime = (payload[:view_runtime] || 0).ceil
|
136
|
+
db_runtime = (payload[:db_runtime] || 0).ceil
|
137
|
+
controller_name = payload[:controller]
|
138
|
+
action_name = payload[:action]
|
139
|
+
|
140
|
+
Errplane.queue.push({
|
141
|
+
:name => "controllers/#{controller_name}##{action_name}",
|
142
|
+
:value => controller_runtime,
|
143
|
+
:timestamp => timestamp
|
144
|
+
})
|
145
|
+
|
146
|
+
Errplane.queue.push({
|
147
|
+
:name => "views/#{controller_name}##{action_name}",
|
148
|
+
:value => view_runtime,
|
149
|
+
:timestamp => timestamp
|
150
|
+
})
|
151
|
+
|
152
|
+
Errplane.queue.push({
|
153
|
+
:name => "db/#{controller_name}##{action_name}",
|
154
|
+
:value => db_runtime,
|
155
|
+
:timestamp => timestamp
|
156
|
+
})
|
140
157
|
end
|
141
158
|
end
|
142
159
|
end
|
data/lib/errplane/sinatra.rb
CHANGED
data/lib/errplane/version.rb
CHANGED
data/lib/errplane/worker.rb
CHANGED
@@ -6,13 +6,13 @@ require "base64"
|
|
6
6
|
module Errplane
|
7
7
|
class Worker
|
8
8
|
MAX_POST_LINES = 200
|
9
|
-
|
9
|
+
MAX_TIME_SERIES_NAME_LENGTH = 255
|
10
10
|
|
11
11
|
class << self
|
12
12
|
include Errplane::Logger
|
13
13
|
|
14
14
|
def indent_lines(lines, num)
|
15
|
-
lines.split("\n").map {|line| (" " * num) + line}.join("\n")
|
15
|
+
lines.split("\n").map {|line| (" " * num) + line[0..64]}.join("\n")
|
16
16
|
end
|
17
17
|
|
18
18
|
def post_data(data)
|
@@ -20,33 +20,12 @@ module Errplane
|
|
20
20
|
log :debug, "Current environment is ignored, skipping POST."
|
21
21
|
return false
|
22
22
|
else
|
23
|
-
log :debug, "
|
24
|
-
url = "/databases/#{Errplane.configuration.application_id}#{Errplane.configuration.rails_environment}/points?api_key=#{Errplane.configuration.api_key}"
|
25
|
-
log :debug, "Posting to: #{url}"
|
26
|
-
|
27
|
-
retry_count = POST_RETRIES
|
23
|
+
log :debug, "POSTing data:\n#{indent_lines(data, 13)}"
|
28
24
|
begin
|
29
|
-
|
30
|
-
http = Net::HTTP.new(Errplane.configuration.api_host, 443)
|
31
|
-
http.use_ssl = true
|
32
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
33
|
-
http.open_timeout = 3
|
34
|
-
http.read_timeout = 3
|
35
|
-
|
36
|
-
response = http.post(url, data)
|
37
|
-
log :debug, "Response code: #{response.code}"
|
38
|
-
log :debug, "Response: #{response.inspect}"
|
25
|
+
Errplane.api.post(data)
|
39
26
|
rescue => e
|
40
|
-
|
41
|
-
unless retry_count.zero?
|
42
|
-
log :info, "POST failed, retrying."
|
43
|
-
sleep 1
|
44
|
-
retry
|
45
|
-
end
|
46
|
-
log :info, "Unable to POST after retrying, aborting!"
|
47
|
-
return false
|
27
|
+
log :error, "Error calling API: #{e.inspect}"
|
48
28
|
end
|
49
|
-
return true
|
50
29
|
end
|
51
30
|
end
|
52
31
|
|
@@ -88,29 +67,10 @@ module Errplane
|
|
88
67
|
log :debug, "Found data in the queue! (#{n[:name]})"
|
89
68
|
|
90
69
|
begin
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
timestamp = n[:finish].utc.to_i
|
96
|
-
controller_runtime = ((n[:finish] - n[:start])*1000).ceil
|
97
|
-
view_runtime = (n[:payload][:view_runtime] || 0).ceil
|
98
|
-
db_runtime = (n[:payload][:db_runtime] || 0).ceil
|
99
|
-
|
100
|
-
data << "controllers/#{n[:payload][:controller]}##{n[:payload][:action]} #{controller_runtime} #{timestamp}"
|
101
|
-
data << "views #{view_runtime} #{timestamp}"
|
102
|
-
data << "db #{db_runtime} #{timestamp}"
|
103
|
-
end
|
104
|
-
when "exception"
|
105
|
-
Errplane.transmitter.deliver n[:data], n[:url]
|
106
|
-
when "custom"
|
107
|
-
if n[:name].length > 255
|
108
|
-
log :error, "Time series name too long! Discarding data for: #{n[:name]}"
|
109
|
-
else
|
110
|
-
line = "#{n[:name]} #{n[:value] || 1} #{n[:timestamp]}"
|
111
|
-
line = "#{line} #{Base64.encode64(n[:message]).strip}" if n[:message]
|
112
|
-
data << line
|
113
|
-
end
|
70
|
+
if n[:name].split("|").any?{|x| x.length > MAX_TIME_SERIES_NAME_LENGTH}
|
71
|
+
log :error, "Time series name too long! Discarding data for: #{n[:name]}"
|
72
|
+
else
|
73
|
+
data << Errplane.process_line(n)
|
114
74
|
end
|
115
75
|
rescue => e
|
116
76
|
log :info, "Instrumentation Error! #{e.inspect}"
|
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.6.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: 2013-02-
|
12
|
+
date: 2013-02-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
16
|
-
requirement: &
|
16
|
+
requirement: &70316697813820 !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: *70316697813820
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: activesupport
|
27
|
-
requirement: &
|
27
|
+
requirement: &70316697809360 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 2.3.2
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70316697809360
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: actionpack
|
38
|
-
requirement: &
|
38
|
+
requirement: &70316697824100 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 2.3.2
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70316697824100
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: bundler
|
49
|
-
requirement: &
|
49
|
+
requirement: &70316697823360 !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: *70316697823360
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: fakeweb
|
60
|
-
requirement: &
|
60
|
+
requirement: &70316697822620 !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: *70316697822620
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: guard
|
71
|
-
requirement: &
|
71
|
+
requirement: &70316697821800 !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: *70316697821800
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: guard-rspec
|
82
|
-
requirement: &
|
82
|
+
requirement: &70316697821120 !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: *70316697821120
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: rake
|
93
|
-
requirement: &
|
93
|
+
requirement: &70316697820380 !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: *70316697820380
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: rdoc
|
104
|
-
requirement: &
|
104
|
+
requirement: &70316697819800 !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: *70316697819800
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: rspec
|
115
|
-
requirement: &
|
115
|
+
requirement: &70316697819200 !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: *70316697819200
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: tzinfo
|
126
|
-
requirement: &
|
126
|
+
requirement: &70316697817820 !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: *70316697817820
|
135
135
|
description: This gem provides implements instrumentation with Errplane for Rails
|
136
136
|
2.3.x and 3.x applications.
|
137
137
|
email:
|
@@ -141,7 +141,6 @@ extensions: []
|
|
141
141
|
extra_rdoc_files: []
|
142
142
|
files:
|
143
143
|
- config.ru
|
144
|
-
- errplane-0.5.29.gem
|
145
144
|
- errplane.gemspec
|
146
145
|
- Gemfile
|
147
146
|
- Gemfile.lock
|
@@ -156,10 +155,11 @@ files:
|
|
156
155
|
- gemfiles/versioned/Gemfile.rails-2.3.2
|
157
156
|
- generators/errplane/errplane_generator.rb
|
158
157
|
- generators/errplane/templates/initializer.rb
|
158
|
+
- lib/errplane/api.rb
|
159
159
|
- lib/errplane/backtrace.rb
|
160
|
-
- lib/errplane/black_box.rb
|
161
160
|
- lib/errplane/capistrano.rb
|
162
161
|
- lib/errplane/configuration.rb
|
162
|
+
- lib/errplane/exception_presenter.rb
|
163
163
|
- lib/errplane/logger.rb
|
164
164
|
- lib/errplane/max_queue.rb
|
165
165
|
- lib/errplane/rack.rb
|
@@ -172,7 +172,6 @@ files:
|
|
172
172
|
- lib/errplane/railtie.rb
|
173
173
|
- lib/errplane/resque.rb
|
174
174
|
- lib/errplane/sinatra.rb
|
175
|
-
- lib/errplane/transmitter.rb
|
176
175
|
- lib/errplane/version.rb
|
177
176
|
- lib/errplane/worker.rb
|
178
177
|
- lib/errplane.rb
|
@@ -204,7 +203,6 @@ files:
|
|
204
203
|
- spec/unit/configuration_spec.rb
|
205
204
|
- spec/unit/errplane_spec.rb
|
206
205
|
- spec/unit/max_queue_spec.rb
|
207
|
-
- spec/unit/transmitter_spec.rb
|
208
206
|
- spec/unit/worker_spec.rb
|
209
207
|
homepage: http://errplane.com
|
210
208
|
licenses:
|
@@ -255,5 +253,4 @@ test_files:
|
|
255
253
|
- spec/unit/configuration_spec.rb
|
256
254
|
- spec/unit/errplane_spec.rb
|
257
255
|
- spec/unit/max_queue_spec.rb
|
258
|
-
- spec/unit/transmitter_spec.rb
|
259
256
|
- spec/unit/worker_spec.rb
|
data/errplane-0.5.29.gem
DELETED
Binary file
|
data/lib/errplane/transmitter.rb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
module Errplane
|
2
|
-
class Transmitter
|
3
|
-
include Errplane::Logger
|
4
|
-
|
5
|
-
attr_reader :last_response
|
6
|
-
|
7
|
-
HTTP_ERRORS = [ EOFError,
|
8
|
-
Errno::ECONNREFUSED,
|
9
|
-
Errno::ECONNRESET,
|
10
|
-
Errno::EINVAL,
|
11
|
-
Net::HTTPBadResponse,
|
12
|
-
Net::HTTPHeaderSyntaxError,
|
13
|
-
Net::ProtocolError,
|
14
|
-
Timeout::Error ].freeze
|
15
|
-
|
16
|
-
def initialize(params = {})
|
17
|
-
@last_response = nil
|
18
|
-
end
|
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.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
|
-
|
48
|
-
def relay(black_box, deployment = false)
|
49
|
-
http = initialize_http_connection
|
50
|
-
data = black_box.to_json
|
51
|
-
response = begin
|
52
|
-
url = "/api/v1/applications/#{Errplane.configuration.application_id}/exceptions/#{Errplane.configuration.rails_environment}#{"/deploy" if deployment}?api_key=#{Errplane.configuration.api_key}"
|
53
|
-
log :info, "URL: #{url}"
|
54
|
-
log :info, "Data: #{data.inspect}"
|
55
|
-
http.post(url, data)
|
56
|
-
rescue *HTTP_ERRORS => e
|
57
|
-
log :error, "HTTP error contacting Errplane API! #{e.class}: #{e.message}"
|
58
|
-
end
|
59
|
-
|
60
|
-
@last_response = response
|
61
|
-
if response.is_a?(Net::HTTPSuccess)
|
62
|
-
log :info, "Request Succeeded: #{response.inspect}"
|
63
|
-
else
|
64
|
-
log :error, "Request Failed: #{response.inspect}"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
private
|
69
|
-
def initialize_http_connection
|
70
|
-
connection = Net::HTTP.new("api.errplane.com", 443)
|
71
|
-
connection.use_ssl = true
|
72
|
-
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
73
|
-
connection
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|