exception_notification 4.2.0 → 4.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +5 -5
  2. data/Appraisals +4 -3
  3. data/CHANGELOG.rdoc +57 -1
  4. data/CONTRIBUTING.md +21 -2
  5. data/Gemfile +3 -1
  6. data/README.md +106 -789
  7. data/Rakefile +4 -2
  8. data/docs/notifiers/campfire.md +50 -0
  9. data/docs/notifiers/custom.md +42 -0
  10. data/docs/notifiers/datadog.md +51 -0
  11. data/docs/notifiers/email.md +195 -0
  12. data/docs/notifiers/google_chat.md +31 -0
  13. data/docs/notifiers/hipchat.md +66 -0
  14. data/docs/notifiers/irc.md +97 -0
  15. data/docs/notifiers/mattermost.md +115 -0
  16. data/docs/notifiers/slack.md +161 -0
  17. data/docs/notifiers/sns.md +37 -0
  18. data/docs/notifiers/teams.md +54 -0
  19. data/docs/notifiers/webhook.md +60 -0
  20. data/examples/sample_app.rb +56 -0
  21. data/examples/sinatra/Gemfile +8 -6
  22. data/examples/sinatra/config.ru +3 -1
  23. data/examples/sinatra/sinatra_app.rb +19 -11
  24. data/exception_notification.gemspec +30 -23
  25. data/gemfiles/rails4_0.gemfile +1 -2
  26. data/gemfiles/rails4_1.gemfile +1 -2
  27. data/gemfiles/rails4_2.gemfile +1 -2
  28. data/gemfiles/rails5_0.gemfile +1 -2
  29. data/gemfiles/rails5_1.gemfile +7 -0
  30. data/gemfiles/rails5_2.gemfile +7 -0
  31. data/gemfiles/rails6_0.gemfile +7 -0
  32. data/lib/exception_notification.rb +3 -0
  33. data/lib/exception_notification/rack.rb +34 -27
  34. data/lib/exception_notification/rails.rb +3 -0
  35. data/lib/exception_notification/resque.rb +10 -10
  36. data/lib/exception_notification/sidekiq.rb +10 -12
  37. data/lib/exception_notification/version.rb +5 -0
  38. data/lib/exception_notifier.rb +79 -11
  39. data/lib/exception_notifier/base_notifier.rb +10 -5
  40. data/lib/exception_notifier/campfire_notifier.rb +14 -9
  41. data/lib/exception_notifier/datadog_notifier.rb +156 -0
  42. data/lib/exception_notifier/email_notifier.rb +78 -87
  43. data/lib/exception_notifier/google_chat_notifier.rb +44 -0
  44. data/lib/exception_notifier/hipchat_notifier.rb +16 -10
  45. data/lib/exception_notifier/irc_notifier.rb +38 -31
  46. data/lib/exception_notifier/mattermost_notifier.rb +54 -131
  47. data/lib/exception_notifier/modules/backtrace_cleaner.rb +2 -2
  48. data/lib/exception_notifier/modules/error_grouping.rb +87 -0
  49. data/lib/exception_notifier/modules/formatter.rb +121 -0
  50. data/lib/exception_notifier/notifier.rb +9 -6
  51. data/lib/exception_notifier/slack_notifier.rb +75 -32
  52. data/lib/exception_notifier/sns_notifier.rb +86 -0
  53. data/lib/exception_notifier/teams_notifier.rb +200 -0
  54. data/lib/exception_notifier/views/exception_notifier/_backtrace.html.erb +1 -1
  55. data/lib/exception_notifier/views/exception_notifier/_environment.text.erb +1 -1
  56. data/lib/exception_notifier/views/exception_notifier/_request.text.erb +1 -1
  57. data/lib/exception_notifier/views/exception_notifier/background_exception_notification.text.erb +9 -9
  58. data/lib/exception_notifier/views/exception_notifier/exception_notification.html.erb +2 -4
  59. data/lib/exception_notifier/views/exception_notifier/exception_notification.text.erb +2 -2
  60. data/lib/exception_notifier/webhook_notifier.rb +19 -16
  61. data/lib/generators/exception_notification/install_generator.rb +11 -5
  62. data/lib/generators/exception_notification/templates/{exception_notification.rb → exception_notification.rb.erb} +14 -12
  63. data/test/exception_notification/rack_test.rb +90 -4
  64. data/test/exception_notification/resque_test.rb +54 -0
  65. data/test/exception_notifier/campfire_notifier_test.rb +66 -39
  66. data/test/exception_notifier/datadog_notifier_test.rb +153 -0
  67. data/test/exception_notifier/email_notifier_test.rb +301 -145
  68. data/test/exception_notifier/google_chat_notifier_test.rb +185 -0
  69. data/test/exception_notifier/hipchat_notifier_test.rb +112 -65
  70. data/test/exception_notifier/irc_notifier_test.rb +48 -30
  71. data/test/exception_notifier/mattermost_notifier_test.rb +218 -55
  72. data/test/exception_notifier/modules/error_grouping_test.rb +167 -0
  73. data/test/exception_notifier/modules/formatter_test.rb +152 -0
  74. data/test/exception_notifier/sidekiq_test.rb +9 -6
  75. data/test/exception_notifier/slack_notifier_test.rb +109 -59
  76. data/test/exception_notifier/sns_notifier_test.rb +123 -0
  77. data/test/exception_notifier/teams_notifier_test.rb +92 -0
  78. data/test/exception_notifier/webhook_notifier_test.rb +68 -38
  79. data/test/exception_notifier_test.rb +220 -37
  80. data/test/support/exception_notifier_helper.rb +14 -0
  81. data/test/{dummy/app → support}/views/exception_notifier/_new_bkg_section.html.erb +0 -0
  82. data/test/{dummy/app → support}/views/exception_notifier/_new_bkg_section.text.erb +0 -0
  83. data/test/{dummy/app → support}/views/exception_notifier/_new_section.html.erb +0 -0
  84. data/test/{dummy/app → support}/views/exception_notifier/_new_section.text.erb +0 -0
  85. data/test/test_helper.rb +14 -13
  86. metadata +154 -162
  87. data/test/dummy/.gitignore +0 -4
  88. data/test/dummy/Rakefile +0 -7
  89. data/test/dummy/app/controllers/application_controller.rb +0 -3
  90. data/test/dummy/app/controllers/posts_controller.rb +0 -30
  91. data/test/dummy/app/helpers/application_helper.rb +0 -2
  92. data/test/dummy/app/helpers/posts_helper.rb +0 -2
  93. data/test/dummy/app/models/post.rb +0 -2
  94. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  95. data/test/dummy/app/views/posts/_form.html.erb +0 -0
  96. data/test/dummy/app/views/posts/new.html.erb +0 -0
  97. data/test/dummy/app/views/posts/show.html.erb +0 -0
  98. data/test/dummy/config.ru +0 -4
  99. data/test/dummy/config/application.rb +0 -42
  100. data/test/dummy/config/boot.rb +0 -6
  101. data/test/dummy/config/database.yml +0 -22
  102. data/test/dummy/config/environment.rb +0 -17
  103. data/test/dummy/config/environments/development.rb +0 -25
  104. data/test/dummy/config/environments/production.rb +0 -50
  105. data/test/dummy/config/environments/test.rb +0 -38
  106. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  107. data/test/dummy/config/initializers/inflections.rb +0 -10
  108. data/test/dummy/config/initializers/mime_types.rb +0 -5
  109. data/test/dummy/config/initializers/secret_token.rb +0 -8
  110. data/test/dummy/config/initializers/session_store.rb +0 -8
  111. data/test/dummy/config/locales/en.yml +0 -5
  112. data/test/dummy/config/routes.rb +0 -3
  113. data/test/dummy/db/migrate/20110729022608_create_posts.rb +0 -15
  114. data/test/dummy/db/schema.rb +0 -24
  115. data/test/dummy/db/seeds.rb +0 -7
  116. data/test/dummy/lib/tasks/.gitkeep +0 -0
  117. data/test/dummy/public/404.html +0 -26
  118. data/test/dummy/public/422.html +0 -26
  119. data/test/dummy/public/500.html +0 -26
  120. data/test/dummy/public/favicon.ico +0 -0
  121. data/test/dummy/public/images/rails.png +0 -0
  122. data/test/dummy/public/index.html +0 -239
  123. data/test/dummy/public/javascripts/application.js +0 -2
  124. data/test/dummy/public/javascripts/controls.js +0 -965
  125. data/test/dummy/public/javascripts/dragdrop.js +0 -974
  126. data/test/dummy/public/javascripts/effects.js +0 -1123
  127. data/test/dummy/public/javascripts/prototype.js +0 -6001
  128. data/test/dummy/public/javascripts/rails.js +0 -191
  129. data/test/dummy/public/robots.txt +0 -5
  130. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  131. data/test/dummy/public/stylesheets/scaffold.css +0 -56
  132. data/test/dummy/script/rails +0 -6
  133. data/test/dummy/test/functional/posts_controller_test.rb +0 -218
  134. data/test/dummy/test/test_helper.rb +0 -7
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
  require 'carrier-pigeon'
