exception_notification 4.2.0 → 4.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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