sidekiq 7.3.9 → 8.0.8

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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +116 -0
  3. data/README.md +16 -13
  4. data/bin/sidekiqload +10 -10
  5. data/bin/webload +69 -0
  6. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +104 -58
  7. data/lib/sidekiq/api.rb +124 -39
  8. data/lib/sidekiq/capsule.rb +6 -6
  9. data/lib/sidekiq/cli.rb +15 -19
  10. data/lib/sidekiq/client.rb +28 -17
  11. data/lib/sidekiq/component.rb +42 -3
  12. data/lib/sidekiq/config.rb +23 -20
  13. data/lib/sidekiq/embedded.rb +2 -1
  14. data/lib/sidekiq/iterable_job.rb +1 -0
  15. data/lib/sidekiq/job/iterable.rb +44 -16
  16. data/lib/sidekiq/job.rb +2 -2
  17. data/lib/sidekiq/job_logger.rb +4 -4
  18. data/lib/sidekiq/job_retry.rb +33 -10
  19. data/lib/sidekiq/job_util.rb +5 -1
  20. data/lib/sidekiq/launcher.rb +2 -1
  21. data/lib/sidekiq/loader.rb +57 -0
  22. data/lib/sidekiq/logger.rb +25 -69
  23. data/lib/sidekiq/manager.rb +0 -1
  24. data/lib/sidekiq/metrics/query.rb +71 -45
  25. data/lib/sidekiq/metrics/shared.rb +8 -5
  26. data/lib/sidekiq/metrics/tracking.rb +12 -7
  27. data/lib/sidekiq/middleware/current_attributes.rb +11 -19
  28. data/lib/sidekiq/paginator.rb +8 -1
  29. data/lib/sidekiq/processor.rb +21 -14
  30. data/lib/sidekiq/profiler.rb +72 -0
  31. data/lib/sidekiq/rails.rb +46 -67
  32. data/lib/sidekiq/redis_client_adapter.rb +0 -1
  33. data/lib/sidekiq/redis_connection.rb +14 -3
  34. data/lib/sidekiq/testing.rb +3 -3
  35. data/lib/sidekiq/transaction_aware_client.rb +13 -5
  36. data/lib/sidekiq/version.rb +2 -2
  37. data/lib/sidekiq/web/action.rb +146 -83
  38. data/lib/sidekiq/web/application.rb +353 -332
  39. data/lib/sidekiq/web/config.rb +120 -0
  40. data/lib/sidekiq/web/helpers.rb +57 -27
  41. data/lib/sidekiq/web/router.rb +60 -76
  42. data/lib/sidekiq/web.rb +51 -156
  43. data/lib/sidekiq.rb +6 -1
  44. data/sidekiq.gemspec +6 -6
  45. data/web/assets/images/logo.png +0 -0
  46. data/web/assets/images/status.png +0 -0
  47. data/web/assets/javascripts/application.js +26 -26
  48. data/web/assets/javascripts/base-charts.js +30 -16
  49. data/web/assets/javascripts/chartjs-adapter-date-fns.min.js +7 -0
  50. data/web/assets/javascripts/dashboard.js +1 -1
  51. data/web/assets/javascripts/metrics.js +16 -34
  52. data/web/assets/stylesheets/style.css +759 -0
  53. data/web/locales/ar.yml +1 -0
  54. data/web/locales/cs.yml +1 -0
  55. data/web/locales/da.yml +1 -0
  56. data/web/locales/de.yml +1 -0
  57. data/web/locales/el.yml +1 -0
  58. data/web/locales/en.yml +6 -0
  59. data/web/locales/es.yml +24 -2
  60. data/web/locales/fa.yml +1 -0
  61. data/web/locales/fr.yml +1 -0
  62. data/web/locales/gd.yml +1 -0
  63. data/web/locales/he.yml +1 -0
  64. data/web/locales/hi.yml +1 -0
  65. data/web/locales/it.yml +8 -0
  66. data/web/locales/ja.yml +1 -0
  67. data/web/locales/ko.yml +1 -0
  68. data/web/locales/lt.yml +1 -0
  69. data/web/locales/nb.yml +1 -0
  70. data/web/locales/nl.yml +1 -0
  71. data/web/locales/pl.yml +1 -0
  72. data/web/locales/{pt-br.yml → pt-BR.yml} +2 -1
  73. data/web/locales/pt.yml +1 -0
  74. data/web/locales/ru.yml +1 -0
  75. data/web/locales/sv.yml +1 -0
  76. data/web/locales/ta.yml +1 -0
  77. data/web/locales/tr.yml +1 -0
  78. data/web/locales/uk.yml +6 -5
  79. data/web/locales/ur.yml +1 -0
  80. data/web/locales/vi.yml +1 -0
  81. data/web/locales/{zh-cn.yml → zh-CN.yml} +85 -73
  82. data/web/locales/{zh-tw.yml → zh-TW.yml} +2 -1
  83. data/web/views/_footer.erb +31 -33
  84. data/web/views/_job_info.erb +91 -89
  85. data/web/views/_metrics_period_select.erb +13 -10
  86. data/web/views/_nav.erb +14 -21
  87. data/web/views/_paging.erb +23 -21
  88. data/web/views/_poll_link.erb +2 -2
  89. data/web/views/_summary.erb +16 -16
  90. data/web/views/busy.erb +124 -122
  91. data/web/views/dashboard.erb +62 -66
  92. data/web/views/dead.erb +31 -27
  93. data/web/views/filtering.erb +3 -3
  94. data/web/views/layout.erb +13 -29
  95. data/web/views/metrics.erb +75 -81
  96. data/web/views/metrics_for_job.erb +45 -46
  97. data/web/views/morgue.erb +61 -70
  98. data/web/views/profiles.erb +43 -0
  99. data/web/views/queue.erb +54 -52
  100. data/web/views/queues.erb +43 -41
  101. data/web/views/retries.erb +66 -75
  102. data/web/views/retry.erb +32 -27
  103. data/web/views/scheduled.erb +59 -55
  104. data/web/views/scheduled_job_info.erb +1 -1
  105. metadata +26 -25
  106. data/web/assets/stylesheets/application-dark.css +0 -147
  107. data/web/assets/stylesheets/application-rtl.css +0 -163
  108. data/web/assets/stylesheets/application.css +0 -759
  109. data/web/assets/stylesheets/bootstrap-rtl.min.css +0 -9
  110. data/web/assets/stylesheets/bootstrap.css +0 -5
  111. data/web/views/_status.erb +0 -4