3
5
 
4
6
  class IrcNotifierTest < ActiveSupport::TestCase
5
-
6
- test "should send irc notification if properly configured" do
7
+ test 'should send irc notification if properly configured' do
7
8
  options = {
8
- :domain => 'irc.example.com'
9
+ domain: 'irc.example.com'
9
10
  }
10
11
 
11
12
  CarrierPigeon.expects(:send).with(has_key(:uri)) do |v|
@@ -16,13 +17,30 @@ class IrcNotifierTest < ActiveSupport::TestCase
16
17
  irc.call(fake_exception)
17
18
  end
18
19
 
19
- test "should call pre/post_callback if specified" do
20
- pre_callback_called, post_callback_called = 0,0
20
+ test 'should exclude errors count in message if :accumulated_errors_count nil' do
21
+ irc = ExceptionNotifier::IrcNotifier.new({})
22
+ irc.stubs(:active?).returns(true)
23
+
24
+ irc.expects(:send_message).with { |message| message.include?('divided by 0') }.once
25
+ irc.call(fake_exception)
26
+ end
27
+
28
+ test 'should include errors count in message if :accumulated_errors_count is 3' do
29
+ irc = ExceptionNotifier::IrcNotifier.new({})
30
+ irc.stubs(:active?).returns(true)
31
+
32
+ irc.expects(:send_message).with { |message| message.include?("(3 times)'divided by 0'") }.once
33
+ irc.call(fake_exception, accumulated_errors_count: 3)
34
+ end
35
+
36
+ test 'should call pre/post_callback if specified' do
37
+ pre_callback_called = 0
38
+ post_callback_called = 0
21
39
 
