exception_notification 4.3.0 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +2 -2
  3. data/CHANGELOG.rdoc +14 -0
  4. data/CONTRIBUTING.md +18 -0
  5. data/Gemfile +1 -1
  6. data/README.md +64 -935
  7. data/Rakefile +2 -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 +54 -0
  21. data/examples/sinatra/Gemfile +6 -6
  22. data/examples/sinatra/config.ru +1 -1
  23. data/examples/sinatra/sinatra_app.rb +14 -10
  24. data/exception_notification.gemspec +27 -22
  25. data/gemfiles/rails4_0.gemfile +3 -3
  26. data/gemfiles/rails4_1.gemfile +3 -3
  27. data/gemfiles/rails4_2.gemfile +3 -3
  28. data/gemfiles/rails5_0.gemfile +3 -3
  29. data/gemfiles/rails5_1.gemfile +3 -3
  30. data/gemfiles/rails5_2.gemfile +7 -0
  31. data/gemfiles/rails6_0.gemfile +7 -0
  32. data/lib/exception_notification.rb +1 -0
  33. data/lib/exception_notification/rack.rb +8 -21
  34. data/lib/exception_notification/resque.rb +8 -10
  35. data/lib/exception_notification/sidekiq.rb +8 -12
  36. data/lib/exception_notification/version.rb +3 -0
  37. data/lib/exception_notifier.rb +20 -3
  38. data/lib/exception_notifier/base_notifier.rb +2 -3
  39. data/lib/exception_notifier/campfire_notifier.rb +12 -13
  40. data/lib/exception_notifier/datadog_notifier.rb +153 -0
  41. data/lib/exception_notifier/email_notifier.rb +64 -87
  42. data/lib/exception_notifier/google_chat_notifier.rb +25 -119
  43. data/lib/exception_notifier/hipchat_notifier.rb +11 -12
  44. data/lib/exception_notifier/irc_notifier.rb +32 -30
  45. data/lib/exception_notifier/mattermost_notifier.rb +47 -140
  46. data/lib/exception_notifier/modules/backtrace_cleaner.rb +0 -2
  47. data/lib/exception_notifier/modules/error_grouping.rb +5 -5
  48. data/lib/exception_notifier/modules/formatter.rb +118 -0
  49. data/lib/exception_notifier/notifier.rb +5 -6
  50. data/lib/exception_notifier/slack_notifier.rb +63 -40
  51. data/lib/exception_notifier/sns_notifier.rb +17 -11
  52. data/lib/exception_notifier/teams_notifier.rb +58 -44
  53. data/lib/exception_notifier/views/exception_notifier/_backtrace.html.erb +1 -1
  54. data/lib/exception_notifier/views/exception_notifier/_environment.text.erb +1 -1
  55. data/lib/exception_notifier/views/exception_notifier/_request.text.erb +1 -1
  56. data/lib/exception_notifier/views/exception_notifier/exception_notification.html.erb +2 -2
  57. data/lib/exception_notifier/views/exception_notifier/exception_notification.text.erb +2 -2
  58. data/lib/exception_notifier/webhook_notifier.rb +14 -11
  59. data/lib/generators/exception_notification/install_generator.rb +5 -5
  60. data/lib/generators/exception_notification/templates/{exception_notification.rb → exception_notification.rb.erb} +13 -11
  61. data/test/exception_notification/rack_test.rb +27 -11
  62. data/test/exception_notification/resque_test.rb +52 -0
  63. data/test/exception_notifier/campfire_notifier_test.rb +42 -42
  64. data/test/exception_notifier/datadog_notifier_test.rb +151 -0
  65. data/test/exception_notifier/email_notifier_test.rb +269 -153
  66. data/test/exception_notifier/google_chat_notifier_test.rb +154 -101
  67. data/test/exception_notifier/hipchat_notifier_test.rb +78 -81
  68. data/test/exception_notifier/irc_notifier_test.rb +34 -34
  69. data/test/exception_notifier/mattermost_notifier_test.rb +164 -67
  70. data/test/exception_notifier/modules/error_grouping_test.rb +39 -40
  71. data/test/exception_notifier/modules/formatter_test.rb +150 -0
  72. data/test/exception_notifier/sidekiq_test.rb +6 -6
  73. data/test/exception_notifier/slack_notifier_test.rb +61 -60
  74. data/test/exception_notifier/sns_notifier_test.rb +27 -32
  75. data/test/exception_notifier/teams_notifier_test.rb +23 -26
  76. data/test/exception_notifier/webhook_notifier_test.rb +48 -46
  77. data/test/exception_notifier_test.rb +41 -38
  78. data/test/{dummy/app → support}/views/exception_notifier/_new_bkg_section.html.erb +0 -0
  79. data/test/{dummy/app → support}/views/exception_notifier/_new_bkg_section.text.erb +0 -0
  80. data/test/{dummy/app → support}/views/exception_notifier/_new_section.html.erb +0 -0
  81. data/test/{dummy/app → support}/views/exception_notifier/_new_section.text.erb +0 -0
  82. data/test/test_helper.rb +11 -14
  83. metadata +136 -166
  84. data/test/dummy/.gitignore +0 -4
  85. data/test/dummy/Rakefile +0 -7
  86. data/test/dummy/app/controllers/application_controller.rb +0 -3
  87. data/test/dummy/app/controllers/posts_controller.rb +0 -30
  88. data/test/dummy/app/helpers/application_helper.rb +0 -2
  89. data/test/dummy/app/helpers/posts_helper.rb +0 -2
  90. data/test/dummy/app/models/post.rb +0 -2
  91. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  92. data/test/dummy/app/views/posts/_form.html.erb +0 -0
  93. data/test/dummy/app/views/posts/new.html.erb +0 -0
  94. data/test/dummy/app/views/posts/show.html.erb +0 -0
  95. data/test/dummy/config.ru +0 -4
  96. data/test/dummy/config/application.rb +0 -42
  97. data/test/dummy/config/boot.rb +0 -6
  98. data/test/dummy/config/database.yml +0 -22
  99. data/test/dummy/config/environment.rb +0 -17
  100. data/test/dummy/config/environments/development.rb +0 -25
  101. data/test/dummy/config/environments/production.rb +0 -50
  102. data/test/dummy/config/environments/test.rb +0 -35
  103. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  104. data/test/dummy/config/initializers/inflections.rb +0 -10
  105. data/test/dummy/config/initializers/mime_types.rb +0 -5
  106. data/test/dummy/config/initializers/secret_token.rb +0 -8
  107. data/test/dummy/config/initializers/session_store.rb +0 -8
  108. data/test/dummy/config/locales/en.yml +0 -5
  109. data/test/dummy/config/routes.rb +0 -3
  110. data/test/dummy/db/migrate/20110729022608_create_posts.rb +0 -15
  111. data/test/dummy/db/schema.rb +0 -24
  112. data/test/dummy/db/seeds.rb +0 -7
  113. data/test/dummy/lib/tasks/.gitkeep +0 -0
  114. data/test/dummy/public/404.html +0 -26
  115. data/test/dummy/public/422.html +0 -26
  116. data/test/dummy/public/500.html +0 -26
  117. data/test/dummy/public/favicon.ico +0 -0
  118. data/test/dummy/public/images/rails.png +0 -0
  119. data/test/dummy/public/index.html +0 -239
  120. data/test/dummy/public/javascripts/application.js +0 -2
  121. data/test/dummy/public/javascripts/controls.js +0 -965
  122. data/test/dummy/public/javascripts/dragdrop.js +0 -974
  123. data/test/dummy/public/javascripts/effects.js +0 -1123
  124. data/test/dummy/public/javascripts/prototype.js +0 -6001
  125. data/test/dummy/public/javascripts/rails.js +0 -191
  126. data/test/dummy/public/robots.txt +0 -5
  127. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  128. data/test/dummy/public/stylesheets/scaffold.css +0 -56
  129. data/test/dummy/script/rails +0 -6
  130. data/test/dummy/test/functional/posts_controller_test.rb +0 -237
  131. data/test/dummy/test/test_helper.rb +0 -7