@@ -32,8 +32,14 @@ module Sidekiq
32
32
  @_runtime = 0
33
33
  @_args = nil
34
34
  @_cancelled = nil
35
+ @current_object = nil
35
36
  end
36
37
 
38
+ # Access to the current object while iterating.
39
+ # This value is not reset so the latest element is
40
+ # explicitly available to cleanup/complete callbacks.
41
+ attr_reader :current_object
42
+
37
43
  def arguments
38
44
  @_args
39
45
  end
@@ -54,9 +60,7 @@ module Sidekiq
54
60
  c.pipelined do |p|
55
61
  p.hsetnx(key, "cancelled", Time.now.to_i)
56
62
  p.hget(key, "cancelled")
57
- # TODO When Redis 7.2 is required
58
- # p.expire(key, Sidekiq::Job::Iterable::STATE_TTL, "nx")
59
- p.expire(key, Sidekiq::Job::Iterable::STATE_TTL)
63
+ p.expire(key, Sidekiq::Job::Iterable::STATE_TTL, "nx")
60
64
  end
61
65
  end
62
66
  @_cancelled = result.to_i
@@ -66,6 +70,10 @@ module Sidekiq
66
70
  @_cancelled
67
71
  end
68
72
 
73
+ def cursor
74
+ @_cursor.freeze
75
+ end
76
+
69
77
  # A hook to override that will be called when the job starts iterating.
70
78
  #
71
79
  # It is called only once, for the first time.
@@ -93,6 +101,11 @@ module Sidekiq
93
101
  def on_stop
94
102
  end
95
103
 
104
+ # A hook to override that will be called when the job is cancelled.
105
+ #
106
+ def on_cancel
107
+ end
108
+
96
109
  # A hook to override that will be called when the job finished iterating.
97
110
  #
98
111
  def on_complete
@@ -130,7 +143,7 @@ module Sidekiq
130
143
  fetch_previous_iteration_state
131
144
 
132
145
  @_executions += 1
133
- @_start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
146
+ @_start_time = mono_now
134
147
 
135
148
  enumerator = build_enumerator(*args, cursor: @_cursor)