22
40
  options = {
23
- :domain => 'irc.example.com',
24
- :pre_callback => proc { |*| pre_callback_called += 1},
25
- :post_callback => proc { |*| post_callback_called += 1}
41
+ domain: 'irc.example.com',
42
+ pre_callback: proc { |*| pre_callback_called += 1 },
43
+ post_callback: proc { |*| post_callback_called += 1 }
26
44
  }
27
45
 
28
46
  CarrierPigeon.expects(:send).with(has_key(:uri)) do |v|
@@ -35,9 +53,9 @@ class IrcNotifierTest < ActiveSupport::TestCase
35
53
  assert_equal(1, post_callback_called)
36
54
  end
37
55
 
38
- test "should send irc notification without backtrace info if properly configured" do
56
+ test 'should send irc notification without backtrace info if properly configured' do
39
57
  options = {
40
- :domain => 'irc.example.com'
58
+ domain: 'irc.example.com'
41
59
  }
42
60
 
43
61
  CarrierPigeon.expects(:send).with(has_key(:uri)) do |v|
@@ -48,25 +66,25 @@ class IrcNotifierTest < ActiveSupport::TestCase
48
66
  irc.call(fake_exception_without_backtrace)
49
67
  end
50
68
 
51
- test "should properly construct URI from constituent parts" do
69
+ test 'should properly construct URI from constituent parts' do
52
70
  options = {
53
- :nick => 'BadNewsBot',
54
- :password => 'secret',
55
- :domain => 'irc.example.com',
56
- :port => 9999,
57
- :channel => '#exceptions'
71
+ nick: 'BadNewsBot',
72
+ password: 'secret',
73
+ domain: 'irc.example.com',
74
+ port: 9999,
75
+ channel: '#exceptions'
58
76
  }
59
77
 
60
- CarrierPigeon.expects(:send).with(has_entry(uri: "irc://BadNewsBot:secret@irc.example.com:9999/#exceptions"))
78
+ CarrierPigeon.expects(:send).with(has_entry(uri: 'irc://BadNewsBot:secret@irc.example.com:9999/#exceptions'))
61
79
 
62
80
  irc = ExceptionNotifier::IrcNotifier.new(options)
63
81
  irc.call(fake_exception)
64
82
  end
65
83
 
