sidekiq-failures-discourse 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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