crashlog 0.0.2 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -8,7 +8,7 @@ GIT
8
8
  PATH
9
9
  remote: .
10
10
  specs:
11
- crashlog (0.0.1)
11
+ crashlog (1.0.0.rc1)
12
12
  activesupport
13
13
  crashlog-auth-hmac (~> 1.1.5)
14
14
  faraday
@@ -86,7 +86,7 @@ GEM
86
86
  multipart-post (1.1.5)
87
87
  pg (0.14.0)
88
88
  polyglot (0.3.3)
89
- rabl (0.7.0)
89
+ rabl (0.7.1)
90
90
  activesupport (>= 2.3.14)
91
91
  multi_json (~> 1.0)
92
92
  rack (1.4.1)
data/INSTALL CHANGED
@@ -3,8 +3,8 @@
3
3
  You should have something like this in config/initializers/crashlog.rb.
4
4
 
5
5
  CrashLog.configure do |config|
6
- config.api_key = 'AhHusJhJHAjJajA'
7
- config.project_id = 'ca9e5931-310f-4897-90c2-d0626f0f2a01'
6
+ config.api_key = 'API_KEY'
7
+ config.secret = 'SECRET'
8
8
  end
9
9
 
10
10
  (Please note that this configuration should be in a global configuration, and
@@ -18,5 +18,4 @@ this rake task (from RAILS_ROOT):
18
18
  rake crashlog:test
19
19
 
20
20
  If everything is configured properly, that task will send a notice to CrashLog
21
- which will be visible immediately.
22
-
21
+ which will be visible immediately.
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # CrashLog
2
2
 
3
+ [![Build Status](https://secure.travis-ci.org/crashlog/crashlog.png)](http://travis-ci.org/crashlog/crashlog)
4
+
3
5
  CrashLog is a exception tracking and notification service that gives you unparalleled
4
6
  insight into issues occurring within your production applications, in realtime.
5
7
 
data/Rakefile CHANGED
@@ -11,5 +11,4 @@ require "rspec/core/rake_task"
11
11
  desc "Run all examples"
12
12
  RSpec::Core::RakeTask.new
13
13
 
14
- task :default => :spec
15
-
14
+ task :default => :spec
@@ -39,14 +39,14 @@ module CrashLog
39
39
  #
40
40
  # Get this from your projects configuration page within http://CrashLog.io
41
41
  :api_key => nil,
42
- :project_id => nil,
42
+ :secret => nil,
43
43
 
44
44
  # Stages (environments) which we consider to be in a production environment
45
45
  # and thus you want to be sent notifications for.
46
46
  :release_stages => ['staging', 'production'],
47
47
 
48
48
  # The name of the current stage
49
- :stage => 'development',
49
+ :stage => 'production',
50
50
 
51
51
  # Project Root directory
52
52
  :project_root => nil,
@@ -127,7 +127,9 @@ module CrashLog
127
127
 
128
128
  # Internal
129
129
  # Do not change unless you know what this does.
130
- :service_name => 'CrashLog'
130
+ :service_name => 'CrashLog',
131
+
132
+ :json_parser => :yajl
131
133
 
132
134
  def root
133
135
  fetch(:project_root)
@@ -147,7 +149,7 @@ module CrashLog
147
149
 
148
150
  # Release stages are stages which send exceptions
149
151
  def release_stage?
150
- release_stages.include?(stage)
152
+ Array(release_stages).include?(stage)
151
153
  end
152
154
 
153
155
  # Set the current stage
@@ -159,9 +161,13 @@ module CrashLog
159
161
  #
160
162
  # Returns true if all required keys are provided, otherwise false
161
163
  def valid?
162
- [:api_key, :project_id, :host, :port].all? do |key|
163
- !__send__(key).nil?
164
- end
164
+ invalid_keys.empty?
165
+ end
166
+
167
+ def invalid_keys
168
+ [:api_key, :secret, :host, :port].map do |key|
169
+ key if send(key).nil?
170
+ end.compact
165
171
  end
166
172
 
167
173
  def ignored?(exception)
@@ -36,7 +36,10 @@ module CrashLog
36
36
  end
37
37
 
38
38
  def deliver
39
- Reporter.new(config).notify(self.body)
39
+ reporter = Reporter.new(config)
40
+ if reporter.notify(self.body)
41
+ reporter.result
42
+ end
40
43
  end
41
44
 
42
45
  attr_reader :event, :backtrace, :exception_object, :environment, :context
@@ -21,7 +21,7 @@ module CrashLog
21
21
 
22
22
  CrashLog.configure do |config|
23
23
  config.logger = rails_logger
24
- config.release_stage = RAILS_ENV if defined?(RAILS_ENV)
24
+ config.stage = RAILS_ENV if defined?(RAILS_ENV)
25
25
  config.project_root = RAILS_ROOT if defined?(RAILS_ROOT)
26
26
  config.framework = "Rails: #{::Rails::VERSION::STRING}" if defined?(::Rails::VERSION)
27
27
  end
@@ -7,9 +7,9 @@ module CrashLog
7
7
 
8
8
  config.after_initialize do
9
9
  CrashLog.configure do |config|
10
- config.logger ||= ::Rails.logger
11
- config.stage ||= ::Rails.env
12
- config.project_root ||= ::Rails.root
10
+ config.logger = ::Rails.logger
11
+ config.stage = ::Rails.env
12
+ config.project_root = ::Rails.root
13
13
  config.framework = "Rails: #{::Rails::VERSION::STRING}"
14
14
  end
15
15
 
@@ -1,6 +1,7 @@
1
1
  require 'faraday'
2
2
  require 'faraday/request/hmac_authentication'
3
3
  require 'uuid'
4
+ require 'multi_json'
4
5
  require 'yajl'
5
6
 
6
7
  module CrashLog
@@ -18,11 +19,12 @@ module CrashLog
18
19
  @endpoint = config.endpoint
19
20
  @announce_endpoint = config.announce == true ?
20
21
  config.announce_endpoint : nil
22
+ MultiJson.use(config.json_parser || :yajl)
21
23
  end
22
24
 
23
25
  def notify(payload)
24
- #return if dry_run?
25
- #MultiJson.use(:yajl)
26
+ return if dry_run?
27
+
26
28
  response = post(endpoint, MultiJson.encode({:payload => payload}))
27
29
  @response = response
28
30
  report_result(response.body)
@@ -30,6 +32,7 @@ module CrashLog
30
32
  rescue => e
31
33
  log_exception e
32
34
  error("Sending exception failed due to a connectivity issue")
35
+ nil
33
36
  end
34
37
 
35
38
  def announce
@@ -38,13 +41,11 @@ module CrashLog
38
41
 
39
42
  response = post(config.announce_endpoint, JSON.dump(identification_hash))
40
43
  if response.status == 201
41
- JSON.load(response.body).symbolize_keys.fetch(:application, 'Default')
44
+ JSON.load(response.body).symbolize_keys.fetch(:application_name, 'Default')
42
45
  else
43
- false
46
+ nil
44
47
  end
45
48
  rescue => e
46
- # We only want to log our mess when testing
47
- log_exception(e) # if respond_to?(:should)
48
49
  error("Failed to announce application launch")
49
50
  nil
50
51
  end
@@ -54,7 +55,7 @@ module CrashLog
54
55
  end
55
56
 
56
57
  def url
57
- URI.parse("#{scheme}://#{host}:#{port}")
58
+ URI.parse("#{scheme}://#{host}:#{port}").to_s
58
59
  end
59
60
 
60
61
  def identification_hash
@@ -64,10 +65,6 @@ module CrashLog
64
65
  }
65
66
  end
66
67
 
67
- def print_result
68
-
69
- end
70
-
71
68
  def dry_run?
72
69
  config.dry_run == true
73
70
  end
@@ -75,18 +72,15 @@ module CrashLog
75
72
  def post(endpoint, body)
76
73
  connection.post do |req|
77
74
  req.url(endpoint)
78
- # req.sign!(config.project_id, config.api_key)
79
75
  req.headers['Content-Type'] = 'application/json'
80
76
  req.body = body
81
77
  end
82
78
  end
83
79
 
84
- # private
85
-
86
80
  def connection
87
81
  @connection ||= begin
88
82
  Faraday.new(:url => url) do |faraday|
89
- faraday.request :hmac_authentication, config.project_id, config.api_key, {:service_id => config.service_name}
83
+ faraday.request :hmac_authentication, config.api_key, config.secret, {:service_id => config.service_name}
90
84
  faraday.adapter(adapter)
91
85
  faraday.request :url_encoded
92
86
  # faraday.request :token_auth, config.api_key
@@ -1,3 +1,3 @@
1
1
  module CrashLog
2
- VERSION = "0.0.2"
2
+ VERSION = "1.0.0.rc1"
3
3
  end
data/lib/crash_log.rb CHANGED
@@ -53,7 +53,15 @@ module CrashLog
53
53
  #
54
54
  # Returns true if successful, otherwise false
55
55
  def notify(exception, context = {})
56
- send_notification(exception, context)
56
+ send_notification(exception, context).tap do |notification|
57
+ if notification
58
+ info "Event sent to CrashLog.io"
59
+ info "Event URL: http://crashlog.io/locate/#{notification[:location_id]}" if notification.has_key?(:location_id)
60
+ else
61
+ error "Failed to send event to CrashLog.io"
62
+ log_exception(exception)
63
+ end
64
+ end
57
65
  end
58
66
 
59
67
  # Sends the notice unless it is one of the default ignored exceptions.
@@ -66,7 +74,7 @@ module CrashLog
66
74
  application = CrashLog::Reporter.new(configuration).announce
67
75
 
68
76
  if application
69
- info("Initialized and ready to handle exceptions for #{application}")
77
+ info("Configured correctly and ready to handle exceptions for '#{application}'")
70
78
  else
71
79
  error("Failed to report for duty, your application failed to authenticate correctly with stdin.crashlog.io")
72
80
  end
@@ -74,12 +82,15 @@ module CrashLog
74
82
 
75
83
  # Configure the gem to send notifications, at the very least an api_key is
76
84
  # required.
77
- def configure
78
- yield(configuration) if block_given?
79
- if configuration.valid?
80
- report_for_duty!
81
- else
82
- error('Not configured correctly')
85
+ def configure(&block)
86
+ if block_given?
87
+ yield(configuration)
88
+
89
+ if configuration.valid?
90
+ report_for_duty!
91
+ elsif !configuration.invalid_keys.include?(:api_key)
92
+ error("Not configured correctly. Missing the following keys: #{configuration.invalid_keys.join(', ')}")
93
+ end
83
94
  end
84
95
  end
85
96
 
@@ -111,7 +122,9 @@ module CrashLog
111
122
  private
112
123
 
113
124
  def send_notification(exception, context = {})
114
- build_payload(exception, context).deliver! if live?
125
+ if live?
126
+ build_payload(exception, context).deliver!
127
+ end
115
128
  end
116
129
 
117
130
  def build_payload(exception, context = {})
@@ -26,10 +26,6 @@ module Faraday
26
26
  request[:body]
27
27
  end
28
28
 
29
- # def request_path(request)
30
- # URI.parse(request[:url]).path
31
- # end
32
-
33
29
  def request_path(request)
34
30
  URI.parse(request[:url].to_s).path
35
31
  end
@@ -53,8 +49,7 @@ module Faraday
53
49
 
54
50
  # Public
55
51
  def call(env)
56
- env[:request_headers][KEY] ||= hmac_auth_header(env).to_s #if sign_request?
57
- puts env[:request_headers]
52
+ env[:request_headers][KEY] ||= hmac_auth_header(env).to_s if sign_request?
58
53
  @app.call(env)
59
54
  end
60
55
 
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'logger'
4
+ require 'fileutils'
5
+
6
+ RAILS_ENV = "production"
7
+ RAILS_ROOT = FileUtils.pwd
8
+ RAILS_DEFAULT_LOGGER = Logger.new(STDOUT)
9
+
10
+ $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
11
+ require 'crashlog'
12
+ require File.expand_path('../../rails/init', __FILE__)
13
+
14
+ fail "Please supply an API Key as the first argument" if ARGV.empty?
15
+
16
+ host = ARGV[3]
17
+ host ||= "stdin.crashlog.io"
18
+
19
+ secure = (ARGV[2] == "secure")
20
+
21
+ exception = begin
22
+ raise "Testing crashlog notifier with secure = #{secure}. If you can see this, it works."
23
+ rescue => foo
24
+ foo
25
+ end
26
+
27
+ CrashLog.configure do |config|
28
+ config.api_key = ARGV[0]
29
+ config.secret = ARGV[1]
30
+ config.scheme = secure ? 'https' : 'http'
31
+ config.host = host
32
+ config.service_name = 'Staging'
33
+ end
34
+
35
+ puts "Configuration:"
36
+ CrashLog.configuration.each do |key, value|
37
+ puts sprintf("%25s: %s", key.to_s, value.inspect.slice(0, 55))
38
+ end
39
+ puts "Sending #{secure ? "" : "in"}secure notification to project with key #{ARGV.first}"
40
+ CrashLog.notify(exception)
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe CrashLog::Configuration do
4
+ context 'release stage' do
5
+ it 'includes production' do
6
+ subject.release_stages.should include 'production'
7
+ end
8
+
9
+ it 'includes staging' do
10
+ subject.release_stages.should include 'staging'
11
+ end
12
+
13
+ it 'is true if production' do
14
+ subject.stage = 'production'
15
+ subject.release_stage?.should be_true
16
+ end
17
+
18
+ it 'is true if staging' do
19
+ subject.stage = 'staging'
20
+ subject.release_stage?.should be_true
21
+ end
22
+
23
+ it 'is false in development' do
24
+ subject.stage = 'development'
25
+ subject.release_stage?.should be_false
26
+ end
27
+ end
28
+
29
+ context 'valid?' do
30
+ it 'is valid if api_key and secret are present' do
31
+ subject.should_not be_valid
32
+ subject.api_key = 'API_KEY'
33
+ subject.secret = 'SECRET'
34
+ subject.should be_valid
35
+ end
36
+ end
37
+ end
@@ -5,7 +5,7 @@ describe CrashLog::Reporter do
5
5
 
6
6
  let(:config) {
7
7
  CrashLog::Configuration.new.tap do |config|
8
- config.project_id = 'PROJECT_ID'
8
+ config.secret = 'SECRET'
9
9
  config.api_key = 'API_KEY'
10
10
  # config.adapter = test_adapter
11
11
  config.scheme = 'http'
@@ -44,7 +44,7 @@ describe CrashLog::Reporter do
44
44
  end
45
45
 
46
46
  let(:announce_response) do
47
- {:application => "CrashLog Test"}
47
+ {:application_name=> "CrashLog Test"}
48
48
  end
49
49
 
50
50
  let(:positive_response_json) { positive_response.to_json }
@@ -66,7 +66,7 @@ describe CrashLog::Reporter do
66
66
  before do
67
67
  test_connection = Faraday.new(:url => subject.url) do |builder|
68
68
  builder.adapter :test, stubs
69
- builder.request :hmac_authentication, 'PROJECT_ID', 'SECRET', {:service_id => 'CrashLog'}
69
+ builder.request :hmac_authentication, 'API_KEY', 'SECRET', {:service_id => 'CrashLog'}
70
70
  builder.request :url_encoded
71
71
  end
72
72
 
@@ -84,14 +84,22 @@ describe CrashLog::Reporter do
84
84
  end
85
85
 
86
86
  it 'makes a post request' do
87
- subject.send(:connection).should_receive(:post).once
87
+ response = double("Post", success?: true)
88
+ response.stub(:body).and_return(positive_response_json)
89
+ subject.send(:connection).should_receive(:post).once.and_return(response)
88
90
  subject.notify(payload)
89
91
  end
90
92
 
91
93
  it 'authenticates request with HMAC' do
94
+ time_travel_to "2012-08-01 00:00:00 UTC"
95
+
92
96
  subject.notify(payload).should be_true
97
+
93
98
  subject.response.env[:request_headers]['Authorization'].should ==
94
- CrashLog::AuthHMAC.new({}, {:service_id => 'CrashLog'}).authorization(subject.response.env, 'PROJECT_ID', 'SECRET')
99
+ CrashLog::AuthHMAC.new({}, {
100
+ :service_id => 'CrashLog',
101
+ :signature => Faraday::Request::HMACAuthentication::CanonicalString
102
+ }).authorization(subject.response.env, 'API_KEY', 'SECRET')
95
103
  stubs.verify_stubbed_calls
96
104
  end
97
105
 
@@ -96,7 +96,7 @@ describe CrashLog do
96
96
  CrashLog::Reporter.any_instance.stub(:announce).and_return("Test Application")
97
97
  logger = stub('Logger')
98
98
  logger.should_receive(:info).
99
- with("** [CrashLog] Initialized and ready to handle exceptions for Test Application")
99
+ with("** [CrashLog] Configured correctly and ready to handle exceptions for 'Test Application'")
100
100
 
101
101
  CrashLog.stub(:logger).and_return(logger)
102
102
  CrashLog.report_for_duty!
@@ -2,5 +2,6 @@ require 'crashlog'
2
2
 
3
3
  CrashLog.configure do |config|
4
4
  config.api_key = "API_KEY"
5
+ config.secret = "SECRET"
5
6
  config.dry_run = true
6
7
  end
@@ -5,6 +5,10 @@ describe 'Rescue from within a Rails 3.x controller' do
5
5
  include RSpec::Rails::RequestExampleGroup
6
6
  include Rack::Test::Methods
7
7
 
8
+ it 'is testing tails 3.x' do
9
+ Rails.version.should =~ /^3\./
10
+ end
11
+
8
12
  describe 'dummy app' do
9
13
  it 'should response nicely to index' do
10
14
  get '/'
data/spec/spec_helper.rb CHANGED
@@ -17,7 +17,5 @@ Dir[File.expand_path("../support/*.rb", __FILE__)].each { |file| require file }
17
17
 
18
18
  RSpec.configure do |config|
19
19
  config.mock_with :rspec
20
-
21
- config.before do
22
- end
20
+ config.include Delorean
23
21
  end
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crashlog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
4
+ version: 1.0.0.rc1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - TestPilot CI
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-06 00:00:00.000000000 Z
12
+ date: 2012-09-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &70175970544380 !ruby/object:Gem::Requirement
16
+ requirement: &70309383792940 !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: *70175970544380
24
+ version_requirements: *70309383792940
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: faraday
27
- requirement: &70175970543240 !ruby/object:Gem::Requirement
27
+ requirement: &70309383792280 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70175970543240
35
+ version_requirements: *70309383792280
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: crashlog-auth-hmac
38
- requirement: &70175970541460 !ruby/object:Gem::Requirement
38
+ requirement: &70309383791780 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.1.5
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70175970541460
46
+ version_requirements: *70309383791780
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: yajl-ruby
49
- requirement: &70175970540800 !ruby/object:Gem::Requirement
49
+ requirement: &70309383791260 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70175970540800
57
+ version_requirements: *70309383791260
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rabl
60
- requirement: &70175970540040 !ruby/object:Gem::Requirement
60
+ requirement: &70309383806820 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 0.6.14
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70175970540040
68
+ version_requirements: *70309383806820
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: uuid
71
- requirement: &70175970539280 !ruby/object:Gem::Requirement
71
+ requirement: &70309383806220 !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: :runtime
78
78
  prerelease: false
79
- version_requirements: *70175970539280
79
+ version_requirements: *70309383806220
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: hashr
82
- requirement: &70175970538820 !ruby/object:Gem::Requirement
82
+ requirement: &70309383805760 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '0'
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *70175970538820
90
+ version_requirements: *70309383805760
91
91
  description: CrashLog Exception reporter
92
92
  email:
93
93
  - support@crashlog.io
@@ -129,7 +129,9 @@ files:
129
129
  - lib/faraday/request/hmac_authentication.rb
130
130
  - lib/rails/generators/crashlog/crashlog_generator.rb
131
131
  - rails/init.rb
132
+ - script/integration_test
132
133
  - spec/crash_log/backtrace_spec.rb
134
+ - spec/crash_log/configuration_spec.rb
133
135
  - spec/crash_log/initializer_spec.rb
134
136
  - spec/crash_log/payload_spec.rb
135
137
  - spec/crash_log/reporter_spec.rb
@@ -188,9 +190,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
188
190
  required_rubygems_version: !ruby/object:Gem::Requirement
189
191
  none: false
190
192
  requirements:
191
- - - ! '>='
193
+ - - ! '>'
192
194
  - !ruby/object:Gem::Version
193
- version: '0'
195
+ version: 1.3.1
194
196
  requirements: []
195
197
  rubyforge_project:
196
198
  rubygems_version: 1.8.15
@@ -199,6 +201,7 @@ specification_version: 3
199
201
  summary: CrashLog is an exception handler for production applications
200
202
  test_files:
201
203
  - spec/crash_log/backtrace_spec.rb
204
+ - spec/crash_log/configuration_spec.rb
202
205
  - spec/crash_log/initializer_spec.rb
203
206
  - spec/crash_log/payload_spec.rb
204
207
  - spec/crash_log/reporter_spec.rb