exception-track 0.6.2 → 1.3.0
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.
- checksums.yaml +4 -4
- data/README.md +8 -3
- data/app/assets/config/exception_track_manifest.js +0 -0
- data/app/assets/stylesheets/exception-track/application.css +126 -44
- data/app/controllers/exception_track/logs_controller.rb +2 -3
- data/app/views/exception_track/logs/index.html.erb +2 -1
- data/config/initializers/exception-track.rb +11 -6
- data/db/migrate/20170217023900_create_exception_track_logs.rb +2 -2
- data/lib/exception-track/configuration.rb +1 -0
- data/lib/exception-track/engine.rb +3 -1
- data/lib/exception-track/log_subscriber.rb +12 -0
- data/lib/exception-track/version.rb +1 -1
- data/lib/exception-track.rb +4 -3
- data/lib/exception_notification/rack.rb +66 -0
- data/lib/exception_notification/rails.rb +11 -0
- data/lib/exception_notification/resque.rb +24 -0
- data/lib/exception_notification/sidekiq.rb +29 -0
- data/lib/exception_notification/version.rb +5 -0
- data/lib/exception_notification.rb +14 -0
- data/lib/exception_notifier/base_notifier.rb +30 -0
- data/lib/exception_notifier/{exception_track_notifier.rb → db_notifier.rb} +30 -26
- data/lib/exception_notifier/modules/backtrace_cleaner.rb +13 -0
- data/lib/exception_notifier/modules/error_grouping.rb +90 -0
- data/lib/exception_notifier/modules/formatter.rb +125 -0
- data/lib/exception_notifier/notifier.rb +191 -0
- metadata +91 -22
@@ -1,27 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ExceptionNotifier
|
4
|
-
class
|
5
|
-
def initialize(
|
4
|
+
class DbNotifier < ExceptionNotifier::BaseNotifier
|
5
|
+
def initialize(opts = {})
|
6
|
+
super(opts)
|
7
|
+
end
|
6
8
|
|
7
|
-
def call(exception,
|
9
|
+
def call(exception, opts = {})
|
8
10
|
return unless ExceptionTrack.config.enabled_env?(Rails.env)
|
9
11
|
|
10
12
|
# send the notification
|
11
13
|
title = exception.message || "None"
|
12
|
-
|
13
14
|
messages = []
|
14
|
-
messages << headers_for_env(_options[:env])
|
15
|
-
messages << ""
|
16
|
-
messages << "--------------------------------------------------"
|
17
|
-
messages << ""
|
18
|
-
messages << exception.inspect
|
19
|
-
unless exception.backtrace.blank?
|
20
|
-
messages << "\n"
|
21
|
-
messages << exception.backtrace
|
22
|
-
end
|
23
15
|
|
24
|
-
|
16
|
+
ActiveSupport::Notifications.instrument("track.exception_track", title: title) do
|
17
|
+
messages << headers_for_env(opts[:env])
|
18
|
+
messages << ""
|
19
|
+
messages << "--------------------------------------------------"
|
20
|
+
messages << ""
|
21
|
+
messages << exception.inspect
|
22
|
+
unless exception.backtrace.blank?
|
23
|
+
messages << "\n"
|
24
|
+
messages << exception.backtrace
|
25
|
+
end
|
26
|
+
|
27
|
+
Rails.logger.silence do
|
28
|
+
ExceptionTrack::Log.create(title: title[0, 200], body: messages.join("\n"))
|
29
|
+
end
|
30
|
+
end
|
25
31
|
rescue => e
|
26
32
|
errs = []
|
27
33
|
errs << "-- [ExceptionTrack] create error ---------------------------"
|
@@ -41,16 +47,14 @@ module ExceptionNotifier
|
|
41
47
|
parameters = filter_parameters(env)
|
42
48
|
|
43
49
|
headers = []
|
44
|
-
headers << "Method: #{env[
|
45
|
-
headers << "URL: #{env[
|
46
|
-
if env[
|
47
|
-
|
48
|
-
|
49
|
-
headers << "
|
50
|
-
headers << "
|
51
|
-
headers << "
|
52
|
-
headers << "Remote IP: #{env['REMOTE_ADDR']}"
|
53
|
-
headers << "Language: #{env['HTTP_ACCEPT_LANGUAGE']}"
|
50
|
+
headers << "Method: #{env["REQUEST_METHOD"]}"
|
51
|
+
headers << "URL: #{env["REQUEST_URI"]}"
|
52
|
+
headers << "Parameters:\n#{pretty_hash(parameters.except(:controller, :action), 13)}" if env["REQUEST_METHOD"].downcase != "get"
|
53
|
+
headers << "Controller: #{parameters["controller"]}##{parameters["action"]}"
|
54
|
+
headers << "RequestId: #{env["action_dispatch.request_id"]}"
|
55
|
+
headers << "User-Agent: #{env["HTTP_USER_AGENT"]}"
|
56
|
+
headers << "Remote IP: #{env["REMOTE_ADDR"]}"
|
57
|
+
headers << "Language: #{env["HTTP_ACCEPT_LANGUAGE"]}"
|
54
58
|
headers << "Server: #{Socket.gethostname}"
|
55
59
|
headers << "Process: #{$PROCESS_ID}"
|
56
60
|
|
@@ -60,10 +64,10 @@ module ExceptionNotifier
|
|
60
64
|
def filter_parameters(env)
|
61
65
|
parameters = env["action_dispatch.request.parameters"] || {}
|
62
66
|
parameter_filter = ActiveSupport::ParameterFilter.new(env["action_dispatch.parameter_filter"] || [])
|
63
|
-
|
67
|
+
parameter_filter.filter(parameters)
|
64
68
|
rescue => e
|
65
69
|
Rails.logger.error "filter_parameters error: #{e.inspect}"
|
66
|
-
|
70
|
+
parameters
|
67
71
|
end
|
68
72
|
|
69
73
|
def pretty_hash(params, indent = 0)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ExceptionNotifier
|
4
|
+
module BacktraceCleaner
|
5
|
+
def clean_backtrace(exception)
|
6
|
+
if defined?(Rails) && Rails.respond_to?(:backtrace_cleaner)
|
7
|
+
Rails.backtrace_cleaner.send(:filter, exception.backtrace)
|
8
|
+
else
|
9
|
+
exception.backtrace
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
if Rails.version > "7.0"
|
4
|
+
require "active_support/isolated_execution_state"
|
5
|
+
end
|
6
|
+
require "active_support/core_ext/numeric/time"
|
7
|
+
require "active_support/concern"
|
8
|
+
|
9
|
+
module ExceptionNotifier
|
10
|
+
module ErrorGrouping
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
mattr_accessor :error_grouping
|
15
|
+
self.error_grouping = false
|
16
|
+
|
17
|
+
mattr_accessor :error_grouping_period
|
18
|
+
self.error_grouping_period = 5.minutes
|
19
|
+
|
20
|
+
mattr_accessor :notification_trigger
|
21
|
+
|
22
|
+
mattr_accessor :error_grouping_cache
|
23
|
+
end
|
24
|
+
|
25
|
+
module ClassMethods
|
26
|
+
# Fallback to the memory store while the specified cache store doesn't work
|
27
|
+
#
|
28
|
+
def fallback_cache_store
|
29
|
+
@fallback_cache_store ||= ActiveSupport::Cache::MemoryStore.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def error_count(error_key)
|
33
|
+
count =
|
34
|
+
begin
|
35
|
+
error_grouping_cache.read(error_key)
|
36
|
+
rescue => e
|
37
|
+
log_cache_error(error_grouping_cache, e, :read)
|
38
|
+
fallback_cache_store.read(error_key)
|
39
|
+
end
|
40
|
+
|
41
|
+
count&.to_i
|
42
|
+
end
|
43
|
+
|
44
|
+
def save_error_count(error_key, count)
|
45
|
+
error_grouping_cache.write(error_key, count, expires_in: error_grouping_period)
|
46
|
+
rescue => e
|
47
|
+
log_cache_error(error_grouping_cache, e, :write)
|
48
|
+
fallback_cache_store.write(error_key, count, expires_in: error_grouping_period)
|
49
|
+
end
|
50
|
+
|
51
|
+
def group_error!(exception, options)
|
52
|
+
message_based_key = "exception:#{Zlib.crc32("#{exception.class.name}\nmessage:#{exception.message}")}"
|
53
|
+
accumulated_errors_count = 1
|
54
|
+
|
55
|
+
if (count = error_count(message_based_key))
|
56
|
+
accumulated_errors_count = count + 1
|
57
|
+
save_error_count(message_based_key, accumulated_errors_count)
|
58
|
+
else
|
59
|
+
backtrace_based_key =
|
60
|
+
"exception:#{Zlib.crc32("#{exception.class.name}\npath:#{exception.backtrace.try(:first)}")}"
|
61
|
+
|
62
|
+
if (count = error_grouping_cache.read(backtrace_based_key))
|
63
|
+
accumulated_errors_count = count + 1
|
64
|
+
save_error_count(backtrace_based_key, accumulated_errors_count)
|
65
|
+
else
|
66
|
+
save_error_count(backtrace_based_key, accumulated_errors_count)
|
67
|
+
save_error_count(message_based_key, accumulated_errors_count)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
options[:accumulated_errors_count] = accumulated_errors_count
|
72
|
+
end
|
73
|
+
|
74
|
+
def send_notification?(exception, count)
|
75
|
+
if notification_trigger.respond_to?(:call)
|
76
|
+
notification_trigger.call(exception, count)
|
77
|
+
else
|
78
|
+
factor = Math.log2(count)
|
79
|
+
factor.to_i == factor
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def log_cache_error(cache, exception, action)
|
86
|
+
"#{cache.inspect} failed to #{action}, reason: #{exception.message}. Falling back to memory cache store."
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/time"
|
4
|
+
require "action_dispatch"
|
5
|
+
|
6
|
+
module ExceptionNotifier
|
7
|
+
class Formatter
|
8
|
+
include ExceptionNotifier::BacktraceCleaner
|
9
|
+
|
10
|
+
attr_reader :app_name
|
11
|
+
|
12
|
+
def initialize(exception, opts = {})
|
13
|
+
@exception = exception
|
14
|
+
|
15
|
+
@env = opts[:env]
|
16
|
+
@errors_count = opts[:accumulated_errors_count].to_i
|
17
|
+
@app_name = opts[:app_name] || rails_app_name
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# :warning: Error occurred in production :warning:
|
22
|
+
# :warning: Error occurred :warning:
|
23
|
+
#
|
24
|
+
def title
|
25
|
+
env = Rails.env if defined?(::Rails) && ::Rails.respond_to?(:env)
|
26
|
+
|
27
|
+
if env
|
28
|
+
"⚠️ Error occurred in #{env} ⚠️"
|
29
|
+
else
|
30
|
+
"⚠️ Error occurred ⚠️"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# A *NoMethodError* occurred.
|
36
|
+
# 3 *NoMethodError* occurred.
|
37
|
+
# A *NoMethodError* occurred in *home#index*.
|
38
|
+
#
|
39
|
+
def subtitle
|
40
|
+
errors_text = if errors_count > 1
|
41
|
+
errors_count
|
42
|
+
else
|
43
|
+
/^[aeiou]/i.match?(exception.class.to_s) ? "An" : "A"
|
44
|
+
end
|
45
|
+
|
46
|
+
in_action = " in *#{controller_and_action}*" if controller
|
47
|
+
|
48
|
+
"#{errors_text} *#{exception.class}* occurred#{in_action}."
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
#
|
53
|
+
# *Request:*
|
54
|
+
# ```
|
55
|
+
# * url : https://www.example.com/
|
56
|
+
# * http_method : GET
|
57
|
+
# * ip_address : 127.0.0.1
|
58
|
+
# * parameters : {"controller"=>"home", "action"=>"index"}
|
59
|
+
# * timestamp : 2019-01-01 00:00:00 UTC
|
60
|
+
# ```
|
61
|
+
#
|
62
|
+
def request_message
|
63
|
+
request = ActionDispatch::Request.new(env) if env
|
64
|
+
return unless request
|
65
|
+
|
66
|
+
[
|
67
|
+
"```",
|
68
|
+
"* url : #{request.original_url}",
|
69
|
+
"* http_method : #{request.method}",
|
70
|
+
"* ip_address : #{request.remote_ip}",
|
71
|
+
"* parameters : #{request.filtered_parameters}",
|
72
|
+
"* timestamp : #{Time.current}",
|
73
|
+
"```"
|
74
|
+
].join("\n")
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
#
|
79
|
+
# *Backtrace:*
|
80
|
+
# ```
|
81
|
+
# * app/controllers/my_controller.rb:99:in `specific_function'
|
82
|
+
# * app/controllers/my_controller.rb:70:in `specific_param'
|
83
|
+
# * app/controllers/my_controller.rb:53:in `my_controller_params'
|
84
|
+
# ```
|
85
|
+
#
|
86
|
+
def backtrace_message
|
87
|
+
backtrace = exception.backtrace ? clean_backtrace(exception) : nil
|
88
|
+
|
89
|
+
return unless backtrace
|
90
|
+
|
91
|
+
text = []
|
92
|
+
|
93
|
+
text << "```"
|
94
|
+
backtrace.first(3).each { |line| text << "* #{line}" }
|
95
|
+
text << "```"
|
96
|
+
|
97
|
+
text.join("\n")
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# home#index
|
102
|
+
#
|
103
|
+
def controller_and_action
|
104
|
+
"#{controller.controller_name}##{controller.action_name}" if controller
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
attr_reader :exception, :env, :errors_count
|
110
|
+
|
111
|
+
def rails_app_name
|
112
|
+
return unless defined?(::Rails) && ::Rails.respond_to?(:application)
|
113
|
+
|
114
|
+
if Rails::VERSION::MAJOR >= 6
|
115
|
+
Rails.application.class.module_parent_name.underscore
|
116
|
+
else
|
117
|
+
Rails.application.class.parent_name.underscore
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def controller
|
122
|
+
env["action_controller.instance"] if env
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
require "active_support/core_ext/string/inflections"
|
5
|
+
require "active_support/core_ext/module/attribute_accessors"
|
6
|
+
require "exception_notifier/base_notifier"
|
7
|
+
require "exception_notifier/modules/error_grouping"
|
8
|
+
|
9
|
+
module ExceptionNotifier
|
10
|
+
include ErrorGrouping
|
11
|
+
|
12
|
+
autoload :BacktraceCleaner, "exception_notifier/modules/backtrace_cleaner"
|
13
|
+
autoload :Formatter, "exception_notifier/modules/formatter"
|
14
|
+
|
15
|
+
autoload :Notifier, "exception_notifier/notifier"
|
16
|
+
autoload :DbNotifier, "exception_notifier/db_notifier"
|
17
|
+
|
18
|
+
class UndefinedNotifierError < StandardError; end
|
19
|
+
|
20
|
+
# Define logger
|
21
|
+
mattr_accessor :logger
|
22
|
+
@@logger = Logger.new($stdout)
|
23
|
+
|
24
|
+
# Define a set of exceptions to be ignored, ie, dont send notifications when any of them are raised.
|
25
|
+
mattr_accessor :ignored_exceptions
|
26
|
+
@@ignored_exceptions = %w[
|
27
|
+
AbstractController::ActionNotFound
|
28
|
+
ActionController::BadRequest
|
29
|
+
ActionController::InvalidAuthenticityToken
|
30
|
+
ActionController::InvalidCrossOriginRequest
|
31
|
+
ActionController::ParameterMissing
|
32
|
+
ActionController::RoutingError
|
33
|
+
ActionController::UnknownFormat
|
34
|
+
ActionController::UrlGenerationError
|
35
|
+
ActionView::MissingTemplate
|
36
|
+
ActionView::TemplateError
|
37
|
+
ActiveRecord::RecordNotFound
|
38
|
+
Mime::Type::InvalidMimeType
|
39
|
+
Mongoid::Errors::DocumentNotFound
|
40
|
+
]
|
41
|
+
|
42
|
+
mattr_accessor :testing_mode
|
43
|
+
@@testing_mode = false
|
44
|
+
|
45
|
+
class << self
|
46
|
+
# Store conditions that decide when exceptions must be ignored or not.
|
47
|
+
@@ignores = []
|
48
|
+
|
49
|
+
# Store by-notifier conditions that decide when exceptions must be ignored or not.
|
50
|
+
@@by_notifier_ignores = {}
|
51
|
+
|
52
|
+
# Store notifiers that send notifications when exceptions are raised.
|
53
|
+
@@notifiers = {}
|
54
|
+
|
55
|
+
def testing_mode!
|
56
|
+
self.testing_mode = true
|
57
|
+
end
|
58
|
+
|
59
|
+
def notify_exception(exception, options = {}, &block)
|
60
|
+
return false if ignored_exception?(options[:ignore_exceptions], exception)
|
61
|
+
return false if ignored?(exception, options)
|
62
|
+
|
63
|
+
if error_grouping
|
64
|
+
errors_count = group_error!(exception, options)
|
65
|
+
return false unless send_notification?(exception, errors_count)
|
66
|
+
end
|
67
|
+
|
68
|
+
notification_fired = false
|
69
|
+
selected_notifiers = options.delete(:notifiers) || notifiers
|
70
|
+
[*selected_notifiers].each do |notifier|
|
71
|
+
unless notifier_ignored?(exception, options, notifier: notifier)
|
72
|
+
fire_notification(notifier, exception, options.dup, &block)
|
73
|
+
notification_fired = true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
notification_fired
|
78
|
+
end
|
79
|
+
|
80
|
+
def register_exception_notifier(name, notifier_or_options)
|
81
|
+
if notifier_or_options.respond_to?(:call)
|
82
|
+
@@notifiers[name] = notifier_or_options
|
83
|
+
elsif notifier_or_options.is_a?(Hash)
|
84
|
+
create_and_register_notifier(name, notifier_or_options)
|
85
|
+
else
|
86
|
+
raise ArgumentError, "Invalid notifier '#{name}' defined as #{notifier_or_options.inspect}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
alias_method :add_notifier, :register_exception_notifier
|
90
|
+
|
91
|
+
def unregister_exception_notifier(name)
|
92
|
+
@@notifiers.delete(name)
|
93
|
+
end
|
94
|
+
|
95
|
+
def registered_exception_notifier(name)
|
96
|
+
@@notifiers[name]
|
97
|
+
end
|
98
|
+
|
99
|
+
def notifiers
|
100
|
+
@@notifiers.keys
|
101
|
+
end
|
102
|
+
|
103
|
+
# Adds a condition to decide when an exception must be ignored or not.
|
104
|
+
#
|
105
|
+
# ExceptionNotifier.ignore_if do |exception, options|
|
106
|
+
# not Rails.env.production?
|
107
|
+
# end
|
108
|
+
def ignore_if(&block)
|
109
|
+
@@ignores << block
|
110
|
+
end
|
111
|
+
|
112
|
+
def ignore_notifier_if(notifier, &block)
|
113
|
+
@@by_notifier_ignores[notifier] = block
|
114
|
+
end
|
115
|
+
|
116
|
+
def ignore_crawlers(crawlers)
|
117
|
+
ignore_if do |_exception, opts|
|
118
|
+
opts.key?(:env) && from_crawler(opts[:env], crawlers)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def clear_ignore_conditions!
|
123
|
+
@@ignores.clear
|
124
|
+
@@by_notifier_ignores.clear
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def ignored?(exception, options)
|
130
|
+
@@ignores.any? { |condition| condition.call(exception, options) }
|
131
|
+
rescue Exception => e
|
132
|
+
raise e if @@testing_mode
|
133
|
+
|
134
|
+
logger.warn(
|
135
|
+
"An error occurred when evaluating an ignore condition. #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
|
136
|
+
)
|
137
|
+
false
|
138
|
+
end
|
139
|
+
|
140
|
+
def notifier_ignored?(exception, options, notifier:)
|
141
|
+
return false unless @@by_notifier_ignores.key?(notifier)
|
142
|
+
|
143
|
+
condition = @@by_notifier_ignores[notifier]
|
144
|
+
condition.call(exception, options)
|
145
|
+
rescue Exception => e
|
146
|
+
raise e if @@testing_mode
|
147
|
+
|
148
|
+
logger.warn(<<~"MESSAGE")
|
149
|
+
An error occurred when evaluating a by-notifier ignore condition. #{e.class}: #{e.message}
|
150
|
+
#{e.backtrace.join("\n")}
|
151
|
+
MESSAGE
|
152
|
+
false
|
153
|
+
end
|
154
|
+
|
155
|
+
def ignored_exception?(ignore_array, exception)
|
156
|
+
all_ignored_exceptions = (Array(ignored_exceptions) + Array(ignore_array)).map(&:to_s)
|
157
|
+
exception_ancestors = exception.singleton_class.ancestors.map(&:to_s)
|
158
|
+
!(all_ignored_exceptions & exception_ancestors).empty?
|
159
|
+
end
|
160
|
+
|
161
|
+
def fire_notification(notifier_name, exception, options, &block)
|
162
|
+
notifier = registered_exception_notifier(notifier_name)
|
163
|
+
notifier.call(exception, options, &block)
|
164
|
+
rescue Exception => e
|
165
|
+
raise e if @@testing_mode
|
166
|
+
|
167
|
+
logger.warn(
|
168
|
+
"An error occurred when sending a notification using '#{notifier_name}' notifier." \
|
169
|
+
"#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
|
170
|
+
)
|
171
|
+
false
|
172
|
+
end
|
173
|
+
|
174
|
+
def create_and_register_notifier(name, options)
|
175
|
+
notifier_classname = "#{name}_notifier".camelize
|
176
|
+
notifier_class = ExceptionNotifier.const_get(notifier_classname)
|
177
|
+
notifier = notifier_class.new(options)
|
178
|
+
register_exception_notifier(name, notifier)
|
179
|
+
rescue NameError => e
|
180
|
+
raise UndefinedNotifierError,
|
181
|
+
"No notifier named '#{name}' was found. Please, revise your configuration options. Cause: #{e.message}"
|
182
|
+
end
|
183
|
+
|
184
|
+
def from_crawler(env, ignored_crawlers)
|
185
|
+
agent = env["HTTP_USER_AGENT"]
|
186
|
+
Array(ignored_crawlers).any? do |crawler|
|
187
|
+
agent =~ Regexp.new(crawler)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
metadata
CHANGED
@@ -1,71 +1,127 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exception-track
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Lee
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: kaminari
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0.15'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0.15'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: rails
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '5.2'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '5.2'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: pg
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
48
|
-
type: :
|
47
|
+
version: '1'
|
48
|
+
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mocha
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.13.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.13.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mock_redis
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.19.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.19.0
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
84
|
+
name: resque
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.8.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.8.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: sidekiq
|
57
99
|
requirement: !ruby/object:Gem::Requirement
|
58
100
|
requirements:
|
59
101
|
- - ">="
|
60
102
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
103
|
+
version: 5.0.4
|
62
104
|
type: :development
|
63
105
|
prerelease: false
|
64
106
|
version_requirements: !ruby/object:Gem::Requirement
|
65
107
|
requirements:
|
66
108
|
- - ">="
|
67
109
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
110
|
+
version: 5.0.4
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: timecop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.9.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.9.0
|
69
125
|
description: Tracking exceptions for Rails application store them in database by exception_notification
|
70
126
|
gem.
|
71
127
|
email:
|
@@ -76,6 +132,7 @@ extra_rdoc_files: []
|
|
76
132
|
files:
|
77
133
|
- MIT-LICENSE
|
78
134
|
- README.md
|
135
|
+
- app/assets/config/exception_track_manifest.js
|
79
136
|
- app/assets/stylesheets/exception-track/application.css
|
80
137
|
- app/controllers/exception_track/logs_controller.rb
|
81
138
|
- app/models/exception_track/log.rb
|
@@ -88,14 +145,26 @@ files:
|
|
88
145
|
- lib/exception-track.rb
|
89
146
|
- lib/exception-track/configuration.rb
|
90
147
|
- lib/exception-track/engine.rb
|
148
|
+
- lib/exception-track/log_subscriber.rb
|
91
149
|
- lib/exception-track/version.rb
|
92
|
-
- lib/
|
150
|
+
- lib/exception_notification.rb
|
151
|
+
- lib/exception_notification/rack.rb
|
152
|
+
- lib/exception_notification/rails.rb
|
153
|
+
- lib/exception_notification/resque.rb
|
154
|
+
- lib/exception_notification/sidekiq.rb
|
155
|
+
- lib/exception_notification/version.rb
|
156
|
+
- lib/exception_notifier/base_notifier.rb
|
157
|
+
- lib/exception_notifier/db_notifier.rb
|
158
|
+
- lib/exception_notifier/modules/backtrace_cleaner.rb
|
159
|
+
- lib/exception_notifier/modules/error_grouping.rb
|
160
|
+
- lib/exception_notifier/modules/formatter.rb
|
161
|
+
- lib/exception_notifier/notifier.rb
|
93
162
|
- lib/generators/exception_track/install_generator.rb
|
94
163
|
homepage: https://github.com/rails-engine/exception-track
|
95
164
|
licenses:
|
96
165
|
- MIT
|
97
166
|
metadata: {}
|
98
|
-
post_install_message:
|
167
|
+
post_install_message:
|
99
168
|
rdoc_options: []
|
100
169
|
require_paths:
|
101
170
|
- lib
|
@@ -110,8 +179,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
179
|
- !ruby/object:Gem::Version
|
111
180
|
version: '0'
|
112
181
|
requirements: []
|
113
|
-
rubygems_version: 3.
|
114
|
-
signing_key:
|
182
|
+
rubygems_version: 3.2.3
|
183
|
+
signing_key:
|
115
184
|
specification_version: 4
|
116
185
|
summary: Tracking exceptions for Rails application store them in database.
|
117
186
|
test_files: []
|