@@ -1,136 +1,42 @@
1
- require 'action_dispatch'
2
- require 'active_support/core_ext/time'
1
+ require 'httparty'
3
2
 
4
3
  module ExceptionNotifier
5
- class GoogleChatNotifier
6
- include ExceptionNotifier::BacktraceCleaner
4
+ class GoogleChatNotifier < BaseNotifier
5
+ def call(exception, opts = {})
6
+ options = base_options.merge(opts)
7
+ formatter = Formatter.new(exception, options)
7
8
 
8
- class MissingController
9
- def method_missing(*args, &block)
10
- end
11
- end
12
-
13
- attr_accessor :httparty
14
-
15
- def initialize(options = {})
16
- super()
17
- @default_options = options
18
- @httparty = HTTParty
19
- end
20
-
21
- def call(exception, options = {})
22
- @options = options.merge(@default_options)
23
- @exception = exception
24
- @backtrace = exception.backtrace ? clean_backtrace(exception) : nil
25
-
26
- @env = @options.delete(:env)
27
-
28
- @application_name = @options.delete(:app_name) || Rails.application.class.parent_name.underscore
29
-
30
- @webhook_url = @options.delete(:webhook_url)
31
- raise ArgumentError.new "You must provide 'webhook_url' parameter." unless @webhook_url
32
-
33
- unless @env.nil?
34
- @controller = @env['action_controller.instance'] || MissingController.new
35
-
36
- request = ActionDispatch::Request.new(@env)
37
-
38
- @request_items = { url: request.original_url,
39
- http_method: request.method,
40
- ip_address: request.remote_ip,
41
- parameters: request.filtered_parameters,
42
- timestamp: Time.current }
43
- else
44
- @controller = @request_items = nil
45
- end
46
-
47
-
48
- @options[:body] = payload.to_json
49
- @options[:headers] ||= {}
50
- @options[:headers].merge!({ 'Content-Type' => 'application/json' })
51
-
52
- @httparty.post(@webhook_url, @options)
9
+ HTTParty.post(
10
+ options[:webhook_url],
11
+ body: { text: body(exception, formatter) }.to_json,
12
+ headers: { 'Content-Type' => 'application/json' }
13
+ )
53
14
  end