136
149
  unless enumerator
@@ -184,34 +197,40 @@ module Sidekiq
184
197
 
185
198
  def iterate_with_enumerator(enumerator, arguments)
186
199
  if is_cancelled?
200
+ on_cancel
187
201
  logger.info { "Job cancelled" }
188
202
  return true
189
203
  end
190
204
 
191
205
  time_limit = Sidekiq.default_configuration[:timeout]
192
206
  found_record = false
193
- state_flushed_at = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
207
+ state_flushed_at = mono_now
194
208
 
195
209
  enumerator.each do |object, cursor|
196
210
  found_record = true
197
211
  @_cursor = cursor
212
+ @current_object = object
198
213
 
199
- is_interrupted = interrupted?
200
- if ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - state_flushed_at >= STATE_FLUSH_INTERVAL || is_interrupted
214
+ interrupt_job = interrupted? || should_interrupt?
215
+ if mono_now - state_flushed_at >= STATE_FLUSH_INTERVAL || interrupt_job
201
216
  _, _, cancelled = flush_state
202
- state_flushed_at = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
217
+ state_flushed_at = mono_now
203
218
  if cancelled
204
219
  @_cancelled = true
220
+ on_cancel
205
221
  logger.info { "Job cancelled" }
206
222
  return true
207
223
  end
208
224
  end
209
225
 
210
- return false if is_interrupted
226
+ return false if interrupt_job
211
227
 
212
- verify_iteration_time(time_limit, object) do
228
+ verify_iteration_time(time_limit) do
213
229
  around_iteration do
214
230
  each_iteration(object, *arguments)
231
+ rescue Exception
232
+ flush_state
233
+ raise
215
234
  end
216
235
  end
217
236
  end
@@ -219,16 +238,16 @@ module Sidekiq
219
238
  logger.debug("Enumerator found nothing to iterate!") unless found_record
220
239
  true
221
240
  ensure
222
- @_runtime += (::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - @_start_time)
241
+ @_runtime += (mono_now - @_start_time)
223
242
  end
224
243
 
225
- def verify_iteration_time(time_limit, object)
226
- start = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
244
+ def verify_iteration_time(time_limit)
245
+ start = mono_now
227
246
  yield
228
- finish = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
247
+ finish = mono_now
229
248
  total = finish - start
230
249
  if total > time_limit
231
- logger.warn { "Iteration took longer (%.2f) than Sidekiq's shutdown timeout (%d) when processing `%s`. This can lead to job processing problems during deploys" % [total, time_limit, object] }
250
+ logger.warn { "Iteration took longer (%.2f) than Sidekiq's shutdown timeout (%d). This can lead to job processing problems during deploys" % [total, time_limit] }
232
251
  end
233
252
  end
234
253
 
@@ -254,6 +273,11 @@ module Sidekiq
254
273
  end
255
274
  end
256
275
 
276
+ def should_interrupt?
277
+ max_iteration_runtime = Sidekiq.default_configuration[:max_iteration_runtime]
278
+ max_iteration_runtime && (mono_now - @_start_time > max_iteration_runtime)
279
+ end
280
+
257
281
  def flush_state
258
282
  key = iteration_key
