sidekiq-failures-discourse 0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c480f406d6925142f99a976501f2388b6d1e1e00
4
+ data.tar.gz: c82a6b0f9d58f2d02edd54f5ea329d2ed72ff58a
5
+ SHA512:
6
+ metadata.gz: 065f2dca2eaaacf33997b7365b2a3a429b69108b68b2c1a88eeb717d78fb06ac4729d34a74b240a72b312668d17d5c00ed8627c45f5e2ac6053c7b6cfea5a0a2
7
+ data.tar.gz: 22efa3a06a64125f18678fb456b40c1b99653554a7238fec7463c512d2783007d249a5e16b0d81644e296c17f71772c21c121471c9b50bd8200e59e9aca32f7f
@@ -0,0 +1,16 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ services:
3
+ - redis-server
4
+ rvm:
5
+ - 1.9.3
6
+ - jruby-19mode
7
+ - 2.0.0
@@ -0,0 +1,48 @@
1
+ ## Unreleased
2
+
3
+ ## 0.3.0
4
+ * Bump sidekiq dependency to sidekiq >= 2.14.0
5
+ * Remove slim templates and dependecy
6
+ * Escape exception info when outputing to html
7
+ * Add `Sidekiq::Failures.reset_failures` helper method
8
+ * Add `Sidekiq::Failures.count` helper method (@zanker)
9
+ * Adhere to sidekiq approach of showing UTC times
10
+ * Catch all exceptions, not just those that inherit from StandardError (@tylerkovacs)
11
+ * Fix private method call (@bwthomas)
12
+
13
+ ## 0.2.2
14
+ * Support ERB for sidekiq >= 2.14.0 (@tobiassvn)
15
+ * Bump sidekiq dep to >= 2.9.0
16
+ * Show newest failures first (@PlugIN73)
17
+ * Fix specs (@krasnoukhov)
18
+
19
+ ## 0.2.1
20
+ * Fix exhausted mode when retry is disabled (@wr0ngway)
21
+
22
+ ## 0.2.0
23
+ * Added processor identity to failure data (@krasnoukhov)
24
+ * Handle Sidekiq::Shutdown exceptions (@krasnoukhov)
25
+ * Add failures maximum count option (@mathieulaporte)
26
+ * User Expception#message instead of Exception#to_s (@supaspoida)
27
+ * Removed web depencies (@LongMan)
28
+ * Stop overloading find_template (@zquestz)
29
+
30
+ ## 0.1.0
31
+ * Allow per worker configuration of failure tracking mode. Thanks to
32
+ @kbaum for most of the work.
33
+ * Prevent sidekiq-failures from loading up sidekiq/processor (and thus
34
+ Celluloid actors) except for inside a Sidekiq server context (@cheald)
35
+ * Fix pagination bug
36
+ * Add failures default mode option (@kbaum)
37
+ * Add checkbox option to reset failed counter (@krasnoukhov)
38
+
39
+ ## 0.0.3
40
+
41
+ * Adequate layout to new sidekiq web ui design (@krasnoukhov)
42
+ * Improve backtrace view (@krasnoukhov)
43
+ * Remove unnecessary slash in redirect (@krasnoukhov)
44
+ * Invert order of failed jobs (@krasnoukhov)
45
+
46
+ ## 0.0.2
47
+
48
+ * Show backtrace similar to resque (Kunal Modi)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sidekiq-failures.gemspec
4
+ gemspec
@@ -0,0 +1,51 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sidekiq-failures-discourse (0.3.0)
5
+ sidekiq (>= 2.14.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ celluloid (0.15.2)
11
+ timers (~> 1.1.0)
12
+ connection_pool (2.0.0)
13
+ hike (1.2.1)
14
+ json (1.8.1)
15
+ multi_json (1.7.3)
16
+ rack (1.4.1)
17
+ rack-protection (1.2.0)
18
+ rack
19
+ rack-test (0.6.2)
20
+ rack (>= 1.0)
21
+ rake (0.9.2.2)
22
+ redis (3.0.7)
23
+ redis-namespace (1.4.1)
24
+ redis (~> 3.0.4)
25
+ sidekiq (3.0.0)
26
+ celluloid (>= 0.15.2)
27
+ connection_pool (>= 2.0.0)
28
+ json
29
+ redis (>= 3.0.6)
30
+ redis-namespace (>= 1.3.1)
31
+ sinatra (1.3.3)
32
+ rack (~> 1.3, >= 1.3.6)
33
+ rack-protection (~> 1.2)
34
+ tilt (~> 1.3, >= 1.3.3)
35
+ sprockets (2.8.1)
36
+ hike (~> 1.2)
37
+ multi_json (~> 1.0)
38
+ rack (~> 1.0)
39
+ tilt (~> 1.1, != 1.3.0)
40
+ tilt (1.3.3)
41
+ timers (1.1.0)
42
+
43
+ PLATFORMS
44
+ ruby
45
+
46
+ DEPENDENCIES
47
+ rack-test
48
+ rake
49
+ sidekiq-failures-discourse!
50
+ sinatra
51
+ sprockets
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Marcelo Silveira
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,153 @@
1
+ # Sidekiq::Failures [![Build Status](https://secure.travis-ci.org/mhfs/sidekiq-failures.png)](http://travis-ci.org/mhfs/sidekiq-failures)
2
+
3
+ Keeps track of Sidekiq failed jobs and adds a tab to the Web UI to let you browse
4
+ them. Makes use of Sidekiq's custom tabs and middleware chain.
5
+
6
+ It mimics the way Resque keeps track of failures.
7
+
8
+ WARNING: by default sidekiq-failures will keep up to 1000 failures. See [Maximum Tracked Failures](https://github.com/mhfs/sidekiq-failures#maximum-tracked-failures) below.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'sidekiq-failures'
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ Simply having the gem in your Gemfile is enough to get you started. Your failed
21
+ jobs will be visible via a Failures tab in the Web UI.
22
+
23
+ ## Configuring
24
+
25
+ ### Maximum Tracked Failures
26
+
27
+ Since each failed job/retry creates a new failure entry that will only be removed
28
+ by you manually, your failures list might consume more resources than you have
29
+ available.
30
+
31
+ To avoid this sidekiq-failures adopts a default of 1000 maximum tracked failures.
32
+
33
+ To change the maximum amount:
34
+
35
+ ```ruby
36
+ Sidekiq.configure_server do |config|
37
+ config.failures_max_count = 5000
38
+ end
39
+ ```
40
+
41
+ To disable the limit entirely:
42
+
43
+ ```ruby
44
+ Sidekiq.configure_server do |config|
45
+ config.failures_max_count = false
46
+ end
47
+ ```
48
+
49
+ ### Failures Tracking Mode
50
+
51
+ Sidekiq-failures offers three failures tracking options (per worker):
52
+
53
+
54
+ #### :all (default)
55
+
56
+ Tracks failures every time a background job fails. This mean a job with 25 retries
57
+ enabled might generate up to 25 failure entries. If the worker has retry disabled
58
+ only one failure will be tracked.
59
+
60
+ This is the default behavior but can be made explicit with:
61
+
62
+ ```ruby
63
+ class MyWorker
64
+ include Sidekiq::Worker
65
+
66
+ sidekiq_options :failures => true # or :all
67
+
68
+ def perform; end
69
+ end
70
+ ```
71
+
72
+ #### :exhausted
73
+
74
+ Only track failures if the job exhausts all its retries (or doesn't have retries
75
+ enabled).
76
+
77
+ You can set this mode as follows:
78
+
79
+ ```ruby
80
+ class MyWorker
81
+ include Sidekiq::Worker
82
+
83
+ sidekiq_options :failures => :exhausted
84
+
85
+ def perform; end
86
+ end
87
+ ```
88
+
89
+ #### :off
90
+
91
+ You can also completely turn off failures tracking for a given worker as follows:
92
+
93
+ ```ruby
94
+ class MyWorker
95
+ include Sidekiq::Worker
96
+
97
+ sidekiq_options :failures => false # or :off
98
+
99
+ def perform; end
100
+ end
101
+ ```
102
+
103
+ #### Change the default mode
104
+
105
+ You can also change the default of all your workers at once by setting the following
106
+ server config:
107
+
108
+ ```ruby
109
+ Sidekiq.configure_server do |config|
110
+ config.failures_default_mode = :off
111
+ end
112
+ ```
113
+
114
+ The valid modes are `:all`, `:exhausted` or `:off`.
115
+
116
+ ## Helper Methods
117
+
118
+ ### Failures Count
119
+
120
+ Gives back the number of failed jobs currently stored in Sidekiq Failures. Notice that it's
121
+ different from `Sidekiq` built in failed stat. Also, notice that this might be
122
+ influenced by `failures_max_count`.
123
+
124
+ ```ruby
125
+ Sidekiq::Failures.count
126
+ ```
127
+
128
+ ### Reset Failures
129
+
130
+ Gives a convenient way of reseting Sidekiq Failure stored failed jobs programmatically.
131
+ Takes an options hash and if the `counter` key is present also resets Sidekiq own failed stats.
132
+
133
+ ```ruby
134
+ Sidekiq::Failures.reset_failures
135
+ ```
136
+
137
+ ## Dependencies
138
+
139
+ Depends on Sidekiq >= 2.14.0
140
+
141
+ ## Contributing
142
+
143
+ 1. Fork it
144
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
145
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
146
+ 4. Push to the branch (`git push origin my-new-feature`)
147
+ 5. Create new Pull Request
148
+
149
+ ## License
150
+
151
+ Released under the MIT License. See the [LICENSE][license] file for further details.
152
+
153
+ [license]: https://github.com/mhfs/sidekiq-failures/blob/master/LICENSE
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ task :default => :test
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.libs << "lib"
9
+ t.libs << "test"
10
+ t.test_files = FileList["test/**/*_test.rb"]
11
+ t.verbose = true
12
+ end
@@ -0,0 +1 @@
1
+ require "sidekiq/failures"
@@ -0,0 +1,79 @@
1
+ begin
2
+ require "sidekiq/web"
3
+ rescue LoadError
4
+ # client-only usage
5
+ end
6
+
7
+ require "sidekiq/api"
8
+ require "sidekiq/failures/version"
9
+ require "sidekiq/failures/sorted_entry"
10
+ require "sidekiq/failures/failure_set"
11
+ require "sidekiq/failures/middleware"
12
+ require "sidekiq/failures/web_extension"
13
+
14
+ module Sidekiq
15
+
16
+ SIDEKIQ_FAILURES_MODES = [:all, :exhausted, :off].freeze
17
+
18
+ # Sets the default failure tracking mode.
19
+ #
20
+ # The value provided here will be the default behavior but can be overwritten
21
+ # per worker by using `sidekiq_options :failures => :mode`
22
+ #
23
+ # Defaults to :all
24
+ def self.failures_default_mode=(mode)
25
+ unless SIDEKIQ_FAILURES_MODES.include?(mode.to_sym)
26
+ raise ArgumentError, "Sidekiq#failures_default_mode valid options: #{SIDEKIQ_FAILURES_MODES}"
27
+ end
28
+
29
+ @failures_default_mode = mode.to_sym
30
+ end
31
+
32
+ # Fetches the default failure tracking mode.
33
+ def self.failures_default_mode
34
+ @failures_default_mode || :all
35
+ end
36
+
37
+ # Sets the maximum number of failures to track
38
+ #
39
+ # If the number of failures exceeds this number the list will be trimmed (oldest
40
+ # failures will be purged).
41
+ #
42
+ # Defaults to 1000
43
+ # Set to false to disable rotation
44
+ def self.failures_max_count=(value)
45
+ @failures_max_count = value
46
+ end
47
+
48
+ # Fetches the failures max count value
49
+ def self.failures_max_count
50
+ return 1000 if @failures_max_count.nil?
51
+
52
+ @failures_max_count
53
+ end
54
+
55
+ module Failures
56
+ LIST_KEY = :failed
57
+
58
+ def self.reset_failures
59
+ Sidekiq.redis { |c| c.set("stat:failed", 0) }
60
+ end
61
+
62
+ def self.count
63
+ Sidekiq.redis {|r| r.zcard(LIST_KEY) }
64
+ end
65
+ end
66
+ end
67
+
68
+ Sidekiq.configure_server do |config|
69
+ config.server_middleware do |chain|
70
+ chain.insert_before Sidekiq::Middleware::Server::RetryJobs,
71
+ Sidekiq::Failures::Middleware
72
+ end
73
+ end
74
+
75
+ if defined?(Sidekiq::Web)
76
+ Sidekiq::Web.register Sidekiq::Failures::WebExtension
77
+ Sidekiq::Web.tabs["Failures"] = "failures"
78
+ Sidekiq::Web.settings.locales << File.join(File.dirname(__FILE__), "failures/locales")
79
+ end
@@ -0,0 +1,22 @@
1
+ module Sidekiq
2
+ module Failures
3
+ Superclass =
4
+ if defined?(Sidekiq::JobSet)
5
+ Sidekiq::JobSet
6
+ else
7
+ Sidekiq::SortedSet
8
+ end
9
+
10
+ class FailureSet < Superclass
11
+ def initialize
12
+ super LIST_KEY
13
+ end
14
+
15
+ def retry_all_failures
16
+ while size > 0
17
+ each(&:retry_failure)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ en:
2
+ FailedJobs: Failed Jobs
3
+ FailedAt: Failed At
4
+ ResetCounter: Reset Counter
5
+ NoFailedJobsFound: No failed jobs found
@@ -0,0 +1,99 @@
1
+ module Sidekiq
2
+ module Failures
3
+
4
+ class Middleware
5
+ attr_accessor :msg
6
+
7
+ def call(worker, msg, queue)
8
+ self.msg = msg
9
+ yield
10
+ rescue Sidekiq::Shutdown
11
+ raise
12
+ rescue Exception => e
13
+ raise e if skip_failure?
14
+
15
+ msg['error_message'] = e.message
16
+ msg['error_class'] = e.class.name
17
+ msg['processor'] = identity
18
+ msg['failed_at'] = Time.now.utc.to_f
19
+
20
+ if msg['backtrace'] == true
21
+ msg['error_backtrace'] = e.backtrace
22
+ elsif msg['backtrace'] == false
23
+ # do nothing
24
+ elsif msg['backtrace'].to_i != 0
25
+ msg['error_backtrace'] = e.backtrace[0..msg['backtrace'].to_i]
26
+ end
27
+
28
+ payload = Sidekiq.dump_json(msg)
29
+ Sidekiq.redis do |conn|
30
+ conn.zadd(LIST_KEY, Time.now.utc.to_f, payload)
31
+ unless Sidekiq.failures_max_count == false
32
+ conn.zremrangebyrank(LIST_KEY, 0, -(Sidekiq.failures_max_count + 1))
33
+ end
34
+ end
35
+
36
+ raise e
37
+ end
38
+
39
+ private
40
+
41
+ def failure_mode_off?
42
+ failure_mode == :off
43
+ end
44
+
45
+ def failure_mode_exhausted?
46
+ failure_mode == :exhausted
47
+ end
48
+
49
+ def skip_failure?
50
+ failure_mode_off? || failure_mode_exhausted? && !exhausted?
51
+ end
52
+
53
+ def failure_mode
54
+ case msg['failures'].to_s
55
+ when 'true', 'all'
56
+ :all
57
+ when 'false', 'off'
58
+ :off
59
+ when 'exhausted'
60
+ :exhausted
61
+ else
62
+ Sidekiq.failures_default_mode
63
+ end
64
+ end
65
+
66
+ def exhausted?
67
+ !retriable? || retry_count >= max_retries
68
+ end
69
+
70
+ def retriable?
71
+ msg['retry']
72
+ end
73
+
74
+ def retry_count
75
+ msg['retry_count'] || 0
76
+ end
77
+
78
+ def max_retries
79
+ retry_middleware.send(:retry_attempts_from, msg['retry'], default_max_retries)
80
+ end
81
+
82
+ def retry_middleware
83
+ @retry_middleware ||= Sidekiq::Middleware::Server::RetryJobs.new
84
+ end
85
+
86
+ def default_max_retries
87
+ Sidekiq::Middleware::Server::RetryJobs::DEFAULT_MAX_RETRY_ATTEMPTS
88
+ end
89
+
90
+ def hostname
91
+ Socket.gethostname
92
+ end
93
+
94
+ def identity
95
+ @@identity ||= "#{hostname}:#{$$}"
96
+ end
97
+ end
98
+ end
99
+ end