errplane 0.4.12 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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 --api-key your-api-key-goes-here
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
@@ -3,7 +3,6 @@
3
3
  if ENV["BUNDLE_GEMFILE"] == File.expand_path("Gemfile")
4
4
  ENV["BUNDLE_GEMFILE"] = "gemfiles/Gemfile.rails-3.2.x"
5
5
  end
6
- puts "RAKEFILE"
7
6
 
8
7
  require 'bundler'
9
8
  Bundler::GemHelper.install_tasks
data/lib/errplane.rb CHANGED
@@ -1,6 +1,7 @@
1
- require 'net/http'
2
- require 'net/https'
3
- require 'rubygems'
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)
@@ -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 || !params.empty?
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 => params.to_hash,
10
+ :params => use_params,
7
11
  :session_data => errplane_session_data,
8
12
  :controller => params[:controller],
9
13
  :action => params[:action],
@@ -42,7 +42,13 @@ module Errplane
42
42
  response = ::Rails.application.call(env)
43
43
 
44
44
  if response.try(:first) == 500
45
- puts "Done. Check your email or http://errplane.com for the exception notice."
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
- puts "Done. Check your email or http://errplane.com for the exception notice."
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."
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Errplane
2
- VERSION = "0.4.12"
2
+ VERSION = "0.5.0"
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -2,7 +2,6 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
  ENV["RAILS_ENV"] ||= "test"
4
4
 
5
- puts "CALLING"
6
5
  require 'rails/version'
7
6
 
8
7
  if Rails::VERSION::MAJOR > 2
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.12
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-09-06 00:00:00.000000000 Z
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: &70275484338460 !ruby/object:Gem::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: *70275484338460
24
+ version_requirements: *70165371262220
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activesupport
27
- requirement: &70275484337800 !ruby/object:Gem::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: *70275484337800
35
+ version_requirements: *70165371261120
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: actionpack
38
- requirement: &70275484337140 !ruby/object:Gem::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: *70275484337140
46
+ version_requirements: *70165371260600
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bundler
49
- requirement: &70275484336380 !ruby/object:Gem::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: *70275484336380
57
+ version_requirements: *70165371259960
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: fakeweb
60
- requirement: &70275484335580 !ruby/object:Gem::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: *70275484335580
68
+ version_requirements: *70165371259200
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: guard
71
- requirement: &70275484335060 !ruby/object:Gem::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: *70275484335060
79
+ version_requirements: *70165371258360
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: guard-rspec
82
- requirement: &70275484334340 !ruby/object:Gem::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: *70275484334340
90
+ version_requirements: *70165371257800
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: rake
93
- requirement: &70275484349900 !ruby/object:Gem::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: *70275484349900
101
+ version_requirements: *70165371257320
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: rdoc
104
- requirement: &70275484349140 !ruby/object:Gem::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: *70275484349140
112
+ version_requirements: *70165371256800
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: rspec
115
- requirement: &70275484348380 !ruby/object:Gem::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: *70275484348380
123
+ version_requirements: *70165371256240
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: tzinfo
126
- requirement: &70275484347640 !ruby/object:Gem::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: *70275484347640
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