259
283
  state = {
@@ -265,7 +289,7 @@ module Sidekiq
265
289
  Sidekiq.redis do |conn|
266
290
  conn.multi do |pipe|
267
291
  pipe.hset(key, state)
268
- pipe.expire(key, STATE_TTL)
292
+ pipe.expire(key, STATE_TTL, "nx")
269
293
  pipe.hget(key, "cancelled")
270
294
  end
271
295
  end
@@ -289,6 +313,10 @@ module Sidekiq
289
313
  raise "Unexpected thrown value: #{completed.inspect}"
290
314
  end
291
315
  end
316
+
317
+ def mono_now
318
+ ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
319
+ end
292
320
  end
293
321
  end
294
322
  end
data/lib/sidekiq/job.rb CHANGED
@@ -248,9 +248,9 @@ module Sidekiq
248
248
  end
249
249
  alias_method :perform_sync, :perform_inline
250
250
 
251
- def perform_bulk(args, batch_size: 1_000)
251
+ def perform_bulk(args, **options)
252
252
  client = @klass.build_client
253
- client.push_bulk(@opts.merge("class" => @klass, "args" => args, :batch_size => batch_size))
253
+ client.push_bulk(@opts.merge({"class" => @klass, "args" => args}, options))
254
254
  end
255
255
 
256
256
  # +interval+ must be a timestamp, numeric or something that acts
@@ -26,16 +26,16 @@ module Sidekiq
26
26
  # If we're using a wrapper class, like ActiveJob, use the "wrapped"
27
27
  # attribute to expose the underlying thing.
28
28
  h = {
29
- class: job_hash["display_class"] || job_hash["wrapped"] || job_hash["class"],
30
- jid: job_hash["jid"]
29
+ jid: job_hash["jid"],
30
+ class: job_hash["wrapped"] || job_hash["class"]
31
31
  }
32
32
  h[:bid] = job_hash["bid"] if job_hash.has_key?("bid")
33
33
  h[:tags] = job_hash["tags"] if job_hash.has_key?("tags")
34
34
 
35
35
  Thread.current[:sidekiq_context] = h
36
36
  level = job_hash["log_level"]
37
- if level && @logger.respond_to?(:log_at)
38
- @logger.log_at(level, &block)
37
+ if level
38
+ @logger.with_level(level, &block)
39
39
  else
40
40
  yield
41
41
  end
@@ -139,6 +139,10 @@ module Sidekiq
139
139
 
140
140
  private
141
141
 
142
+ def now_ms
143
+ ::Process.clock_gettime(::Process::CLOCK_REALTIME, :millisecond)
144
+ end
145
+
142
146
  # Note that +jobinst+ can be nil here if an error is raised before we can
143
147
  # instantiate the job instance. All access must be guarded and
144
148
  # best effort.
@@ -149,17 +153,17 @@ module Sidekiq
149
153
 
150
154
  m = exception_message(exception)
151
155
  if m.respond_to?(:scrub!)
152
- m.force_encoding("utf-8")
156
+ m.force_encoding(Encoding::UTF_8)
153
157
  m.scrub!
154
158
  end
155
159
 
156
160
  msg["error_message"] = m
157
161
  msg["error_class"] = exception.class.name
158
162
  count = if msg["retry_count"]
159
- msg["retried_at"] = Time.now.to_f
163
+ msg["retried_at"] = now_ms
160
164
  msg["retry_count"] += 1
161
165
  else
162
- msg["failed_at"] = Time.now.to_f
166
+ msg["failed_at"] = now_ms
163
167
  msg["retry_count"] = 0
164
168
  end
165
169
 
@@ -177,19 +181,21 @@ module Sidekiq
177
181
  return retries_exhausted(jobinst, msg, exception) if count >= max_retry_attempts
178
182
 
179
183
  rf = msg["retry_for"]
180
- return retries_exhausted(jobinst, msg, exception) if rf && ((msg["failed_at"] + rf) < Time.now.to_f)
184
+ return retries_exhausted(jobinst, msg, exception) if rf && (time_for(msg["failed_at"]) + rf) < Time.now
181
185
 
182
186
  strategy, delay = delay_for(jobinst, count, exception, msg)
183
187
  case strategy
184
188
  when :discard
185
- return # poof!
189
+ msg["discarded_at"] = now_ms
190
+
191
+ return run_death_handlers(msg, exception)
186
192
  when :kill
187
193
  return retries_exhausted(jobinst, msg, exception)
188
194
  end
189
195
 
190
196
  # Logging here can break retries if the logging device raises ENOSPC #3979
191
197
  # logger.debug { "Failure! Retry #{count} in #{delay} seconds" }
192
- jitter = rand(10) * (count + 1)
198
+ jitter = rand(10 * (count + 1))
193
199
  retry_at = Time.now.to_f + delay + jitter
194
200
  payload = Sidekiq.dump_json(msg)
195
201
  redis do |conn|
@@ -197,6 +203,14 @@ module Sidekiq
197
203
  end
198
204
  end
199
205
 
206
+ def time_for(item)
207
+ if item.is_a?(Float)
208
+ Time.at(item)
209
+ else
210
+ Time.at(item / 1000, item % 1000)
211
+ end
212
+ end
213
+
200
214
  # returns (strategy, seconds)
201
215
  def delay_for(jobinst, count, exception, msg)
202
216
  rv = begin
@@ -243,13 +257,22 @@ module Sidekiq
243
257
  handle_exception(e, {context: "Error calling retries_exhausted", job: msg})
244
258
  end
245
259
 
246
- return if rv == :discard # poof!
247
- send_to_morgue(msg) unless msg["dead"] == false
260
+ discarded = msg["dead"] == false || rv == :discard
261
+
262
+ if discarded
263
+ msg["discarded_at"] = now_ms
264
+ else
265
+ send_to_morgue(msg)
266
+ end
267
+
268
+ run_death_handlers(msg, exception)
269
+ end
248
270
 
271
+ def run_death_handlers(job, exception)
249
272
  @capsule.config.death_handlers.each do |handler|
250
- handler.call(msg, exception)
273
+ handler.call(job, exception)
251
274
  rescue => e
252
- handle_exception(e, {context: "Error calling death handler", job: msg})
275
+ handle_exception(e, {context: "Error calling death handler", job: job})
253
276
  end
254
277
  end
255
278
 
@@ -58,10 +58,14 @@ module Sidekiq
58
58
  item["class"] = item["class"].to_s
59
59
  item["queue"] = item["queue"].to_s
60
60
  item["retry_for"] = item["retry_for"].to_i if item["retry_for"]
61
- item["created_at"] ||= Time.now.to_f
61
+ item["created_at"] ||= now_in_millis
62
62
  item
63
63
  end
64
64
 
65
+ def now_in_millis
66
+ ::Process.clock_gettime(::Process::CLOCK_REALTIME, :millisecond)
67
+ end
68
+
65
69
  def normalized_hash(item_class)
66
70
  if item_class.is_a?(Class)
67
71
  raise(ArgumentError, "Message must include a Sidekiq::Job class, not class name: #{item_class.ancestors.inspect}") unless item_class.respond_to?(:get_sidekiq_options)
@@ -68,6 +68,7 @@ module Sidekiq
68
68
  stoppers.each(&:join)
69
69
 
70
70
  clear_heartbeat
71
+ fire_event(:exit, reverse: true)
71
72
  end
72
73
 
73
74
  def stopping?
@@ -81,7 +82,7 @@ module Sidekiq
81
82
 
82
83
  end
83
84
 
84
- private unless $TESTING
85
+ private
85
86
 
86
87
  BEAT_PAUSE = 10
87
88
 
@@ -0,0 +1,57 @@
1
+ module Sidekiq
2
+ require "sidekiq/component"
3
+
4
+ class Loader
5
+ include Sidekiq::Component
6
+
7
+ def initialize(cfg = Sidekiq.default_configuration)
8
+ @config = cfg
9
+ @load_hooks = Hash.new { |h, k| h[k] = [] }
10
+ @loaded = Set.new
11
+ @lock = Mutex.new
12
+ end
13
+
14
+ # Declares a block that will be executed when a Sidekiq component is fully
15
+ # loaded. If the component has already loaded, the block is executed
16
+ # immediately.
17
+ #
18
+ # Sidekiq.loader.on_load(:api) do
19
+ # # extend the sidekiq API
20
+ # end
21
+ #
22
+ def on_load(name, &block)
23
+ # we don't want to hold the lock while calling the block
24
+ to_run = nil
25
+
26
+ @lock.synchronize do
27
+ if @loaded.include?(name)
28
+ to_run = block
29
+ else
30
+ @load_hooks[name] << block
31
+ end
32
+ end
33
+
34
+ to_run&.call
35
+ nil
36
+ end
37
+
38
+ # Executes all blocks registered to +name+ via on_load.
39
+ #
40
+ # Sidekiq.loader.run_load_hooks(:api)
41
+ #
42
+ # In the case of the above example, it will execute all hooks registered for +:api+.
43
+ #
44
+ def run_load_hooks(name)
45
+ hks = @lock.synchronize do
46
+ @loaded << name
47
+ @load_hooks.delete(name)
48
+ end
49
+
50
+ hks&.each do |blk|
51
+ blk.call
52
+ rescue => ex
53
+ handle_exception(ex, hook: name)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -22,92 +22,48 @@ module Sidekiq
22
22
  end
23
23
  end
24
24
 
25
- module LoggingUtils
26
- LEVELS = {
27
- "debug" => 0,
28
- "info" => 1,
29
- "warn" => 2,
30
- "error" => 3,
31
- "fatal" => 4
32
- }
33
- LEVELS.default_proc = proc do |_, level|
34
- puts("Invalid log level: #{level.inspect}")
35
- nil
36
- end
37
-
38
- LEVELS.each do |level, numeric_level|
39
- define_method(:"#{level}?") do
40
- local_level.nil? ? super() : local_level <= numeric_level
41
- end
42
- end
43
-
44
- def local_level
45
- Thread.current[:sidekiq_log_level]
46
- end
47
-
48
- def local_level=(level)
49
- case level
50
- when Integer
51
- Thread.current[:sidekiq_log_level] = level
52
- when Symbol, String
53
- Thread.current[:sidekiq_log_level] = LEVELS[level.to_s]
54
- when nil
55
- Thread.current[:sidekiq_log_level] = nil
56
- else
57
- raise ArgumentError, "Invalid log level: #{level.inspect}"
58
- end
59
- end
60
-
61
- def level
62
- local_level || super
63
- end
64
-
65
- # Change the thread-local level for the duration of the given block.
66
- def log_at(level)
67
- old_local_level = local_level
68
- self.local_level = level
69
- yield
70
- ensure
71
- self.local_level = old_local_level
72
- end
73
- end
74
-
75
25
  class Logger < ::Logger
76
- include LoggingUtils
77
-
78
26
  module Formatters
79
27
  class Base < ::Logger::Formatter
28
+ COLORS = {
29
+ "DEBUG" => "\e[1;32mDEBUG\e[0m", # green
30
+ "INFO" => "\e[1;34mINFO \e[0m", # blue
31
+ "WARN" => "\e[1;33mWARN \e[0m", # yellow
32
+ "ERROR" => "\e[1;31mERROR\e[0m", # red
33
+ "FATAL" => "\e[1;35mFATAL\e[0m" # pink
34
+ }
35
+
80
36
  def tid
81
37
  Thread.current["sidekiq_tid"] ||= (Thread.current.object_id ^ ::Process.pid).to_s(36)
82
38
  end
83
39
 
84
- def ctx
85
- Sidekiq::Context.current
40
+ def format_context(ctxt = Sidekiq::Context.current)
41
+ (ctxt.size == 0) ? "" : " #{ctxt.map { |k, v|
42
+ case v
43
+ when Array
44
+ "#{k}=#{v.join(",")}"
45
+ else
46
+ "#{k}=#{v}"
47
+ end
48
+ }.join(" ")}"
86
49
  end
