honeybadger 2.7.2 → 3.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -3
- data/README.md +8 -15
- data/lib/honeybadger.rb +9 -232
- data/lib/honeybadger/agent.rb +292 -134
- data/lib/honeybadger/backend.rb +6 -6
- data/lib/honeybadger/backend/base.rb +11 -0
- data/lib/honeybadger/backend/server.rb +2 -14
- data/lib/honeybadger/cli.rb +0 -2
- data/lib/honeybadger/cli/deploy.rb +42 -0
- data/lib/honeybadger/cli/exec.rb +138 -0
- data/lib/honeybadger/cli/heroku.rb +1 -22
- data/lib/honeybadger/cli/install.rb +74 -0
- data/lib/honeybadger/cli/main.rb +138 -153
- data/lib/honeybadger/cli/notify.rb +66 -0
- data/lib/honeybadger/cli/test.rb +266 -0
- data/lib/honeybadger/config.rb +178 -162
- data/lib/honeybadger/config/defaults.rb +5 -5
- data/lib/honeybadger/config/env.rb +8 -6
- data/lib/honeybadger/config/ruby.rb +100 -0
- data/lib/honeybadger/config/yaml.rb +18 -19
- data/lib/honeybadger/const.rb +3 -16
- data/lib/honeybadger/context_manager.rb +50 -0
- data/lib/honeybadger/init/rails.rb +9 -21
- data/lib/honeybadger/init/rake.rb +2 -0
- data/lib/honeybadger/init/ruby.rb +9 -0
- data/lib/honeybadger/init/sinatra.rb +13 -6
- data/lib/honeybadger/notice.rb +29 -14
- data/lib/honeybadger/plugins/delayed_job/plugin.rb +4 -5
- data/lib/honeybadger/plugins/passenger.rb +1 -2
- data/lib/honeybadger/plugins/rails.rb +0 -28
- data/lib/honeybadger/plugins/resque.rb +2 -5
- data/lib/honeybadger/plugins/shoryuken.rb +2 -2
- data/lib/honeybadger/plugins/sidekiq.rb +2 -2
- data/lib/honeybadger/plugins/sucker_punch.rb +1 -0
- data/lib/honeybadger/plugins/thor.rb +2 -2
- data/lib/honeybadger/plugins/warden.rb +1 -0
- data/lib/honeybadger/rack/error_notifier.rb +11 -9
- data/lib/honeybadger/rack/user_feedback.rb +6 -4
- data/lib/honeybadger/rack/user_informer.rb +6 -4
- data/lib/honeybadger/ruby.rb +2 -0
- data/lib/honeybadger/singleton.rb +26 -0
- data/lib/honeybadger/util/http.rb +12 -0
- data/lib/honeybadger/util/request_hash.rb +71 -0
- data/lib/honeybadger/util/sanitizer.rb +101 -64
- data/lib/honeybadger/version.rb +1 -1
- data/lib/honeybadger/worker.rb +246 -0
- metadata +17 -13
- data/lib/honeybadger/agent/batch.rb +0 -50
- data/lib/honeybadger/agent/null_worker.rb +0 -26
- data/lib/honeybadger/agent/worker.rb +0 -243
- data/lib/honeybadger/cli/helpers.rb +0 -160
- data/lib/honeybadger/config/callbacks.rb +0 -70
- data/lib/honeybadger/plugins/unicorn.rb +0 -27
- data/lib/honeybadger/rack/metrics_reporter.rb +0 -16
- data/lib/honeybadger/rack/request_hash.rb +0 -55
data/lib/honeybadger/backend.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
|
3
|
+
require 'honeybadger/backend/base'
|
4
|
+
require 'honeybadger/backend/server'
|
5
|
+
require 'honeybadger/backend/test'
|
6
|
+
require 'honeybadger/backend/null'
|
7
|
+
require 'honeybadger/backend/debug'
|
8
|
+
|
3
9
|
module Honeybadger
|
4
10
|
module Backend
|
5
11
|
class BackendError < StandardError; end
|
@@ -16,11 +22,5 @@ module Honeybadger
|
|
16
22
|
def self.for(backend)
|
17
23
|
mapping[backend] or raise(BackendError, "Unable to locate backend: #{backend}")
|
18
24
|
end
|
19
|
-
|
20
|
-
autoload :Base, 'honeybadger/backend/base'
|
21
|
-
autoload :Server, 'honeybadger/backend/server'
|
22
|
-
autoload :Test, 'honeybadger/backend/test'
|
23
|
-
autoload :Null, 'honeybadger/backend/null'
|
24
|
-
autoload :Debug, 'honeybadger/backend/debug'
|
25
25
|
end
|
26
26
|
end
|
@@ -11,6 +11,13 @@ module Honeybadger
|
|
11
11
|
|
12
12
|
attr_reader :code, :body, :message, :error
|
13
13
|
|
14
|
+
FRIENDLY_ERRORS = {
|
15
|
+
429 => "Your project is currently sending too many errors.\nThis issue should resolve itself once error traffic is reduced.".freeze,
|
16
|
+
503 => "Your project is currently sending too many errors.\nThis issue should resolve itself once error traffic is reduced.".freeze,
|
17
|
+
402 => "The project owner's billing information has expired (or the trial has ended).\nPlease check your payment details or email support@honeybadger.io for help.".freeze,
|
18
|
+
403 => "The API key is invalid. Please check your API key and try again.".freeze
|
19
|
+
}.freeze
|
20
|
+
|
14
21
|
# Public: Initializes the Response instance.
|
15
22
|
#
|
16
23
|
# response - With 1 argument Net::HTTPResponse, the code, body, and
|
@@ -37,6 +44,10 @@ module Honeybadger
|
|
37
44
|
@success
|
38
45
|
end
|
39
46
|
|
47
|
+
def error_message
|
48
|
+
FRIENDLY_ERRORS[code] || message
|
49
|
+
end
|
50
|
+
|
40
51
|
private
|
41
52
|
|
42
53
|
def parse_error(body)
|
@@ -15,17 +15,7 @@ module Honeybadger
|
|
15
15
|
deploys: '/v1/deploys'.freeze
|
16
16
|
}.freeze
|
17
17
|
|
18
|
-
HTTP_ERRORS =
|
19
|
-
Errno::EINVAL,
|
20
|
-
Errno::ECONNRESET,
|
21
|
-
Errno::ECONNREFUSED,
|
22
|
-
Errno::ENETUNREACH,
|
23
|
-
EOFError,
|
24
|
-
Net::HTTPBadResponse,
|
25
|
-
Net::HTTPHeaderSyntaxError,
|
26
|
-
Net::ProtocolError,
|
27
|
-
OpenSSL::SSL::SSLError,
|
28
|
-
SocketError].freeze
|
18
|
+
HTTP_ERRORS = Util::HTTP::ERRORS
|
29
19
|
|
30
20
|
def initialize(config)
|
31
21
|
@http = Util::HTTP.new(config)
|
@@ -42,9 +32,7 @@ module Honeybadger
|
|
42
32
|
ENDPOINTS[feature] or raise(BackendError, "Unknown feature: #{feature}")
|
43
33
|
Response.new(@http.post(ENDPOINTS[feature], payload, payload_headers(payload)))
|
44
34
|
rescue *HTTP_ERRORS => e
|
45
|
-
Response.new(:error, nil, "HTTP Error: #{e.class}")
|
46
|
-
error { sprintf('http error class=%s message=%s', e.class, e.message.dump) }
|
47
|
-
end
|
35
|
+
Response.new(:error, nil, "HTTP Error: #{e.class}")
|
48
36
|
end
|
49
37
|
|
50
38
|
private
|
data/lib/honeybadger/cli.rb
CHANGED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'honeybadger/cli/main'
|
3
|
+
require 'honeybadger/util/http'
|
4
|
+
|
5
|
+
module Honeybadger
|
6
|
+
module CLI
|
7
|
+
class Deploy
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
def initialize(options, args, config)
|
11
|
+
@options = options
|
12
|
+
@args = args
|
13
|
+
@config = config
|
14
|
+
@shell = ::Thor::Base.shell.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
payload = {
|
19
|
+
environment: options['environment'],
|
20
|
+
revision: options['revision'],
|
21
|
+
repository: options['repository'],
|
22
|
+
local_username: options['user']
|
23
|
+
}
|
24
|
+
|
25
|
+
http = Util::HTTP.new(config)
|
26
|
+
result = http.post('/v1/deploys', payload)
|
27
|
+
if result.code == '201'
|
28
|
+
say("Deploy notification complete.", :green)
|
29
|
+
else
|
30
|
+
say("Invalid response from server: #{result.code}", :red)
|
31
|
+
exit(1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :options, :args, :config
|
38
|
+
|
39
|
+
def_delegator :@shell, :say
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'forwardable'
|
3
|
+
require 'honeybadger/cli/main'
|
4
|
+
require 'honeybadger/util/http'
|
5
|
+
require 'honeybadger/util/stats'
|
6
|
+
require 'open3'
|
7
|
+
require 'ostruct'
|
8
|
+
require 'thor/shell'
|
9
|
+
|
10
|
+
module Honeybadger
|
11
|
+
module CLI
|
12
|
+
class Exec
|
13
|
+
extend Forwardable
|
14
|
+
|
15
|
+
FAILED_TEMPLATE = <<-MSG
|
16
|
+
Honeybadger detected failure or error output for the command:
|
17
|
+
`<%= args.join(' ') %>`
|
18
|
+
|
19
|
+
PROCESS ID: <%= pid %>
|
20
|
+
|
21
|
+
RESULT CODE: <%= code %>
|
22
|
+
|
23
|
+
ERROR OUTPUT:
|
24
|
+
<%= stderr %>
|
25
|
+
|
26
|
+
STANDARD OUTPUT:
|
27
|
+
<%= stdout %>
|
28
|
+
MSG
|
29
|
+
|
30
|
+
NO_EXEC_TEMPLATE = <<-MSG
|
31
|
+
Honeybadger failed to execute the following command:
|
32
|
+
`<%= args.join(' ') %>`
|
33
|
+
|
34
|
+
The command was not executable. Try adjusting permissions on the file.
|
35
|
+
MSG
|
36
|
+
|
37
|
+
NOT_FOUND_TEMPLATE = <<-MSG
|
38
|
+
Honeybadger failed to execute the following command:
|
39
|
+
`<%= args.join(' ') %>`
|
40
|
+
|
41
|
+
The command was not found. Make sure it exists in your PATH.
|
42
|
+
MSG
|
43
|
+
|
44
|
+
def initialize(options, args, config)
|
45
|
+
@options = options
|
46
|
+
@args = args
|
47
|
+
@config = config
|
48
|
+
@shell = ::Thor::Base.shell.new
|
49
|
+
end
|
50
|
+
|
51
|
+
def run
|
52
|
+
result = exec_cmd
|
53
|
+
return if result.success
|
54
|
+
|
55
|
+
payload = {
|
56
|
+
api_key: config.get(:api_key),
|
57
|
+
notifier: NOTIFIER,
|
58
|
+
error: {
|
59
|
+
class: 'honeybdager exec error',
|
60
|
+
message: result.msg
|
61
|
+
},
|
62
|
+
request: {
|
63
|
+
context: {
|
64
|
+
executable: args.first,
|
65
|
+
code: result.code,
|
66
|
+
pid: result.pid
|
67
|
+
}
|
68
|
+
},
|
69
|
+
server: {
|
70
|
+
project_root: Dir.pwd,
|
71
|
+
environment_name: config.get(:env),
|
72
|
+
time: Time.now,
|
73
|
+
stats: Util::Stats.all
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
http = Util::HTTP.new(config)
|
78
|
+
|
79
|
+
begin
|
80
|
+
response = http.post('/v1/notices', payload)
|
81
|
+
rescue
|
82
|
+
say(result.msg)
|
83
|
+
raise
|
84
|
+
end
|
85
|
+
|
86
|
+
if response.code != '201'
|
87
|
+
say(result.msg)
|
88
|
+
say("\nFailed to notify Honeybadger: #{response.code}", :red)
|
89
|
+
exit(1)
|
90
|
+
end
|
91
|
+
|
92
|
+
unless quiet?
|
93
|
+
say(result.msg)
|
94
|
+
say("\nSuccessfully notified Honeybadger")
|
95
|
+
end
|
96
|
+
|
97
|
+
exit(0)
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
attr_reader :options, :args, :config
|
103
|
+
|
104
|
+
def_delegator :@shell, :say
|
105
|
+
|
106
|
+
def quiet?
|
107
|
+
!!options[:quiet]
|
108
|
+
end
|
109
|
+
|
110
|
+
def exec_cmd
|
111
|
+
stdout, stderr, status = Open3.capture3(args.join(' '))
|
112
|
+
|
113
|
+
pid = status.pid
|
114
|
+
code = status.to_i
|
115
|
+
msg = ERB.new(FAILED_TEMPLATE).result(binding) unless status.success?
|
116
|
+
|
117
|
+
OpenStruct.new(
|
118
|
+
msg: msg,
|
119
|
+
pid: pid,
|
120
|
+
code: code,
|
121
|
+
stdout: stdout,
|
122
|
+
stderr: stderr,
|
123
|
+
success: status.success? && stderr =~ BLANK
|
124
|
+
)
|
125
|
+
rescue Errno::EACCES, Errno::ENOEXEC
|
126
|
+
OpenStruct.new(
|
127
|
+
msg: ERB.new(NO_EXEC_TEMPLATE).result(binding),
|
128
|
+
code: 126
|
129
|
+
)
|
130
|
+
rescue Errno::ENOENT
|
131
|
+
OpenStruct.new(
|
132
|
+
msg: ERB.new(NOT_FOUND_TEMPLATE).result(binding),
|
133
|
+
code: 127
|
134
|
+
)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -1,10 +1,6 @@
|
|
1
|
-
require 'honeybadger/cli/helpers'
|
2
|
-
|
3
1
|
module Honeybadger
|
4
2
|
module CLI
|
5
3
|
class Heroku < Thor
|
6
|
-
include Helpers
|
7
|
-
|
8
4
|
class_option :app, aliases: :'-a', type: :string, default: nil, desc: 'Specify optional Heroku APP'
|
9
5
|
|
10
6
|
desc 'install_deploy_notification', 'Install Heroku deploy notifications addon'
|
@@ -37,19 +33,10 @@ module Honeybadger
|
|
37
33
|
def install(api_key)
|
38
34
|
say("Installing Honeybadger #{VERSION} for Heroku")
|
39
35
|
|
40
|
-
load_rails(verbose: true)
|
41
|
-
|
42
|
-
ENV['HONEYBADGER_LOGGING_LEVEL'] = '2'
|
43
|
-
ENV['HONEYBADGER_LOGGING_TTY_LEVEL'] = '0'
|
44
|
-
ENV['HONEYBADGER_LOGGING_PATH'] = 'STDOUT'
|
45
|
-
ENV['HONEYBADGER_REPORT_DATA'] = 'true'
|
46
|
-
|
47
|
-
ENV['HONEYBADGER_API_KEY'] = api_key
|
48
|
-
|
49
36
|
app = options[:app] || detect_heroku_app(false)
|
50
37
|
say("Adding config HONEYBADGER_API_KEY=#{api_key} to Heroku.", :magenta)
|
51
38
|
unless write_heroku_env({'HONEYBADGER_API_KEY' => api_key}, app)
|
52
|
-
say('Unable to update heroku config.
|
39
|
+
say('Unable to update heroku config. You may need to specify an app name with --app APP', :red)
|
53
40
|
exit(1)
|
54
41
|
end
|
55
42
|
|
@@ -61,14 +48,6 @@ module Honeybadger
|
|
61
48
|
say("To install manually, try `honeybadger heroku install_deploy_notification#{app ? " -a #{app}" : ""} -k #{api_key} --environment ENVIRONMENT`", :yellow)
|
62
49
|
end
|
63
50
|
|
64
|
-
config = Config.new(rails_framework_opts)
|
65
|
-
Honeybadger.start(config) unless load_rails_env(verbose: true)
|
66
|
-
say('Sending test notice')
|
67
|
-
unless Agent.instance && send_test(false)
|
68
|
-
say("Honeybadger is installed, but failed to send a test notice. Try `HONEYBADGER_API_KEY=#{api_key} honeybadger test`.", :red)
|
69
|
-
exit(1)
|
70
|
-
end
|
71
|
-
|
72
51
|
say("Installation complete. Happy 'badgering!", :green)
|
73
52
|
end
|
74
53
|
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'honeybadger/cli/main'
|
3
|
+
require 'honeybadger/cli/test'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module Honeybadger
|
7
|
+
module CLI
|
8
|
+
class Install
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
def initialize(options, api_key)
|
12
|
+
@options = options
|
13
|
+
@api_key = api_key
|
14
|
+
@shell = ::Thor::Base.shell.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
say("Installing Honeybadger #{VERSION}")
|
19
|
+
|
20
|
+
begin
|
21
|
+
require File.join(Dir.pwd, 'config', 'application.rb')
|
22
|
+
rescue LoadError
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
root = defined?(Rails.root) ? Rails.root : Pathname.new(Dir.pwd)
|
27
|
+
config_root = defined?(Rails.root) ? root.join('config') : root
|
28
|
+
config_path = config_root.join('honeybadger.yml')
|
29
|
+
|
30
|
+
if config_path.exist?
|
31
|
+
say("You're already on Honeybadger, so you're all set.", :yellow)
|
32
|
+
else
|
33
|
+
say("Writing configuration to: #{config_path}", :yellow)
|
34
|
+
|
35
|
+
path = config_path
|
36
|
+
|
37
|
+
if path.exist?
|
38
|
+
say("The configuration file #{config_path} already exists.", :red)
|
39
|
+
exit(1)
|
40
|
+
elsif !path.dirname.writable?
|
41
|
+
say("The configuration path #{config_path.dirname} is not writable.", :red)
|
42
|
+
exit(1)
|
43
|
+
end
|
44
|
+
|
45
|
+
File.open(path, 'w+') do |file|
|
46
|
+
file.write(<<-CONFIG)
|
47
|
+
---
|
48
|
+
api_key: '#{api_key}'
|
49
|
+
CONFIG
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
if (capfile = root.join('Capfile')).exist?
|
54
|
+
if capfile.read.match(/honeybadger/)
|
55
|
+
say("Detected Honeybadger in Capfile; skipping Capistrano installation.", :yellow)
|
56
|
+
else
|
57
|
+
say("Appending Capistrano tasks to: #{capfile}", :yellow)
|
58
|
+
File.open(capfile, 'a') do |f|
|
59
|
+
f.puts("\nrequire 'capistrano/honeybadger'")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
Test.new({install: true}.freeze).run
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
attr_reader :options, :api_key
|
70
|
+
|
71
|
+
def_delegator :@shell, :say
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/honeybadger/cli/main.rb
CHANGED
@@ -1,195 +1,180 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
require 'honeybadger/cli/
|
1
|
+
require 'honeybadger/cli/deploy'
|
2
|
+
require 'honeybadger/cli/exec'
|
3
|
+
require 'honeybadger/cli/heroku'
|
4
|
+
require 'honeybadger/cli/install'
|
5
|
+
require 'honeybadger/cli/notify'
|
6
|
+
require 'honeybadger/cli/test'
|
7
|
+
require 'honeybadger/config'
|
8
|
+
require 'honeybadger/config/defaults'
|
9
|
+
require 'honeybadger/util/http'
|
10
|
+
require 'honeybadger/version'
|
11
|
+
require 'logger'
|
4
12
|
|
5
13
|
module Honeybadger
|
6
14
|
module CLI
|
15
|
+
BLANK = /\A\s*\z/
|
16
|
+
|
17
|
+
NOTIFIER = {
|
18
|
+
name: 'honeybadger-ruby (cli)'.freeze,
|
19
|
+
url: 'https://github.com/honeybadger-io/honeybadger-ruby'.freeze,
|
20
|
+
version: VERSION,
|
21
|
+
language: nil
|
22
|
+
}.freeze
|
23
|
+
|
7
24
|
class Main < Thor
|
8
|
-
|
25
|
+
def self.project_options
|
26
|
+
option :api_key, required: false, aliases: :'-k', type: :string, desc: 'Api key of your Honeybadger application'
|
27
|
+
option :environment, required: false, aliases: [:'-e', :'-env'], type: :string, desc: 'Environment this command is being executed in (i.e. "production", "staging")'
|
28
|
+
end
|
9
29
|
|
10
|
-
|
30
|
+
desc 'install API_KEY', 'Install Honeybadger into a new project'
|
31
|
+
def install(api_key)
|
32
|
+
Install.new(options, api_key).run
|
33
|
+
rescue => e
|
34
|
+
log_error(e)
|
35
|
+
exit(1)
|
36
|
+
end
|
11
37
|
|
12
|
-
|
38
|
+
desc 'test', 'Send a test notification from Honeybadger'
|
39
|
+
option :dry_run, type: :boolean, aliases: :'-d', default: false, desc: 'Skip sending data to Honeybadger'
|
40
|
+
option :file, type: :string, aliases: :'-f', default: nil, desc: 'Write the output to FILE'
|
41
|
+
def test
|
42
|
+
Test.new(options).run
|
43
|
+
rescue => e
|
44
|
+
log_error(e)
|
45
|
+
exit(1)
|
46
|
+
end
|
13
47
|
|
14
48
|
desc 'deploy', 'Notify Honeybadger of deployment'
|
15
|
-
|
16
|
-
option :
|
17
|
-
option :
|
18
|
-
option :user, aliases: :'-u',
|
19
|
-
option :api_key, aliases: :'-k', type: :string, desc: 'Api key of your Honeybadger application'
|
49
|
+
project_options
|
50
|
+
option :repository, required: true, type: :string, aliases: :'-r', desc: 'The address of your repository'
|
51
|
+
option :revision, required: true, type: :string, aliases: :'-s', desc: 'The revision/sha that is being deployed'
|
52
|
+
option :user, required: true, type: :string, aliases: :'-u', default: ENV['USER'] || ENV['USERNAME'], desc: 'The local user who is deploying'
|
20
53
|
def deploy
|
21
|
-
|
54
|
+
config = build_config(options)
|
22
55
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
ENV['HONEYBADGER_LOGGING_LEVEL'] = '2'
|
27
|
-
ENV['HONEYBADGER_LOGGING_TTY_LEVEL'] = '0'
|
28
|
-
ENV['HONEYBADGER_LOGGING_PATH'] = 'STDOUT'
|
29
|
-
ENV['HONEYBADGER_REPORT_DATA'] = 'true'
|
30
|
-
|
31
|
-
say('Loading configuration')
|
32
|
-
config = Config.new(rails_framework_opts)
|
33
|
-
config.update(api_key: options[:api_key]) if options[:api_key] =~ NOT_BLANK
|
34
|
-
|
35
|
-
unless (payload[:environment] ||= config[:env]) =~ NOT_BLANK
|
36
|
-
say('Unable to determine environment. (see: `honeybadger help deploy`)', :red)
|
37
|
-
exit(1)
|
56
|
+
if config.get(:api_key).to_s =~ BLANK
|
57
|
+
say("No value provided for required options '--api-key'")
|
58
|
+
return
|
38
59
|
end
|
39
60
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
61
|
+
Deploy.new(options, [], config).run
|
62
|
+
rescue => e
|
63
|
+
log_error(e)
|
64
|
+
exit(1)
|
65
|
+
end
|
44
66
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
67
|
+
desc 'notify', 'Notify Honeybadger of an error'
|
68
|
+
project_options
|
69
|
+
option :class, required: true, type: :string, aliases: :'-c', default: 'CLI Notification', desc: 'The class name of the error. (Default: CLI Notification)'
|
70
|
+
option :message, required: true, type: :string, aliases: :'-m', desc: 'The error message.'
|
71
|
+
option :action, required: false, type: :string, aliases: :'-a', desc: 'The action.'
|
72
|
+
option :component, required: false, type: :string, aliases: :'-C', desc: 'The component.'
|
73
|
+
option :fingerprint, required: false, type: :string, aliases: :'-f', desc: 'The component.'
|
74
|
+
option :tags, required: false, type: :string, aliases: :'-t', desc: 'The tags.'
|
75
|
+
option :url, required: false, type: :string, aliases: :'-u', desc: 'The URL.'
|
76
|
+
def notify
|
77
|
+
config = build_config(options)
|
78
|
+
|
79
|
+
if config.get(:api_key).to_s =~ BLANK
|
80
|
+
say("No value provided for required options '--api-key'")
|
81
|
+
return
|
51
82
|
end
|
83
|
+
|
84
|
+
Notify.new(options, [], config).run
|
52
85
|
rescue => e
|
53
|
-
|
86
|
+
log_error(e)
|
54
87
|
exit(1)
|
55
88
|
end
|
56
89
|
|
57
|
-
desc '
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
config =
|
62
|
-
output_config(config.to_hash(options[:default]))
|
63
|
-
end
|
90
|
+
desc 'exec', 'Execute a command. If the exit status is not 0, report the result to Honeybadger'
|
91
|
+
project_options
|
92
|
+
option :quiet, required: false, type: :boolean, aliases: :'-q', default: false, desc: 'Suppress all output unless Honeybdager notification fails.'
|
93
|
+
def exec(*args)
|
94
|
+
config = build_config(options)
|
64
95
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
def test
|
69
|
-
if options[:file]
|
70
|
-
out = StringIO.new
|
71
|
-
$stdout = out
|
72
|
-
|
73
|
-
flush = Proc.new do
|
74
|
-
$stdout = STDOUT
|
75
|
-
File.open(options[:file], 'w+') do |f|
|
76
|
-
out.rewind
|
77
|
-
out.each_line {|l| f.write(l) }
|
78
|
-
end
|
79
|
-
|
80
|
-
say("Output written to #{options[:file]}", :green)
|
81
|
-
end
|
82
|
-
|
83
|
-
Agent.at_exit(&flush)
|
84
|
-
|
85
|
-
at_exit do
|
86
|
-
# If the agent couldn't be started, the callback should happen here
|
87
|
-
# instead.
|
88
|
-
flush.() unless Agent.running?
|
89
|
-
end
|
96
|
+
if config.get(:api_key).to_s =~ BLANK
|
97
|
+
say("No value provided for required options '--api-key'")
|
98
|
+
return
|
90
99
|
end
|
91
100
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
ENV['HONEYBADGER_LOGGING_PATH'] = 'STDOUT'
|
98
|
-
ENV['HONEYBADGER_DEBUG'] = 'true'
|
99
|
-
ENV['HONEYBADGER_REPORT_DATA'] = options[:dry_run] ? 'false' : 'true'
|
101
|
+
Exec.new(options, args, config).run
|
102
|
+
rescue => e
|
103
|
+
log_error(e)
|
104
|
+
exit(1)
|
105
|
+
end
|
100
106
|
|
101
|
-
|
102
|
-
|
103
|
-
output_config(config.to_hash)
|
107
|
+
desc 'heroku SUBCOMMAND ...ARGS', 'Manage Honeybadger on Heroku'
|
108
|
+
subcommand 'heroku', Heroku
|
104
109
|
|
105
|
-
|
106
|
-
Honeybadger.start(config) unless load_rails_env(verbose: true)
|
110
|
+
private
|
107
111
|
|
108
|
-
|
109
|
-
|
112
|
+
def fetch_value(options, key)
|
113
|
+
options[key] == key ? nil : options[key]
|
114
|
+
end
|
110
115
|
|
111
|
-
|
116
|
+
def build_config(options)
|
117
|
+
config = Config.new(logger: Logger.new('/dev/null'))
|
118
|
+
config.set(:api_key, fetch_value(options, 'api_key')) if options.has_key?('api_key')
|
119
|
+
config.set(:env, fetch_value(options, 'environment')) if options.has_key?('environment')
|
120
|
+
config.init!({
|
121
|
+
framework: :cli
|
122
|
+
})
|
123
|
+
config
|
112
124
|
end
|
113
125
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
126
|
+
def log_error(e)
|
127
|
+
case e
|
128
|
+
when *Util::HTTP::ERRORS
|
129
|
+
say(<<-MSG, :red)
|
130
|
+
!! --- Failed to notify Honeybadger ------------------------------------------- !!
|
131
|
+
|
132
|
+
# What happened?
|
133
|
+
|
134
|
+
We encountered an HTTP error while contacting our service. Issues like this are
|
135
|
+
usually temporary.
|
136
|
+
|
137
|
+
# Error details
|
118
138
|
|
119
|
-
|
139
|
+
#{e.class}: #{e.message}\n at #{e.backtrace && e.backtrace.first}
|
120
140
|
|
121
|
-
|
122
|
-
ENV['HONEYBADGER_LOGGING_TTY_LEVEL'] = '0'
|
123
|
-
ENV['HONEYBADGER_LOGGING_PATH'] = 'STDOUT'
|
124
|
-
ENV['HONEYBADGER_REPORT_DATA'] = 'true'
|
141
|
+
# What can I do?
|
125
142
|
|
126
|
-
|
127
|
-
|
143
|
+
- Retry the command.
|
144
|
+
- Make sure you can connect to api.honeybadger.io (`ping api.honeybadger.io`).
|
145
|
+
- If you continue to see this message, email us at support@honeybadger.io
|
146
|
+
(don't forget to attach this output!)
|
128
147
|
|
129
|
-
|
130
|
-
|
148
|
+
!! --- End -------------------------------------------------------------------- !!
|
149
|
+
MSG
|
131
150
|
else
|
132
|
-
say(
|
133
|
-
|
134
|
-
begin
|
135
|
-
config.write
|
136
|
-
rescue Config::ConfigError => e
|
137
|
-
error("Error: Unable to write configuration file:\n\t#{e}")
|
138
|
-
return
|
139
|
-
rescue StandardError => e
|
140
|
-
error("Error: Unable to write configuration file:\n\t#{e.class} -- #{e.message}\n\t#{e.backtrace.join("\n\t")}")
|
141
|
-
return
|
142
|
-
end
|
143
|
-
end
|
151
|
+
say(<<-MSG, :red)
|
152
|
+
!! --- Honeybadger command failed --------------------------------------------- !!
|
144
153
|
|
145
|
-
|
146
|
-
if capfile.read.match(/honeybadger/)
|
147
|
-
say("Detected Honeybadger in Capfile; skipping Capistrano installation.", :yellow)
|
148
|
-
else
|
149
|
-
say("Appending Capistrano tasks to: #{capfile}", :yellow)
|
150
|
-
File.open(capfile, 'a') do |f|
|
151
|
-
f.puts("\nrequire 'capistrano/honeybadger'")
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
154
|
+
# What did you try to do?
|
155
155
|
|
156
|
-
|
157
|
-
|
158
|
-
say('Sending test notice', :yellow)
|
159
|
-
unless Agent.instance && send_test(false)
|
160
|
-
say('Honeybadger is installed, but failed to send a test notice. Try `honeybadger test`.', :red)
|
161
|
-
exit(1)
|
162
|
-
end
|
163
|
-
end
|
156
|
+
You tried to execute the following command:
|
157
|
+
`honeybadger #{ARGV.join(' ')}`
|
164
158
|
|
165
|
-
|
166
|
-
end
|
159
|
+
# What actually happend?
|
167
160
|
|
168
|
-
|
169
|
-
subcommand 'heroku', Heroku
|
161
|
+
We encountered a Ruby exception and were forced to cancel your request.
|
170
162
|
|
171
|
-
|
163
|
+
# Error details
|
172
164
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
say(indent + "Type: #{Config::OPTIONS[dotted_key].fetch(:type, String).name.split('::').last}")
|
184
|
-
say(indent + "Default: #{Config::OPTIONS[dotted_key][:default].inspect}")
|
185
|
-
say(indent + "Current: #{value.inspect}")
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
165
|
+
#{e.class}: #{e.message}
|
166
|
+
#{e.backtrace && e.backtrace.join("\n ")}
|
167
|
+
|
168
|
+
# What can I do?
|
169
|
+
|
170
|
+
- If you're calling the `install` or `test` command in a Rails app, make sure
|
171
|
+
you can boot the Rails console: `bundle exec rails console`.
|
172
|
+
- Retry the command.
|
173
|
+
- If you continue to see this message, email us at support@honeybadger.io
|
174
|
+
(don't forget to attach this output!)
|
189
175
|
|
190
|
-
|
191
|
-
|
192
|
-
number.times { s << "\s\s" }
|
176
|
+
!! --- End -------------------------------------------------------------------- !!
|
177
|
+
MSG
|
193
178
|
end
|
194
179
|
end
|
195
180
|
end
|