66
- test "should properly add recipients if specified" do
84
+ test 'should properly add recipients if specified' do
67
85
  options = {
68
86
  domain: 'irc.example.com',
69
- recipients: ['peter', 'michael', 'samir']
87
+ recipients: %w[peter michael samir]
70
88
  }
71
89
 
72
90
  CarrierPigeon.expects(:send).with(has_key(:uri)) do |v|
@@ -77,7 +95,7 @@ class IrcNotifierTest < ActiveSupport::TestCase
77
95
  irc.call(fake_exception)
78
96
  end
79
97
 
80
- test "should properly set miscellaneous options" do
98
+ test 'should properly set miscellaneous options' do
81
99
  options = {
82
100
  domain: 'irc.example.com',
83
101
  ssl: true,
@@ -86,11 +104,13 @@ class IrcNotifierTest < ActiveSupport::TestCase
86
104
  prefix: '[test notification]'
87
105
  }
88
106
 
89
- CarrierPigeon.expects(:send).with(has_entries(
107
+ entries = {
90
108
  ssl: true,
91
109
  join: true,
92
- notice: true,
93
- )) do |v|
110
+ notice: true
111
+ }
112
+
113
+ CarrierPigeon.expects(:send).with(has_entries(entries)) do |v|
94
114
  /\[test notification\]/.match(v[:message])
95
115
  end
96
116
 
@@ -98,8 +118,8 @@ class IrcNotifierTest < ActiveSupport::TestCase
98
118
  irc.call(fake_exception)
99
119
  end
100
120
 
101
- test "should not send irc notification if badly configured" do
102
- wrong_params = { domain: '##scriptkiddie.com###'}
121
+ test 'should not send irc notification if badly configured' do
122
+ wrong_params = { domain: '##scriptkiddie.com###' }
103
123
  irc = ExceptionNotifier::IrcNotifier.new(wrong_params)
104
124
 
105
125
  assert_nil irc.call(fake_exception)
@@ -108,11 +128,9 @@ class IrcNotifierTest < ActiveSupport::TestCase
108
128
  private
109
129
 
110
130
  def fake_exception
111
- exception = begin
112
- 5/0
113
- rescue Exception => e
114
- e
115
- end
131
+ 5 / 0
132
+ rescue StandardError => e
133
+ e
116
134
  end
117
135
 
118
136
  def fake_exception_without_backtrace
@@ -1,88 +1,251 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
  require 'httparty'
5
+ require 'timecop'
6
+ require 'json'
3
7
 
4
8
  class MattermostNotifierTest < ActiveSupport::TestCase
9
+ URL = 'http://localhost:8000'
10
+
11
+ def setup
12
+ Timecop.freeze('2018-12-09 12:07:16 UTC')
13
+ end
14
+
15
+ def teardown
16
+ Timecop.return
17
+ end
5
18
 