54
15
 
55
16
  private
56
17
 
57
- def payload
58
- {
59
- text: exception_text
60
- }
61
- end
62
-
63
- def header
64
- errors_count = @options[:accumulated_errors_count].to_i
65
- text = ['']
66
-
67
- text << "Application: *#{@application_name}*"
68
- text << "#{errors_count > 1 ? errors_count : 'An'} *#{@exception.class}* occured" + if @controller then " in *#{controller_and_method}*." else "." end
69
-
70
- text
71
- end
72
-
73
- def exception_text
74
- text = []
75
-
76
- text << header
77
- text << ''
18
+ def body(exception, formatter)
19
+ text = [
20
+ "\nApplication: *#{formatter.app_name}*",
21
+ formatter.subtitle,
22
+ '',
23
+ formatter.title,
24
+ "*#{exception.message.tr('`', "'")}*"
25
+ ]
78
26
 
79
- text << "⚠️ Error 500 in #{Rails.env} ⚠️"
80
- text << "*#{@exception.message.gsub('`', %q('))}*"
81
-
82
- if @request_items
27
+ if (request = formatter.request_message.presence)
83
28
  text << ''
84
- text += message_request
29
+ text << '*Request:*'
30
+ text << request
85
31
  end
86
32
 
87
- if @backtrace
33
+ if (backtrace = formatter.backtrace_message.presence)
88
34
  text << ''
89
- text += message_backtrace
90
- end
91
-
92
- text.join("\n")
93
- end
94
-
95
- def message_request
96
- text = []
97
-
98
- text << "*Request:*"
99
- text << "```"
100
- text << hash_presentation(@request_items)
101
- text << "```"
102
-
103
- text
104
- end
105
-
106
- def hash_presentation(hash)
107
- text = []
108
-
109
- hash.each do |key, value|
110
- text << "* #{key} : #{value}"
35
+ text << '*Backtrace:*'
36
+ text << backtrace
111
37
  end
112
38
 
113
- text.join("\n")
114
- end
115
-
116
- def message_backtrace(size = 3)
117
- text = []
118
-
119
- size = @backtrace.size < size ? @backtrace.size : size
120
- text << "*Backtrace:*"
121
- text << "```"
122
- size.times { |i| text << "* " + @backtrace[i] }
123
- text << "```"
124
-
125
- text
126
- end
127
-
128
- def controller_and_method
129
- if @controller
130
- "#{@controller.controller_name}##{@controller.action_name}"
131
- else
132
- ""
133
- end
39
+ text.compact.join("\n")
134
40
  end