50
+ end
87
51
 
88
- def format_context
89
- if ctx.any?
90
- " " + ctx.compact.map { |k, v|
91
- case v
92
- when Array
93
- "#{k}=#{v.join(",")}"
94
- else
95
- "#{k}=#{v}"
96
- end
97
- }.join(" ")
98
- end
52
+ class Pretty < Base
53
+ def call(severity, time, program_name, message)
54
+ "#{COLORS[severity]} #{time.utc.iso8601(3)} pid=#{::Process.pid} tid=#{tid}#{format_context}: #{message}\n"
99
55
  end
100
56
  end
101
57
 
102
- class Pretty < Base
58
+ class Plain < Base
103
59
  def call(severity, time, program_name, message)
104
- "#{time.utc.iso8601(3)} pid=#{::Process.pid} tid=#{tid}#{format_context} #{severity}: #{message}\n"
60
+ "#{severity} #{time.utc.iso8601(3)} pid=#{::Process.pid} tid=#{tid}#{format_context}: #{message}\n"
105
61
  end
106
62
  end
107
63
 
108
64
  class WithoutTimestamp < Pretty
109
65
  def call(severity, time, program_name, message)
110
- "pid=#{::Process.pid} tid=#{tid}#{format_context} #{severity}: #{message}\n"
66
+ "#{COLORS[severity]} pid=#{::Process.pid} tid=#{tid}#{format_context}: #{message}\n"
111
67
  end
112
68
  end
113
69
 
@@ -120,7 +76,7 @@ module Sidekiq
120
76
  lvl: severity,
121
77
  msg: message
122
78
  }
123
- c = ctx
79
+ c = Sidekiq::Context.current
124
80
  hash["ctx"] = c unless c.empty?
125
81
 
126
82
  Sidekiq.dump_json(hash) << "\n"
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "sidekiq/processor"
4
- require "set"
5
4
 
6
5
  module Sidekiq
7
6
  ##