6
- test "should send notification if properly configured" do
7
- options = {
8
- :webhook_url => 'http://localhost:8000'
19
+ test 'should send notification if properly configured' do
20
+ opts = {
21
+ body: default_body.to_json,
22
+ headers: default_headers
9
23
  }
10
- mattermost_notifier = ExceptionNotifier::MattermostNotifier.new
11
- mattermost_notifier.httparty = FakeHTTParty.new
12
24
 
13
- options = mattermost_notifier.call ArgumentError.new("foo"), options
25
+ HTTParty.expects(:post).with(URL, opts)
26
+ notifier.call ArgumentError.new('foo')
27
+ end
14
28
 
15
- body = ActiveSupport::JSON.decode options[:body]
16
- assert body.has_key? 'text'
17
- assert body.has_key? 'username'
29
+ test 'should send notification with create issue link if specified' do
30
+ body = default_body.merge(
31
+ text: [
32
+ '@channel',
33
+ error_occurred_in,
34
+ 'An *ArgumentError* occurred.',
35
+ '*foo*',
36
+ github_link
37
+ ].join("\n")
38
+ )
39
+
40
+ opts = {
41
+ body: body.to_json,
42
+ headers: default_headers
43
+ }
18
44
 
19
- text = body['text'].split("\n")
20
- assert_equal 4, text.size
21
- assert_equal '@channel', text[0]
22
- assert_equal 'An *ArgumentError* occured.', text[2]
23
- assert_equal '*foo*', text[3]
45
+ HTTParty.expects(:post).with(URL, opts)
46
+ notifier.call ArgumentError.new('foo'), git_url: 'github.com/aschen'
24
47
  end
25
48
 
26
- test "should send notification with create issue link if specified" do
27
- options = {
28
- :webhook_url => 'http://localhost:8000',
29
- :git_url => 'github.com/aschen'
49
+ test 'should add username and icon_url params to the notification if specified' do
50
+ body = default_body.merge(
51
+ username: 'Test Bot',
52
+ icon_url: 'http://site.com/icon.png'
53
+ )
54
+
55
+ opts = {
56
+ body: body.to_json,
57
+ headers: default_headers
30
58
  }
31
- mattermost_notifier = ExceptionNotifier::MattermostNotifier.new
32
- mattermost_notifier.httparty = FakeHTTParty.new
33
59
 
34
- options = mattermost_notifier.call ArgumentError.new("foo"), options
60
+ HTTParty.expects(:post).with(URL, opts)
61
+ notifier.call(
62
+ ArgumentError.new('foo'),
63
+ username: 'Test Bot',
64
+ avatar: 'http://site.com/icon.png'
65
+ )
66
+ end
35
67
 
36
- body = ActiveSupport::JSON.decode options[:body]
68
+ test 'should add other HTTParty options to params' do
69
+ opts = {
70
+ basic_auth: {
71
+ username: 'clara',
72
+ password: 'password'
73
+ },
74
+ body: default_body.to_json,
75
+ headers: default_headers
76
+ }
37
77
 
38
- text = body['text'].split("\n")
39
- assert_equal 5, text.size
40
- assert_equal '[Create an issue](github.com/aschen/dummy/issues/new/?issue%5Btitle%5D=%5BBUG%5D+Error+500+%3A++%28ArgumentError%29+foo)', text[4]
78
+ HTTParty.expects(:post).with(URL, opts)
79
+ notifier.call(
80
+ ArgumentError.new('foo'),
81
+ basic_auth: {
82
+ username: 'clara',
83
+ password: 'password'
84
+ }
85
+ )
41
86
  end
42
87
 
43
- test 'should add username and icon_url params to the notification if specified' do
44
- options = {
45
- :webhook_url => 'http://localhost:8000',
46
- :username => "Test Bot",
47
- :avatar => 'http://site.com/icon.png'
88
+ test "should use 'An' for exceptions count if :accumulated_errors_count option is nil" do
89
+ opts = {
90
+ body: default_body.to_json,
91
+ headers: default_headers
48
92
  }
49
- mattermost_notifier = ExceptionNotifier::MattermostNotifier.new
50
- mattermost_notifier.httparty = FakeHTTParty.new
51
93
 
52
- options = mattermost_notifier.call ArgumentError.new("foo"), options
94
+ HTTParty.expects(:post).with(URL, opts)
95
+ notifier.call(ArgumentError.new('foo'))
96
+ end
53
97
 
54
- body = ActiveSupport::JSON.decode options[:body]
98
+ test 'shoud use direct errors count if :accumulated_errors_count option is 5' do
99
+ body = default_body.merge(
100
+ text: [
101
+ '@channel',
102
+ error_occurred_in,
103
+ '5 *ArgumentError* occurred.',
104
+ '*foo*'
105
+ ].join("\n")
106
+ )
107
+
108
+ opts = {
109
+ body: body.to_json,
110
+ headers: default_headers
111
+ }
55
112
 
56
- assert_equal 'Test Bot', body['username']
57
- assert_equal 'http://site.com/icon.png', body['icon_url']
113
+ HTTParty.expects(:post).with(URL, opts)
114
+ notifier.call(ArgumentError.new('foo'), accumulated_errors_count: 5)
58
115
  end
59
116
 
60
- test 'should add other HTTParty options to params' do
61
- options = {
62
- :webhook_url => 'http://localhost:8000',
63
- :username => "Test Bot",
64
- :avatar => 'http://site.com/icon.png',
65
- :basic_auth => {
66
- :username => 'clara',
67
- :password => 'password'
68
- }
117
+ test 'should include backtrace and request info' do
118
+ body = default_body.merge(text: [
119
+ '@channel',
120
+ error_occurred_in,
121
+ 'An *ArgumentError* occurred.',
122
+ '*foo*',
123
+ request_info,
124
+ backtrace_info
125
+ ].join("\n"))
126
+
127
+ opts = {
128
+ body: body.to_json,
129
+ headers: default_headers
69
130
  }
70
- mattermost_notifier = ExceptionNotifier::MattermostNotifier.new
71
- mattermost_notifier.httparty = FakeHTTParty.new
72
131
 
73
- options = mattermost_notifier.call ArgumentError.new("foo"), options
132
+ HTTParty.expects(:post).with(URL, opts)
133
+
134
+ exception = ArgumentError.new('foo')
135
+ exception.set_backtrace([
136
+ "app/controllers/my_controller.rb:53:in `my_controller_params'",
137
+ "app/controllers/my_controller.rb:34:in `update'"
138
+ ])
74
139
 
75
- assert options.has_key? :basic_auth
76
- assert 'clara', options[:basic_auth][:username]
77
- assert 'password', options[:basic_auth][:password]
140
+ notifier.call(exception, env: test_env)
78
141
  end
79
142
 
80
- end
143
+ test 'should include exception_data_info' do
144
+ body = default_body.merge(
145
+ text: [
146
+ '@channel',
147
+ error_occurred_in,
148
+ 'An *ArgumentError* occurred.',
149
+ '*foo*',
150
+ request_info,
151
+ exception_data_info
152
+ ].join("\n")
153
+ )
154
+
155
+ opts = {
156
+ body: body.to_json,
157
+ headers: default_headers
158
+ }
81
159
 
82
- class FakeHTTParty
160
+ env = test_env.merge(
161
+ 'exception_notifier.exception_data' => { foo: 'bar', john: 'doe' }
162
+ )
83
163
 
84
- def post(url, options)
85
- return options
164
+ HTTParty.expects(:post).with(URL, opts)
165
+ notifier.call(ArgumentError.new('foo'), env: env)
86
166
  end
87
167
 
168
+ private
169
+
170
+ def notifier
171
+ ExceptionNotifier::MattermostNotifier.new(webhook_url: URL)
172
+ end
173
+
174
+ def default_body
175
+ {
176
+ text: [
177
+ '@channel',
178
+ error_occurred_in,
179
+ 'An *ArgumentError* occurred.',
180
+ '*foo*'
181
+ ].join("\n"),
182
+ username: 'Exception Notifier'
183
+ }
184
+ end
185
+
186
+ def default_headers
187
+ { 'Content-Type' => 'application/json' }
188
+ end
189
+
190
+ def test_env
191
+ Rack::MockRequest.env_for(
192
+ '/',
193
+ 'HTTP_HOST' => 'test.address',
194
+ 'REMOTE_ADDR' => '127.0.0.1',
195
+ 'HTTP_USER_AGENT' => 'Rails Testing',
196
+ params: { id: 'foo' }
197
+ )
198
+ end
199
+
200
+ def error_occurred_in
201
+ if defined?(::Rails) && ::Rails.respond_to?(:env)
202
+ '### ⚠️ Error occurred in test ⚠️'
203
+ else
204
+ '### ⚠️ Error occurred ⚠️'
205
+ end
206
+ end
207
+
208
+ def github_link
209
+ if defined?(::Rails) && ::Rails.respond_to?(:application)
210
+ '[Create an issue]' \
211
+ '(github.com/aschen/dummy/issues/new/?issue%5Btitle%5D=%5BBUG%5D+Error+500+%3A++%28ArgumentError%29+foo)'
212
+ else
213
+ # TODO: fix missing app name
214
+ '[Create an issue]' \
215
+ '(github.com/aschen//issues/new/?issue%5Btitle%5D=%5BBUG%5D+Error+500+%3A++%28ArgumentError%29+foo)'
216
+ end
217
+ end
218
+
219
+ def request_info
220
+ [
221
+ '### Request',
222
+ '```',
223
+ '* url : http://test.address/?id=foo',
224
+ '* http_method : GET',
225
+ '* ip_address : 127.0.0.1',
226
+ '* parameters : {"id"=>"foo"}',
227
+ '* timestamp : 2018-12-09 12:07:16 UTC',
228
+ '```'
229
+ ]
230
+ end
231
+
232
+ def backtrace_info
233
+ [
234
+ '### Backtrace',
235
+ '```',
236
+ "* app/controllers/my_controller.rb:53:in `my_controller_params'",
237
+ "* app/controllers/my_controller.rb:34:in `update'",
238
+ '```'
239
+ ]
240
+ end
241
+
242
+ def exception_data_info
243
+ [
244
+ '### Data',
245
+ '```',
246
+ '* foo : bar',
247
+ '* john : doe',
248
+ '```'
249
+ ]
250
+ end
88
251
  end