135
41
  end
136
42
  end
@@ -1,6 +1,5 @@
1
1
  module ExceptionNotifier
2
2
  class HipchatNotifier < BaseNotifier
3
-
4
3
  attr_accessor :from
5
4
  attr_accessor :room
6
5
  attr_accessor :message_options
@@ -11,29 +10,29 @@ module ExceptionNotifier
11
10
  api_token = options.delete(:api_token)
12
11
  room_name = options.delete(:room_name)
13
12
  opts = {
14
- :api_version => options.delete(:api_version) || 'v1'
15
- }
13
+ api_version: options.delete(:api_version) || 'v1'
14
+ }
16
15
  opts[:server_url] = options.delete(:server_url) if options[:server_url]
17
16
  @from = options.delete(:from) || 'Exception'
18
17
  @room = HipChat::Client.new(api_token, opts)[room_name]
19
- @message_template = options.delete(:message_template) || ->(exception, errors_count) {
18
+ @message_template = options.delete(:message_template) || lambda { |exception, errors_count|
20
19
  msg = if errors_count > 1
21
- "The exception occurred #{errors_count} times: '#{Rack::Utils.escape_html(exception.message)}'"
22
- else
23
- "A new exception occurred: '#{Rack::Utils.escape_html(exception.message)}'"
24
- end
20
+ "The exception occurred #{errors_count} times: '#{Rack::Utils.escape_html(exception.message)}'"
21
+ else
22
+ "A new exception occurred: '#{Rack::Utils.escape_html(exception.message)}'"
23
+ end
25
24
  msg += " on '#{exception.backtrace.first}'" if exception.backtrace
26
25
  msg
27
26
  }
28
- @message_options = options
27
+ @message_options = options
29
28
  @message_options[:color] ||= 'red'
30
- rescue
29
+ rescue StandardError
31
30
  @room = nil
32
31
  end
33
32
  end
34
33
 
35
- def call(exception, options={})
36
- return if !active?
34
+ def call(exception, options = {})
35
+ return unless active?
37
36
 
38
37
  message = @message_template.call(exception, options[:accumulated_errors_count].to_i)
39
38
  send_notice(exception, options, message, @message_options) do |msg, message_opts|
@@ -6,50 +6,52 @@ module ExceptionNotifier
6
6
  parse_options(options)
7
7
  end
8
8
 
9
- def call(exception, options={})
9
+ def call(exception, options = {})
10
10
  errors_count = options[:accumulated_errors_count].to_i
11
11
 
12
12
  message = "'#{exception.message}'"
13
13
  message.prepend("(#{errors_count} times)") if errors_count > 1
14
14
 
15
15
  message += " on '#{exception.backtrace.first}'" if exception.backtrace
16
- if active?
17
- send_notice(exception, options, message) do |msg, _|
18
- send_message([*@config.prefix, *msg].join(' '))
19
- end
16
+
17
+ return unless active?
18
+
19
+ send_notice(exception, options, message) do |msg, _|
20
+ send_message([*@config.prefix, *msg].join(' '))
20
21
  end
21
22
  end
22
23
 
23
24
  def send_message(message)
24
- CarrierPigeon.send @config.irc.merge({message: message})
25
+ CarrierPigeon.send @config.irc.merge(message: message)
25
26
  end
26
27
 
27
28
  private
28
- def parse_options(options)
29
- nick = options.fetch(:nick, 'ExceptionNotifierBot')
30
- password = options[:password] ? ":#{options[:password]}" : nil
31
- domain = options.fetch(:domain, nil)
32
- port = options[:port] ? ":#{options[:port]}" : nil
33
- channel = options.fetch(:channel, '#log')
34
- notice = options.fetch(:notice, false)
35
- ssl = options.fetch(:ssl, false)
36
- join = options.fetch(:join, false)
37
- uri = "irc://#{nick}#{password}@#{domain}#{port}/#{channel}"
38
- prefix = options.fetch(:prefix, nil)
39
- recipients = options[:recipients] ? options[:recipients].join(', ') + ':' : nil
40
-
41
- @config.prefix = [*prefix, *recipients].join(' ')
42
- @config.irc = { uri: uri, ssl: ssl, notice: notice, join: join }
43
- end
44
29
 
45
- def active?
46
- valid_uri? @config.irc[:uri]
47
- end
30
+ def parse_options(options)
31
+ nick = options.fetch(:nick, 'ExceptionNotifierBot')
32
+ password = options[:password] ? ":#{options[:password]}" : nil
33
+ domain = options.fetch(:domain, nil)
34
+ port = options[:port] ? ":#{options[:port]}" : nil
35
+ channel = options.fetch(:channel, '#log')
36
+ notice = options.fetch(:notice, false)
37
+ ssl = options.fetch(:ssl, false)
38
+ join = options.fetch(:join, false)
39
+ uri = "irc://#{nick}#{password}@#{domain}#{port}/#{channel}"
40
+ prefix = options.fetch(:prefix, nil)
41
+ recipients = options[:recipients] ? options[:recipients].join(', ') + ':' : nil
42
+
43
+ @config.prefix = [*prefix, *recipients].join(' ')
44
+ @config.irc = { uri: uri, ssl: ssl, notice: notice, join: join }
45
+ end
48
46
 
49
- def valid_uri?(uri)
50
- !!URI.parse(uri)
51
- rescue URI::InvalidURIError
52
- false
53
- end
47
+ def active?
48
+ valid_uri? @config.irc[:uri]
49
+ end
50
+
51
+ def valid_uri?(uri)
52
+ URI.parse(uri)
53
+ rescue URI::InvalidURIError
54
+ false
55
+ end
54
56
  end
55
57
  end
@@ -1,165 +1,72 @@
1
- require 'action_dispatch'
2
- require 'active_support/core_ext/time'
1
+ require 'httparty'
3
2
 
4
3
  module ExceptionNotifier
5
- class MattermostNotifier
6
- include ExceptionNotifier::BacktraceCleaner
7
-
8
- class MissingController
9
- def method_missing(*args, &block)
10
- end
11
- end
12
-
13
- attr_accessor :httparty
14
-
15
- def initialize(options = {})
16
- super()
17
- @default_options = options
18
- @httparty = HTTParty
19
- end
20
-
21
- def call(exception, options = {})
22
- @options = options.merge(@default_options)
4
+ class MattermostNotifier < BaseNotifier
5
+ def call(exception, opts = {})
6
+ options = opts.merge(base_options)
23
7
  @exception = exception
24
- @backtrace = exception.backtrace ? clean_backtrace(exception) : nil
25
-
26
- @env = @options.delete(:env)
27
8
 
28
- @application_name = @options.delete(:app_name) || Rails.application.class.parent_name.underscore
29
- @gitlab_url = @options.delete(:git_url)
30
- @username = @options.delete(:username) || "Exception Notifier"
31
- @avatar = @options.delete(:avatar)
9
+ @formatter = Formatter.new(exception, options)
32
10
 
33
- @channel = @options.delete(:channel)
34
- @webhook_url = @options.delete(:webhook_url)
35
- raise ArgumentError.new "You must provide 'webhook_url' parameter." unless @webhook_url
11
+ @gitlab_url = options[:git_url]
36
12
 
37
- unless @env.nil?
38
- @controller = @env['action_controller.instance'] || MissingController.new
13
+ payload = {
14
+ text: message_text.compact.join("\n"),
15
+ username: options[:username] || 'Exception Notifier'
16
+ }
39
17
 
40
- request = ActionDispatch::Request.new(@env)
18
+ payload[:icon_url] = options[:avatar] if options[:avatar]
19
+ payload[:channel] = options[:channel] if options[:channel]
41
20
 
42
- @request_items = { url: request.original_url,
43
- http_method: request.method,
44
- ip_address: request.remote_ip,
45
- parameters: request.filtered_parameters,
46
- timestamp: Time.current }
47
-
48
- if request.session["warden.user.user.key"]
49
- current_user = User.find(request.session["warden.user.user.key"][0][0])
50
- @request_items.merge!({ current_user: { id: current_user.id, email: current_user.email } })
51
- end
52
- else
53
- @controller = @request_items = nil
54
- end
21
+ httparty_options = options.except(
22
+ :avatar, :channel, :username, :git_url, :webhook_url,
23
+ :env, :accumulated_errors_count, :app_name
24
+ )
55
25
 
56
- payload = message_text.merge(user_info).merge(channel_info)
26
+ httparty_options[:body] = payload.to_json
27
+ httparty_options[:headers] ||= {}
28
+ httparty_options[:headers]['Content-Type'] = 'application/json'
57
29
 
58
- @options[:body] = payload.to_json
59
- @options[:headers] ||= {}
60
- @options[:headers].merge!({ 'Content-Type' => 'application/json' })
61
-
62
- @httparty.post(@webhook_url, @options)
30
+ HTTParty.post(options[:webhook_url], httparty_options)
63
31
  end
64
32
 
65
33
  private
66
34
 
67
- def channel_info
68
- if @channel
69
- { channel: @channel }
70
- else
71
- {}
72
- end
73
- end
74
-
75
- def user_info
76
- infos = {}
35
+ attr_reader :formatter
77
36
 
78
- infos.merge!({ username: @username }) if @username
79
- infos.merge!({ icon_url: @avatar }) if @avatar
37
+ def message_text
38
+ text = [
39
+ '@channel',
40
+ "### #{formatter.title}",
41
+ formatter.subtitle,
42
+ "*#{@exception.message}*"
43
+ ]
80
44
 
81
- infos
45
+ if (request = formatter.request_message.presence)
46
+ text << '### Request'
47
+ text << request
82
48
  end
83
49
 
84
- def message_text
85
- text = []
86
-
87
- text += ["@channel"]
88
- text += message_header
89
- text += message_request if @request_items
90
- text += message_backtrace if @backtrace
91
- text += message_issue_link if @gitlab_url
92
-
93
- { text: text.join("\n") }
94
- end
95
-
96
- def message_header
97
- text = []
98
-
99
- errors_count = @options[:accumulated_errors_count].to_i
100
- text << "### :warning: Error 500 in #{Rails.env} :warning:"
101
- text << "#{errors_count > 1 ? errors_count : 'An'} *#{@exception.class}* occured" + if @controller then " in *#{controller_and_method}*." else "." end
102
- text << "*#{@exception.message}*"
103
-
104
- text
50
+ if (backtrace = formatter.backtrace_message.presence)
51
+ text << '### Backtrace'
52
+ text << backtrace
105
53
  end
106
54
 
107
- def message_request
108
- text = []
55
+ text << message_issue_link if @gitlab_url
109
56
 
110
- text << "### Request"
111
- text << "```"
112
- text << hash_presentation(@request_items)
113
- text << "```"
114
-
115
- text
116
- end
117
-
118
- def message_backtrace(size = 3)
119
- text = []
120
-
121
- size = @backtrace.size < size ? @backtrace.size : size
122
- text << "### Backtrace"
123
- text << "```"
124
- size.times { |i| text << "* " + @backtrace[i] }
125
- text << "```"
126
-
127
- text
128
- end
129
-
130
- def message_issue_link
131
- text = []
132
-
133
- link = [@gitlab_url, @application_name, "issues", "new"].join("/")
134
- params = {
135
- "issue[title]" => ["[BUG] Error 500 :",
136
- controller_and_method,
137
- "(#{@exception.class})",
138
- @exception.message].compact.join(" ")
139
- }.to_query
140
-
141
- text << "[Create an issue](#{link}/?#{params})"
142
-
143
- text
144
- end
145
-
146
- def controller_and_method
147
- if @controller
148
- "#{@controller.controller_name}##{@controller.action_name}"
149
- else
150
- ""
151
- end
152
- end
153
-
154
- def hash_presentation(hash)
155
- text = []
156
-
157
- hash.each do |key, value|
158
- text << "* #{key} : #{value}"
159
- end
57
+ text
58
+ end
160
59
 
161
- text.join("\n")
162
- end
60
+ def message_issue_link
61
+ link = [@gitlab_url, formatter.app_name, 'issues', 'new'].join('/')
62
+ params = {
63
+ 'issue[title]' => ['[BUG] Error 500 :',
64
+ formatter.controller_and_action || '',
65
+ "(#{@exception.class})",
66
+ @exception.message].compact.join(' ')
67
+ }.to_query
163
68
 
69
+ "[Create an issue](#{link}/?#{params})"
70
+ end
164
71
  end
165
72
  end