errplane 0.5.30 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|